Commit graph

63427 commits

Author SHA1 Message Date
dechao_gong
16632c7d55 boards/arm/rtl8730e: commit platform_autoconf.h for CI
platform_autoconf.h is a hand-maintained minimal header that provides the
SDK #defines required by the fwlib sources compiled during PREBUILD.  Unlike
the other Ameba ICs (which use ameba_gen_autoconf.sh to regenerate it from
SDK menuconfig), RTL8730E uses a static file because the amebasmart SDK
does not ship a pre-generated autoconf and running menuconfig in CI is not
feasible.

The file was previously gitignored along with all other prebuilt/ artifacts,
so CI had no platform_autoconf.h on a clean clone, causing:
  fatal error: platform_autoconf.h: No such file or directory

Fix: add !platform_autoconf.h exception to prebuilt/.gitignore and track
the file in git.  Local clean build verified (nuttx.bin 550 KB generated).

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
Assisted-by: Claude <noreply@anthropic.com>
2026-09-21 18:43:22 +08:00
dechao_gong
0c3839973b arch/arm/ameba: fix CI failures in RTL8730E port
Two CI issues in the RTL8730E (AmebaSmart CA32) port:

1. PREBUILD used $(ARCHOPTIMIZATION) which injects --param=min-pagesize=0
   on GCC>=12.  arm-none-eabi-gcc in CI does not recognise this flag.
   Fix: replace $(ARCHOPTIMIZATION) with explicit -Os -ffunction-sections
   -fdata-sections in both the fwlib and wifi PREBUILD loops, matching the
   pattern already used by the other Ameba ICs (rtl8721dx/8720f/8721f).

2. boards/arm/rtl8730e/rtl8730e_evb/configs/nsh/defconfig was out of sync
   with `make savedefconfig` output (missing CONFIG_ARCH_CHIP_RTL8730E_CA32,
   wrong ordering of several NETUTILS options, and redundant entries that
   are auto-selected by Kconfig).  Regenerated with olddefconfig+savedefconfig.

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
Assisted-by: Claude <noreply@anthropic.com>
2026-09-21 18:43:22 +08:00
dechao_gong
d8224051e7 arch/arm/ameba: fix nxstyle and cmake-format issues in RTL8730E port
Fix all nxstyle and cmake-format violations found by CI checkpatch:

- tools/nxstyle.c: add whitelist entries for SDK mixed-case symbols
  (CPU_, Diag, TRNG_, System_, vPort) used in amebasmart stubs
- arch/arm/src/rtl8730e/rtl8730e_serial.c: fix block comment lengths,
  long lines (replace Unicode arrows with ASCII), align inline comments
- arch/arm/src/rtl8730e/rtl8730e_flash_stubs.c: fix long lines and
  missing blank line after declaration
- arch/arm/src/rtl8730e/rtl8730e_wifi_stubs.c: rename nDeviceId to
  device_id, add Public Functions section header
- arch/arm/src/rtl8730e/rtl8730e_memorymap.h: fix block comment lengths
  and inline comment column alignment
- arch/arm/src/rtl8730e/hardware/rtl8730e_loguart.h: wrap long comment
- arch/arm/src/common/ameba/ameba_os_wrap.c: add missing blank lines
  after declarations
- boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_bringup.c: add missing
  blank line after extern declaration
- arch/arm/src/rtl8730e/CMakeLists.txt: apply cmake-format
- boards/arm/rtl8730e/rtl8730e_evb/src/CMakeLists.txt: apply cmake-format

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
2026-09-21 18:43:22 +08:00
dechao_gong
080e3b3539 Documentation/platforms/arm/rtl8730e: add RTL8730E documentation
Add SoC-level and board-level RST documentation for RTL8730E:

- SoC doc: highlights, ATF boot chain, memory map, vendor SDK info,
  build/flash commands, and supported features
- Board doc: rtl8730e_evb features, nsh configuration guide,
  Wi-Fi STA/AP commands, SMP verification, and license exceptions

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-21 18:43:22 +08:00
dechao_gong
1f819e5b4b boards/arm/rtl8730e: add rtl8730e_evb board support
Add the rtl8730e_evb (RTL8730E Evaluation Board) with an nsh configuration
that demonstrates the RTL8730E baseline feature set:

- Dual-core SMP (CONFIG_SMP=y, CONFIG_SMP_NCPUS=2)
- Wi-Fi station and SoftAP via wapi
- DHCP client (wlan0) and DHCP server (wlan1/AP mode)
- littlefs persistent storage at /data on SPI NOR flash
- iperf2 TCP/UDP throughput measurement
- NSH console over the LOG-UART

Board formerly named ca32-evb; renamed to follow the rtlXXXX_evb
convention used by all other Ameba boards.

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-21 18:43:22 +08:00
dechao_gong
c4ddd5add7 arch/arm/ameba: implement CMake build for RTL8730E (AmebaSmart CA32)
Replace the CMake skeleton with full SDK build machinery, mirroring
the make-side ameba_board.mk.  RTL8730E differs from the KM4-based
ICs in three ways that prevent a direct include(ameba_board.cmake):
- No SDK autoconf / image2 ldscript generation: the board uses its own
  dramboot.ld and a static prebuilt platform_autoconf.h
- No NP firmware build: KM0/KM4 are prebuilt blobs in prebuilt/
- No -mcmse: CA32 is ARMv7-A, not Cortex-M33; uses -DCONFIG_ARM_CORE_CA32

The ameba_build_lib() helper (adapted from ameba_board.cmake) compiles
SDK sources with an isolated flag set into libameba_fwlib.a and
libameba_wifi.a, avoiding NuttX header conflicts.

Key additions:
- libameba_fwlib.a: arch.c + log.c + sscanf_minimal.c always; IPC for
  WiFi/FlashFS; ameba_flash_ram.c for FlashFS
- lib_rom.a linked for GPIO or FlashFS (GPIO_Init, Pinmux_Config, etc.)
- libameba_wifi.a + prebuilt WHC host libs for WiFi
- VFS1 geometry extracted from platform_autoconf.h via
  target_compile_definitions (set_property(SOURCE) has scope issues in
  NuttX's include()-based CMake structure)
- `flash` target calls ameba_smart_flash.sh

Verified: gpio (1186 targets) and nsh (1530 targets) configs both
build cleanly; /data mounts at correct 2 MB partition size.

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-21 18:43:22 +08:00
dechao_gong
4416660ce2 arch/arm/ameba: enable SMP on AmebaSmart CA32 (RTL8730E)
RTL8730E has dual Cortex-A32 cores (CA32) in the AP domain.  Core1 is
powered off by default and requires an explicit HSYS power-on sequence
before ATF SP_MIN can service the PSCI CPU_ON call.  Without it, SP_MIN
writes the entry point to the mailbox and times out waiting for Core1 to
poll it.

Add rtl8730e_core1_power_on() that mirrors SDK smp.c:rtk_core1_power_on():
assert reset, assert isolation, two-stage power-on with up_udelay() for
correct 50/50/500/50 us timing, then release isolation and reset.  Call it
from up_cpu_start() before psci_cpu_on().

Enable CONFIG_SMP / CONFIG_SMP_NCPUS=2 / CONFIG_ARM_PSCI in the nsh
defconfig.

Enabling SMP also exposed a latent WHC skb alignment bug: the Realtek
WHC WiFi driver keeps the AP/NP DDR views coherent with by-VA
DCache_Clean/Invalidate at SKB_CACHE_SZ (64 on RTL8730E) granularity,
which requires every skb buffer to be cache-line aligned.  The port had
omitted CONFIG_MM_DEFAULT_ALIGNMENT (defaulting to 8; the 8721Dx parts
set 32), so heap-allocated skb buffers were unaligned and the cache
maintenance spilled onto the neighbouring skb struct, corrupting its
immutable buf pointer (seen as skb->buf = 0x05 and a TX memcpy data
abort on "renew wlan0").  This was harmless on single core -- the
non-shareable DDR mapping made the stray maintenance a no-op -- but the
SMP shareable mapping plus real dual-core concurrency turned it into a
hard fault.  Set CONFIG_MM_DEFAULT_ALIGNMENT=64 in the nsh defconfig.

Hardware verified on RTL8730E (C-cut): /proc/cpuinfo shows both processor 0
and processor 1; getprime 2 completes two concurrent threads in ~573 ms
(same as single-thread), confirming true parallel execution across both cores.
"renew wlan0" now obtains a DHCP lease (192.168.1.101) without faulting.

Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
2026-09-21 18:43:22 +08:00
dechao_gong
7b5861122f arch/arm/ameba: use the real efuse WiFi MAC on AmebaSmart
On AmebaSmart the standard WHC_API_WIFI_GET_MAC_ADDR pull API times out:
the KM4 NP firmware snapshot linked into this image does not register a
handler for it, so wifi_get_mac_address() blocks ~12s per call and cannot
be used to fill the netdev MAC.

The NP does, however, PUSH its real efuse MAC to the host at wifi-on time
via WHC_API_SET_NETIF_INFO, which lands in the host-side
lwip_wlan_set_netif_info() glue.  Previously that glue discarded the
address and ameba_wifi_get_mac() synthesised a random locally-administered
MAC, which then diverged from the MAC the NP actually associates with (the
NP's 802.11 RX filter drops unicast frames addressed to the random MAC, so
DHCP OFFERs never arrive).

Cache the pushed efuse MAC in lwip_wlan_set_netif_info() and return it from
ameba_wifi_get_mac(); the random MAC remains only as a fallback for the
window before the NP has pushed.  ameba_wifi_connect() then mirrors it to
the NP with wifi_set_mac_address() so both sides agree.  The per-IC guard
uses CONFIG_AMEBASMART, not CONFIG_ARCH_CHIP_RTL8730E: these files are
compiled by the board PREBUILD step with the vendor SDK autoconf, where
NuttX Kconfig symbols are invisible.  The other Ameba parts keep their
working GET_MAC efuse path unchanged.

Verified end to end: ifconfig shows the real Realtek OUI MAC
(00:e0:4c:..), association and DHCP complete in a single round.

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
2026-09-21 18:43:22 +08:00
dechao_gong
f156812c0c arch/arm: add Realtek AmebaSmart (RTL8730E) CA32 support
Add NuttX support for the Realtek AmebaSmart (RTL8730E) running on the
CA32 (Cortex-A32) application core, with the KM4/KM0 cores kept as
vendor firmware (KM4 acts as the WiFi network processor over WHC IPC).

Stage 1 bring-up, hardware verified:

  - CA32 boot / exception vectors / MMU + page allocator / heap
  - LOGUART console (RX via KM0-owned IPC + shared memory)
  - IRQ controller, timer, serial
  - On-chip SPI NOR flash MTD -> littlefs mounted at /data
  - WHC-host WiFi netdev (STA): scan / connect / DHCP, verified end to
    end (association -> 4-way -> DHCP -> ping, bidirectional TCP)

IC-agnostic Ameba glue is shared from arch/arm/src/common/ameba via a
relative VPATH entry (matching the rtl8721dx pattern), which also avoids
the empty mkdeps --dep-path that a leading-":" VPATH entry produced and
which intermittently broke parallel .ddc dependency generation.

The FIP packaging / flash image assembly is driven by
common/ameba/tools/ameba_smart_flash.sh from the board scripts.

Vendor blobs and build artefacts under the board prebuilt/ directory are
kept out of the tree via prebuilt/.gitignore.

Signed-off-by: dechao_gong <dechao_gong@realsil.com.cn>
2026-09-21 18:43:22 +08:00
Justin Hammond
8e05ffaab8 boards/risc-v/eic7700x: Enable the reset procfs entry.
Makes /proc/reset available, so which peripherals are held can be read
while the board is running rather than only for the eight lines the
startup report names.

RESET_PROCFS depends on FS_PROCFS_REGISTER, which neither board set.
Without it the symbol is dropped when the configuration is regenerated
and the entry never appears, which is silent: the defconfig still reads
as though the feature were on.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-21 16:29:12 +08:00
Justin Hammond
a763b873b4 arch/risc-v/eic7700x: Name the reset lines through procfs.
Implements get_line, so /proc/reset names all 324 lines and gives the
register and bit each lives in.  The framework asks status() for the
asserted state.

The names do not survive compilation: they live in the enumeration, so
without a table a listing gives only numbers, and working back from one
to a peripheral means counting through the header.  The table costs
about 8 KiB and is built only when the procfs entry is.

The ids are sparse, 324 lines across a space of 1952, so the table is
sorted by id and searched rather than indexed, and an id naming no line
returns -ENODEV.  The framework skips those, which is what leaves the
listing dense.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-21 16:29:12 +08:00
Justin Hammond
7fe77bf1d7 boards/risc-v/eic7700x: Report the reset lines at startup.
A peripheral held in reset reads like one that is absent, and the boot
loader does not leave the same lines released on every board or every
boot.  One line at startup says how much is held:

  reset: 324 lines, 117 held

Beside the clock tree's line and for the same reason: the summary is
worth seeing on every boot, and the detail belongs in /proc where it can
be read when it is wanted.

The driver's error output is enabled, matching the clock driver.  Info
level is not, since nothing at that level prints on a healthy boot.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-21 16:29:12 +08:00
Justin Hammond
74ac90f692 arch/risc-v/eic7700x: Add the CRG reset controller.
The Clock and Reset Generator holds the reset line for every block on
the SoC.  This registers all 324 of them with the NuttX reset framework
as a provider implementing assert, deassert, reset and status.

A line is addressed as its control register index times thirty two plus
its bit, across 61 registers, so the ids are sparse in a space of 1952
and decoding one is arithmetic rather than a lookup.

Each register carries three masks over the same bits: which bits are
lines at all, which the hardware will not let software drive, and which
would take down the system that asserted them.  The last are still
registered and can be read and released; only assert and reset refuse
them.  Where each line falls, and why, is recorded beside the table.

The lines are active low, which the manual never states.  It is inferred
from the field naming, the reset defaults and both vendor Linux drivers.
If that inference is wrong then deassert asserts, so the evidence for it
is written out in full rather than left as a convention.

Several lines are absent from the manual, the GPIO resets at offset
0x438 among them.  They were recovered from the vendor device tree and
confirmed by asserting each one and watching the block stop responding.

Registration writes nothing to the hardware.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-21 16:29:12 +08:00
dependabot[bot]
650152a72a build(deps): bump docker/setup-buildx-action from 4.3.0 to 4.4.1
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 4.3.0 to 4.4.1.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](37fe631027...f87e5991a6)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-21 16:28:50 +08:00
Ulaş Sertan Kemeç
2cb30ac13d arch/arm/am67: Answer the remoteproc shutdown request in rptun.
The mailbox handler drained the FIFO without checking the message body.
That caused shutdown messages to be lost, hence being unable to start/stop
the R5 cores from the Linux side.

The additions allow checking messages for control and virtqueue types.
Shutdown messages fall to the control branch, which ACKs the shutdown
request and parks the core in WFI.

Virtqueues still work as intended; the only difference is that control
messages are now handled correctly.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-21 16:28:36 +08:00
Ulaş Sertan Kemeç
0fca32a652 Documentation/am67: Document the rptun IPC link on t3-gem-o1.
Record the rptun/rpmsg link to the Linux A53 in the board's Peripheral
Support list.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-21 16:28:36 +08:00
Ulaş Sertan Kemeç
cd4fe549ee arch/arm/am67: Add a RAT sliding window for 36-bit DDR access.
J722S maps DDR above the first 2 GB at 0x8_8000_0000, out of reach of the
32-bit R5F, while a 64-bit Linux peer posts virtio buffers there.

Dedicates RAT region 0 as a 16 MB window at 0xFE000000.  am67_rat_map() re-aims
it and returns a pointer plus the bytes left before the edge, so callers can
split copies that straddle it.

The window is Non-cacheable, since it retargets at runtime and cached lines
would alias across physical blocks.  A mapping is valid only until the next
call; the sole user, vhost-net, is serialised on the netdev work thread.

Assisted-by: Claude Code:claude-fable-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-21 16:28:36 +08:00
Ulaş Sertan Kemeç
a2edd99159 arch/arm/am67: Add rptun IPC with the Linux A53 (remoteproc/rpmsg).
Connects the R5F to Linux remoteproc over the NAVSS mailbox.

The mailbox ISR only drains the FIFO and acknowledges; OpenAMP delivery is
deferred to HPWORK, because the rpmsg rx path takes mutexes and allocates.

The resource table publishes two vdevs, rpmsg and virtio-net, leaving every
vring address FW_RSC_ADDR_ANY: Linux allocates them from the R5F DMA pool and
rejects fixed addresses outside it.

Shared IPC memory is mapped Non-cacheable, since the R5F is not coherent with
the A53 and cached mappings leave NuttX reading stale vring state.

Also drops the duplicate arm_mpu.c from CHIP_CSRCS.

Assisted-by: Claude Code:claude-fable-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
2026-09-21 16:28:36 +08:00
Daniel P. Carvalho
e3dfc9875d arch/arm/stm32h7: timestamp the received PTP frames.
Add STM32_ETH_TIMESTAMP_RX for the STM32H7, as the one of the legacy
STM32 that provides the timestamp of the frames received.

Timestamp the PTP version 2 messages, over Ethernet and over UDP, except
for the announce, management and signaling messages. The MAC writes the
timestamp in a context descriptor after the last descriptor of the frame.
The driver reads it before giving the frame to the network stack and
passes it in d_rxtime, in the time of the system time of the MAC, the same
as /dev/ptp0. A frame that is not timestamped has a time of zero.

The timestamp goes over the address of the buffer of the context
descriptor, and the code that dropped the context descriptors used a
pointer that was never set. Keep the address of the buffer of each RX
descriptor, and restore it when a context descriptor is given back.

The timestamps of the PTP frames of a grandmaster clock were checked on
hardware against the system time of the MAC, and were within the delay of
the reads.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 15:11:15 +08:00
Daniel P. Carvalho
4e6b805a0d Documentation/stm32h7: document the Ethernet PTP clock.
The STM32H7 page did not say anything about the Ethernet MAC.

- Describe the time counter of the MAC, the STM32_ETH_PTP option and its
  behavior when the interface goes down.
- Describe the pulse-per-second output and the pins it can use.
- Describe the /dev/ptp0 clock the driver registers and the operations it
  offers, and show a configuration that enables all of it.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 15:11:15 +08:00
Daniel P. Carvalho
e2d5b8f29c arch/arm/stm32h7: add the PTP hardware clock of the Ethernet MAC.
The MAC has a system time that is the base of the PTP hardware
timestamps, but the driver never started it, and STM32_ETH_PTP only
printed a warning.

Add the registers of the timestamp unit and start the system time with
the fine update method and the digital rollover, so that the nanoseconds
count up to 10^9. The increment is 2 * 10^9 / HCLK ns, and the addend
makes the update rate half of HCLK, which leaves room to trim the
frequency in both directions. The time starts at zero right after the MAC
reset, not with the MAC configuration, so it does not depend on the PHY
having a link. The reset clears it, so it starts again each time the
interface goes up.

With STM32_ETH_PTP_GPIO, start the pulse-per-second output as a pulse
train with a period of one second and a width of half of it, at the whole
seconds of the system time. The fixed frequency mode of the MAC gives a
pulse too short to be seen, so the flexible mode is used. The interrupt
of the timestamp unit is not enabled in the MAC: it is set each time the
target time of the PPS output is reached and is cleared by reading
MACTSSR, which the interrupt handler does not do, so it would stay
pending and keep the handler running until the network stops.

Register /dev/ptp0 when CONFIG_PTP_CLOCK is set, so that a PTP daemon can
read and set the system time and correct its frequency and its phase.
The frequency is corrected by changing the addend, by up to 50% each way.
A step of the time is added or subtracted with the update register; with
the digital rollover a subtraction is programmed with the negated seconds
and with 10^9 minus the nanoseconds. The pulse train counts by itself, so
it does not follow a step of the system time and would be displaced by the
same amount: after the time is set or stepped, it is started again at the
next whole second.

With HCLK at 200 MHz the system time advanced 10.0018 s while a host
clock advanced 10.002 s, and the pulse train was seen on the pin. Reading,
setting, steps of +0.5 s and -1.25 s and a change of 100 ppm were done
through /dev/ptp0 on hardware, and the edges of the PPS output stayed at
the whole seconds of the system time.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 15:11:15 +08:00
Daniel P. Carvalho
8e5e3c081a arch/arm/stm32h7: configure the PPS pin only with STM32_ETH_PTP_GPIO.
The driver configured the pulse-per-second pin whenever STM32_ETH_PTP
was set, so a board that uses the timestamp unit without the pin still
had to define GPIO_ETH_PPS_OUT, and the pin was taken away from other
uses. The STM32F4 driver configures the pin with STM32_ETH_PTP_GPIO,
the option meant for it, but that option could not be selected on the
STM32H7, because it depended on the legacy STM32 families.

Configure the pin only with STM32_ETH_PTP_GPIO, and allow that option
on the STM32H7 and STM32H5.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 15:11:15 +08:00
dependabot[bot]
ef04d315f0 build(deps): bump docker/build-push-action from 7.3.0 to 7.4.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 7.3.0 to 7.4.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](53b7df96c9...c3c9e263c2)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 7.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-21 15:08:43 +08:00
Daniel P. Carvalho
d357c54549 arch/arm/stm32: fix PTP multicast filter and RX/TX frame routing
- Under CONFIG_NET_PROMISCUOUS, forward all control frames
  (ETH_MACFFR_PCF_ALL) instead of only non-PAUSE ones, so link-local
  PTP multicast reaches the DMA.
- Move ptp_to_timespec() above its first user so the TX timestamp path
  can call it.
- stm32_receive(): do not log frames already delivered to packet
  sockets (PTP, IPv6) as "Dropped, Unknown type".
- stm32_txtstamp_flush(): clear io_conn before freeing the looped-back
  IOB.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 15:07:04 +08:00
Daniel P. Carvalho
b850fc0205 arch/arm/stm32: implement hardware TX timestamping via SO_TIMESTAMPING loopback
Implement hardware TX timestamping support for STM32 Ethernet MAC
(stm32_eth_m3m4_v1.c) following the upstream SO_TIMESTAMPING loopback
architecture (PR #20161).

When an outgoing packet is flagged with SO_TIMESTAMPING (dev->d_iob->io_conn != NULL):
- Clone the IOB and hold a reference in priv->txmeta[txindex]
- Set ETH_TDES0_TTSE on the transmit DMA descriptor
- On transmission completion (stm32_freeframe), retrieve the hardware
  timestamp from TDES6/TDES7, convert to timespec via ptp_to_timespec(),
  and enqueue the clone onto priv->txtstampq
- Deliver pending TX timestamp clones back to netdev RX path in stm32_receive
  using pkt_input(), where net/pkt intercepts the frame and delivers it to
  userspace via recvmsg(..., MSG_ERRQUEUE)
- Properly drain pending queues and clones on interface down (stm32_ifdown)

Assisted-by: Gemini:gemini-3.8-pro
Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
2026-09-21 15:07:04 +08:00
Daniel P. Carvalho
c1938018e8 arch/arm/stm32h7: fix the bit of ETH_MTLOMR_DTXSTS.
The Drop Transmit Status field of the MTL operation mode register is
bit 1, but it was defined as bit 0. The driver does not use it.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 15:06:45 +08:00
Matteo Golin
33053669ac docs/pthread: Document pthread_sigqueue
Documents the new implementation of pthread_sigqueue.

Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
2026-09-21 14:53:26 +08:00
Matteo Golin
f39b15d28b sched/pthread: Implement pthread_sigqueue
Implements the pthread_sigqueue Linux extension to pthreads. Follows a
similar implementation to sigqueue, except targeting a specific thread
through nxsig_dispatch.

Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
2026-09-21 14:53:26 +08:00
Daniel P. Carvalho
bda32d3a74 Documentation/ptp: add the existing implementations.
The page described how to write a lower-half driver but did not say
which ones are in the tree.

- List the two lower-half drivers that register a PTP clock, the dummy
  driver and the Ethernet MAC of the STM32, with the option that
  enables each.
- Say that the clock of the STM32 driver is the PTP counter of the MAC,
  which is also the time base of the timestamps of the received
  packets, and not CLOCK_REALTIME.
- Say that both use the device number 0 by default and so cannot be
  registered at the same time.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 14:46:59 +08:00
Daniel P. Carvalho
9d861ca27e arch/arm/stm32h7: wait for the PHY link in milliseconds.
The PHY was polled with nxsched_usleep(100) in a loop of 0x1998
iterations, so the time the link had to come up depended on the period
of the system tick. With the usual 10 ms tick that is about 65 s, but
with CONFIG_SCHED_TICKLESS and a 100 us tick it is about 0.65 s, shorter
than the auto-negotiation of the PHY (about 1.7 s on the board tested),
and the interface could not be brought up.

Poll every 10 ms and give the PHY up to 5 s, both for the link and for
the auto-negotiation to complete, whatever the tick.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-21 14:46:24 +08:00
dependabot[bot]
5beb781f9b build(deps): bump anyio from 4.14.0 to 4.14.2 in /Documentation
Bumps [anyio](https://github.com/agronholm/anyio) from 4.14.0 to 4.14.2.
- [Release notes](https://github.com/agronholm/anyio/releases)
- [Commits](https://github.com/agronholm/anyio/compare/4.14.0...4.14.2)

---
updated-dependencies:
- dependency-name: anyio
  dependency-version: 4.14.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-20 18:04:41 -03:00
Daniel P. Carvalho
d6d06c72ad Documentation/stm32f4: document the Ethernet PTP support.
The STM32F4 page did not say anything about the Ethernet MAC.

- Describe the time counter of the MAC and the options that enable the
  timestamping of received packets, the pulse-per-second output and
  the use of the counter as a high-resolution RTC.
- Describe the /dev/ptp0 clock that the driver registers: the
  operations it offers, the numbering, and that the timestamps of the
  received packets are values of the MAC counter and not of
  CLOCK_REALTIME, so they have to be compared with /dev/ptp0.
- Show how to start ptpd with them and a configuration that enables
  everything above.
- Say that the driver does not timestamp transmitted packets.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-20 18:03:58 -03:00
Daniel P. Carvalho
392107954b arch/arm/stm32: fix the comment of the RX timestamp conversion.
The comment of stm32_eth_ptp_convert_rxtime() said that it converts to
CLOCK_REALTIME. Since the timestamp is delivered as the value of the
PTP counter of the MAC, which is the time base of /dev/ptp0, say
that.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-20 17:54:48 -03:00
Daniel P. Carvalho
f7e3b0fa89 drivers/timers/ptp_clock_dummy: fix the nanoseconds of the monotonic time.
ptp_clock_dummy_getcrosststamp() stored the seconds of the monotonic
clock in the nanoseconds field of the monoraw member, so the
monotonic time of the cross timestamp was wrong. Store the nanoseconds.

Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
Assisted-by: Claude:claude-sonnet-5
2026-09-20 17:54:48 -03:00
Royyan Zahir
abbfb31a02 arch/arm64: implement up_addrenv_va_to_pa().
up_addrenv_va_to_pa() is declared in include/nuttx/arch.h but implemented
only by armv7-a, so no arm64 port can map a virtual address to a physical
one. A driver whose device addresses memory physically has nothing to call.

The translation is asked of the MMU with AT S1E1R rather than walked in
software, so it answers for whatever is actually mapped: any granule size,
block or page, at any level, and it cannot drift from the tables in use.

PAR_EL1 is one register per CPU, so nothing may run between the translation
and reading the result. Interrupts are banked with it, so masking them
locally is sufficient and SMP needs nothing further.

Returns zero for an address that is not mapped for a privileged read, which
is what the declaration in arch.h specifies. Note this differs from the
armv7-a implementation, which returns the virtual address unchanged.

Signed-off-by: Royyan Zahir <royzah@gmail.com>
2026-09-20 11:58:33 -03:00
Arnav Sharma
6cd19e661b docs: document common DMA driver framework
Document the common DMA driver framework and its usage.

Describe the DMA controller and client interfaces, channel and
transfer lifecycle, DMA links, controller implementation
requirements, and existing in-tree users.

Add references to the audio DMA and 16550 UART implementations
to provide concrete usage examples.

Signed-off-by: Arnav Sharma <2006arnavsharma@gmail.com>
2026-09-20 22:29:26 +08:00
yushuailong
a298c1734e sched/irq: Preserve all handlers when extending IRQ chains.
Allocate the new handler node independently of the initial chain
conversion so handlers beyond the second are appended instead of silently
dropped.  Delay vector conversion until both required nodes are available
to avoid leaving a partially constructed chain on allocation failure.

Assisted-by: OpenAI Codex
Signed-off-by: yushuailong <yyyusl@qq.com>
2026-09-20 22:28:55 +08:00
Justin Hammond
c7d6f51b9c drivers/usbhost: Stop retrying an xHCI port that will not enumerate.
xhci_enumerate() reports failure by marking the hub port disconnected,
which is what makes xhci_wait() return and the attempt repeat.  The root
port is still connected, so the two disagree again immediately and the
attempt repeats for as long as the device stays plugged in.  A device that
fails every time is retried forever: 1055 attempts in 90 seconds on an
EIC7700X board, enough console traffic to make the board unusable.

Count consecutive failures per root port and stop at
CONFIG_USBHOST_XHCI_ENUM_RETRIES, leaving the port as it is so xhci_wait()
blocks until something physically changes.  A new connection clears the
count, as does a successful enumeration, so a device needing a second
attempt still gets one.  The default of three rides out a slow device or a
marginal reset.

The same board now makes three attempts, reports that it has given up and
falls silent, while a keyboard on the other port enumerates throughout.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
18c834b7d3 drivers/usbhost: Release the xHCI slot when enumeration fails.
A device slot is a finite controller resource: HCSPARAMS1 reports how many
exist and Enable Slot fails with No Slots Available once they are gone.
Two paths took one and returned without giving it back.

xhci_device_init() enables a slot before initialising the transfer ring,
the slot context and the device address, and each of those returned
directly on failure.  It also treated a slot number larger than the
controller supports as success, since Enable Slot itself had succeeded.

xhci_enumerate() is the larger leak: the device is addressed by the time
usbhost_enumerate() runs, so a device whose descriptor cannot be read, or
that no class driver claims, leaves the slot held.  That path clears
hport->connected so the port is retried, taking another slot each time.

Release the slot on both paths with xhci_device_deinit(), which issues
Disable Slot, clears the DCBAA entry and resets the context.  The endpoint
ring is left allocated; xhci_ring_init() reuses an existing one.

Tested on an EIC7700X board with a device no class driver claims, so the
port retries indefinitely: previously the eighth attempt failed with
completion code 9 and the controller enumerated nothing further on either
port; now 1104 consecutive attempts produced no slot failure.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
fc58227802 drivers/usbhost: Serialise xHCI transfers per endpoint.
xhci_ctrl_xfer() and xhci_transfer() release the controller lock before
xhci_transfer_wait(), so the lock does not cover the interval in which a
transfer is outstanding.  Two threads issuing requests on the same
endpoint both reach xhci_ioc_setup(), and the second trips the
DEBUGASSERT(!epinfo->iocwait) that guards it, or overwrites the first
thread's completion state where assertions are compiled out.

A default control endpoint reaches this readily: every interface driver on
a composite device speaks through endpoint 0, so a two interface HID
keyboard runs two poll threads both issuing GET_REPORT.

Other host controller drivers hold the controller lock across the wait,
which here would serialise the whole controller and give up the per
endpoint rings xHCI provides.  Add a mutex to struct xhci_epinfo_s and
hold that instead.  It is taken before the controller lock on both paths,
so the order is endpoint then controller.

xhci_epfree() also freed the endpoint container without destroying iocsem.
Destroy both.

Reachable on any xHCI controller, independently of the preceding commits.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
a5431319bb drivers/usbhost: Make xHCI asynchronous transfers deliver their data.
Submitting an asynchronous transfer refused any buffer needing a cache
line stand-in, and that test also refuses every buffer whose length is not
a whole number of cache lines, which an interrupt transfer's rarely is: a
HID keyboard reads eight bytes.  Every submission returned -EFAULT before
a descriptor was written, and a class driver resubmitting from its
completion callback never sees a second chance.

The refusal existed because the copy out of a stand-in is done by the
blocked caller, and an asynchronous transfer has none.  The work queue
thread handling the completion will do: a buffer given to DRVR_ASYNCH
comes from DRVR_ALLOC, so it is kernel memory reachable from any thread.
Use the same stand-in machinery as every other transfer and finish the DMA
in the completion, just before the callback.  A cancelled transfer returns
its stand-in on cancellation.

The callback also moves outside the spinlock.  It is class driver code
that queues work and takes its own locks, and it may now free a stand-in.
Whether a completion is synchronous is still decided under the lock, since
a posted waiter may be carrying a new transfer immediately.

The asynchronous setup now records the requested length, as the
synchronous setup does.  The byte count handed to the callback is worked
out from it and the residue, and was previously whatever the endpoint held
from an earlier transfer.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
62a7507427 drivers/usbhost: Check for the device before allocating an endpoint.
A root hub port whose enumeration failed is enumerated again, and the slot
the failed attempt used has been given back by then, so the port has no
device context behind it.  xhci_epalloc() took that pointer and wrote the
new endpoint through it without looking, so the retry stored through NULL
and took the system down in answer to a device that had merely failed to
come up.

Check for the device, and free the endpoint that has no home rather than
leaking it.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
a11cecd100 drivers/usbhost: Convert the xHCI endpoint interval from the descriptor.
The Interval field of an endpoint context is an exponent: the controller
services the endpoint every 2^Interval microframes.  An endpoint
descriptor states its period differently depending on device speed, so the
number cannot be copied across, which is what this did.  A low speed
keyboard asking to be polled every 10ms was programmed as 2^10
microframes, which the controller would not accept: Configure Endpoint
went unanswered and allocation failed with -EIO.

Low and full speed interrupt endpoints state a period in frames, so the
exponent is the highest bit of that period in microframes, clamped to the
range the specification allows.  Other periodic endpoints already state an
exponent, one greater than the one wanted here.  Control and bulk
endpoints are not periodic and the field means nothing to them.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
f8ea0f3d02 drivers/usbhost: Copy an xHCI stand-in buffer in the caller's context.
The copy out of a stand-in was done in the completion handler, which runs
on a work queue, while the buffer it copies into may belong to a user
process whose addresses mean nothing there.  Reading a block device
directly from a user program faulted.  The caller is blocked until the
transfer finishes, so the copy belongs there.

An asynchronous transfer has no blocked caller to come back to, so a
buffer that would need a stand-in is refused for that path.  Its callers
are class drivers using kernel memory, which do not need one.  The
refusal is lifted once the completion path can do the copy itself.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
a4475ca284 drivers/usbhost: Announce what an xHCI port has attached.
Report each device as it comes up, and report it going away.

The announcement is made at the end of the port enable rather than at
connect, because the PORTSC speed field means nothing until the port has
been reset: a USB2 port reports its reset default, full speed, until then,
so every device would be announced at 12Mbps regardless of what it
negotiates a moment later.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
6b24a0cac5 drivers/usbhost: Carry the xHCI transfer chain across the ring join.
A transfer described by more than one TRB can reach the end of the ring
part way through, so the link that sends the controller back to the
beginning falls inside the transfer rather than between two of them.
Written without the chain bit, that link ends the transfer where it
stands: the controller follows it, considers the work finished, and
reports nothing, because the TRB that asked for the completion interrupt
is on the far side of the join.  Nothing waiting is woken, and transfers
have no timeout, so the symptom is a read that never returns.

Carry the chain bit onto the link when the TRB it follows has it.

Reading 1MiB from a USB drive, where the last two sizes did not complete
at all before:

    512 byte blocks     166 KB/s
    4 KiB blocks       1333 KB/s
    32 KiB blocks     10666 KB/s
    64 KiB blocks     15515 KB/s

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
432ef71ed7 drivers/usbhost: Describe devices to an xHCI controller correctly.
What a controller is told about a device before it will accept it.  A DWC3
core validates these where QEMU's controller does not.

- HCCPARAMS1 says whether context structures are 32 or 64 bytes, and the
  wider form was refused outright with -EIO; the EIC7700X reports
  0x0220fe45 on both of its controllers, so this driver could not have
  driven either.  A wide context is the same fields with reserved space
  after them, so only the stride changes.  Read it at start up and use it
  wherever a context array is walked.
- Contexts must be 64 byte aligned, since every device context base
  address array entry points at one, and the output context came from
  kmm_zalloc().
- The slot context never carried the device speed, which has no valid
  zero, so a validating controller answers Address Device with a parameter
  error.  The speed was already implied by the endpoint context's maximum
  packet size.  The numbering is xHCI's own, hence the mapping.
- The output device context was cleared and never flushed.  That context
  is the controller's to write, so what stays behind is a dirty line of
  zeros written back over the slot state, and the next command against the
  slot is refused with a context state error.  Enumeration reached
  SET_ADDRESS and stopped.
- A buffer copied through an aligned stand-in was copied back using buflen,
  which control transfers deliberately leave zero, so a descriptor read
  copied nothing back and the caller was handed whatever its buffer held
  before.  Keep the requested length separately, and maintain the cache
  over the whole stand-in rather than the part in use.
- A buffer the controller cannot reach is now copied through a stand-in
  rather than refused.  -EFAULT works for a caller with somewhere better
  to put the data, and fails outright for one without: reading a block
  device directly from a user program returned an error where the transfer
  could have gone through a stand-in.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
c288d9f9e4 drivers/usbhost: Compute the event ring segment count at full width.
The number of event ring segments a controller allows is a power of two
reported as its exponent, and the exponent can reach 15.  Computing
1 << exponent into the uint8_t that holds it wraps to zero on any
controller offering more than 128 segments, and a controller told its
event ring table holds no entries has nowhere to report anything: every
command times out.

Work it out at full width and narrow afterwards.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
ecbd1870d3 drivers/usbhost: Report which xHCI command was rejected.
A failed command logged only its completion code.  The difference between
a refused Address Device and a refused Evaluate Context is most of the
diagnosis, and the completion code does not give it.

Keep the command type before the result overwrites the TRB, and name it in
the message.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00
Justin Hammond
cf93053f74 drivers/usbhost: Read xHCI HCIVERSION with an aligned access.
The register dump read HCIVERSION with a 32-bit access at offset two.  It
is a 16-bit register sharing a word with CAPLENGTH, so that is an
unaligned read of a device register: harmless where the bus permits it and
a fault where it does not.

Read the word once and take both fields from it.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
2026-09-20 22:28:07 +08:00