Brijesh-Thakkar opened a new pull request, #20842:
URL: https://github.com/apache/nuttx/pull/20842

   **Title:** drivers/serial/uart_16550: Add hooks for board-defined UART ports 
(stage 1)
   
   *Refs #18895 (does not fix it, stage 2 follows).*
   
   ## Summary
   
   Issue #18895 asks for the 16550 driver to be usable from board code: register
   as many UARTs as needed, control interrupt registration, and define board
   Kconfig for the active ports.  This is stage 1 of a staged approach.  It adds
   the small building blocks that a board needs and changes nothing for existing
   users.  The object model (a `struct u16550_port_s` with a 
`u16550_dev_init()`,
   shaped like the one in the PL011 refactor, #18837) and board migrations come
   in stage 2, so this PR does not close the issue.
   
   The hooks have no in-tree user in this PR by design, to keep it reviewable
   and regression-free. Stage 2 adds `struct u16550_port_s` and a board user, 
and
   #19478 (RK3506) can drop its console accessor and hard-coded LSR polling
   by using `irq < 0` + `u16550_rxpoll()`. If you prefer, I can fold stage 2 
into
   this PR instead.
   
   What is added:
   
   1. **`g_u16550_ops` is always built and exported.**  The default
      getreg/putreg/isr ops used to be `static` and compiled only if one of
      `CONFIG_16550_UART0..3` was set, so a board with no static UART (or the
      PCI driver alone) could not reuse them.  They are now declared in
      `uart_16550.h`.
   2. **Optional `attach` / `detach` members in `struct u16550_ops_s`.**  If 
NULL
      (every existing user), `u16550_attach()` / `u16550_detach()` do exactly 
what
      they did before (`irq_attach()` + `up_enable_irq()`, and
      `up_disable_irq()` + `irqchain_detach()`).  A board can supply its own, 
for
      example for an IRQ shared with another UART.
   3. **`irq < 0` means "no interrupt".**  The default attach/detach then skip 
the
      interrupt controller and `txint()` sends by polling, like
      `CONFIG_16550_POLLING`.  This is an opt-in for board-defined ports; ports
      configured through Kconfig always have `irq >= 0`.
   4. **`u16550_rxpoll(FAR uart_dev_t *dev)`.**  If LSR.DR is set it calls
      `uart_recvchars()`, as the RX interrupt would.  A board whose RX interrupt
      cannot be used can poll with it instead of reaching into the driver (for
      example with a console accessor and a hard-coded LSR address).
   5. **`uart_pci_16550`: fail the probe when no IRQ is available.**
      `pci_get_irq()` can return a negative errno (e.g. `-ENOTSUP`) and it was
      stored unchecked.  With item 3 that value would have turned a loud
      `irq_attach()` failure at `open()` into a silently polled port, so the
      probe now fails with the error instead.
   6. **Hooks are compiled out unless needed.**  Items 2 and 3 are only active
      with the new hidden option `CONFIG_16550_PORT_HOOKS` (default n, no 
prompt),
      which a board that defines its own ports selects.  Without it two small
      macros make the compiler drop that code, with no `#ifdef` at the branch
      sites.
   
   Commits (each builds on its own):
   
   ```
   drivers/serial/uart_16550: Always build the default ops
   drivers/serial/uart_16550: Add optional attach/detach ops
   drivers/serial/uart_16550: Allow UARTs without an interrupt
   drivers/serial/uart_16550: Add u16550_rxpoll()
   drivers/serial/uart_pci_16550: fail probe when no IRQ is available
   drivers/serial/uart_16550: Compile out the port hooks unless selected
   ```
   
   ## Impact
   
   - **Users / boards:** none.  No defconfig, board or arch file is changed.
     `u16550_earlyserialinit()` / `u16550_serialinit()`, `u16550_bind()` and all
     existing symbols keep their signatures and behavior.  The only Kconfig
     change is the new hidden `16550_PORT_HOOKS`; the `savedefconfig` output of
     every defconfig that uses the driver is unchanged.
   - **API:** additive only: `g_u16550_ops`, `u16550_rxpoll()`, and two new
     trailing members of `struct u16550_ops_s`.  Code that initializes
     `u16550_ops_s` with designated initializers (as the in-tree PCI driver 
does)
     is unaffected; positional initializers would need the two new members.
   - **PCI:** the only behavior change.  A PCI UART whose controller cannot
     provide an IRQ (`pci_get_irq() < 0`) now fails the probe instead of being
     registered and failing at `open()`.  A port with no usable IRQ could not be
     opened before either (the console would have failed to open), so no working
     configuration is affected.
   - **Size** (this PR vs `master` `d0886af95d`, GCC 15.2, default flags of each
     defconfig, whole image `text+data+bss`):
   
     | Config | Image | `uart_16550.o` text |
     |---|---|---|
     | qemu-intel64:nsh | 8807937 -> 8807969 (**+32 B**) | 2607 -> 2764 |
     | qemu-i486:nsh | 485177 -> 485337 (**+160 B**) | 2602 -> 2739 |
     | qemu-intel64:nsh_pci | 8774525 -> 8774561 (+36 B) | 2308 -> 2458 |
     | qemu-intel64:nxterm | 30243123 -> 30243223 (+100 B) | 3761 -> 4016 |
   
     Without option 6 the growth was +128 B / +372 B for the first two rows.  
What
     remains is the two extra pointers in each ops table and the new
     `u16550_rxpoll()`, which the linker drops where unused sections are
     collected (the intel64 images).
   - **Documentation:** the 16550 driver has no documentation page.  The new
     API is documented in `uart_16550.h`.  Stage 2 should add one.
   - **Security / build process:** none.
   
   ## Testing
   
   **Testing was done on QEMU only.  I have no real 16550 hardware, so none of
   this has run on a real board.  Maintainers and users with 16550 boards (and
   AX99100 PCI cards) are asked to test it.**
   
   **Host:** Ubuntu 26.04, Linux 7.0.0-38, x86_64, GCC 15.2.0, QEMU 10.2.1 with
   KVM (`-cpu host -enable-kvm`), `tools/configure.sh` + `make`.  Baseline is
   `master` at `d0886af95d`; the runtime results were produced on the baseline
   and on this branch with the same procedure and compared.
   
   **Build** (no new warnings): qemu-intel64 `nsh`, `nsh_pci`, `nsh_pci_smp`,
   `knsh_romfs_pci`, `ostest`, `nxterm`; qemu-i486 `nsh`.
   `tools/checkpatch.sh -m -g d0886af95d..HEAD`: all checks pass.
   
   **Runtime (QEMU)**: NSH prompt, typed input (RX, typed character by
   character), long TX (`help`, `cat /proc/meminfo`), `ls /dev`:
   
   | Config | Console | Result (baseline / this PR) |
   |---|---|---|
   | qemu-intel64:nsh | COM1, 16550 (port I/O) | pass / pass |
   | qemu-i486:nsh | COM1, 16550 | pass / pass |
   | qemu-intel64:nxterm | QEMU `pci-serial` (PCI 16550), serial NSH fallback | 
pass / pass |
   | qemu-intel64:ostest | COM1 | ostest exits 0 / ostest exits 0 |
   
   `nsh_pci`, `nsh_pci_smp` and `knsh_romfs_pci` target an AX99100 card
   (vendor `0x125b`, device `0x9100`) and cannot be booted under QEMU, whose
   `pci-serial` has a different id; they were only built.  The PCI driver was
   exercised through `nxterm`, which uses wildcard PCI ids.
   
   Excerpt (this PR, `nxterm`, PCI console):
   
   ```
   pci_u16550_register: Register /dev/ttyS0
   ...
   /dev:
    console
    null
    pci
    ptmx
    random
    telnet
    ttyS0
    urandom
    zero
   ```
   
   **Kconfig:** `olddefconfig` + `savedefconfig` round trip on all 77 defconfigs
   that mention `CONFIG_16550_`: output identical to the baseline run (74 files
   unchanged; 3 files differ from their committed defconfig by
   `CONFIG_EXAMPLES_POPEN` in both runs, an apps-tree version mismatch of my
   local checkout, unrelated).
   
   **Syntax-only (clang 21, `-fsyntax-only`)** of `uart_16550.c` and the arch
   serial file for: rv-virt (rv32, rv64), canmv230 (k230), pocketbeagle2
   (am62x), orangepi-5-pro (rk3588), avaota-a1 (a527), t3-gem-o1 (am67),
   csk6011a-nano, moxa: no errors and no new warnings.  `uart_16550.c` was also
   syntax-checked with `CONFIG_16550_PORT_HOOKS` forced on (x86_64).
   
   **Not tested:**
   
   - Any real hardware: all runtime tests are QEMU.
   - Boot of RISC-V (rv-virt, k230, jh7110, ...), arm64 (am62x, rk3588, a527),
     Arm (am67, csk6, moxart), MIPS and OR1K 16550 users: compile-checked only.
   - AX99100 hardware.
   - `CONFIG_16550_UARTn_DMA` configurations.
   - The new hooks (`attach`/`detach`, `irq < 0`, `u16550_rxpoll()`) are not 
used
     by any in-tree board yet and are compiled out in every existing
     configuration, so the runtime tests above show "no regression", not the new
     behavior.  Stage 2 will exercise them.
   
   ## AI assistance
   
   This change was developed with Claude Code (`claude-sonnet-5-5`).  Every
   commit carries an `Assisted-by:` field as required by CONTRIBUTING.md.  I
   reviewed the diff and certify the DCO with my `Signed-off-by`.  The design
   follows the discussion in #18895 and the review of #18837.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to