Skip to content

arch/arm/am67: Add EPWM0/EPWM1 PWM lower-half driver - #20137

Draft
gemstonedevteam wants to merge 7 commits into
apache:masterfrom
t3gemstone:am67-pr-05
Draft

gemstonedevteam wants to merge 7 commits into
apache:masterfrom
t3gemstone:am67-pr-05

Conversation

@gemstonedevteam

Copy link
Copy Markdown

Opening as draft since this depends on #20136 will mark ready once that lands.

Summary

  • Adds a PWM lower-half driver for the AM67 EPWM instances, covering both
    output channels (EPWMxA and EPWMxB) of EPWM0 and EPWM1.
  • The time-base is clocked from the EPWM functional clock, period in TBPRD
    and duty in CMPA/CMPB, with the action-qualifier configured for standard
    edge-aligned output: set on zero, clear on compare.
  • The CTRL_MMR EPWM clock enables are unlocked once during board bring-up
    before any instance is configured.
  • t3-gem-o1 registers EPWM0 as /dev/pwm0 and EPWM1 as /dev/pwm1, with
    CONFIG_PWM_NCHANNELS=2 so both channels are reachable through one device.

Impact

  • Is new feature added? YES — PWM support for AM67.
  • Impact on user? NO — new driver, opt-in by Kconfig.
  • Impact on build? NO.
  • Impact on hardware? YES — arch/arm/am67 and board t3-gem-o1.
  • Impact on documentation? YES — provided in this PR (second commit).
  • Impact on security? NO.
  • Impact on compatibility? NO — additive.
  • Anything else? Depends on PRs 3–4.

Testing

Build Host(s): Pardus GNU/Linux 25 (Debian 13 base), x86_64, host gcc 14
Toolchain:     arm-none-eabi-gcc 14.2.1 20241119 (15:14.2.rel1-1)
Target:        arm / TI AM67 (J722S) Cortex-R5F, board t3-gem-o1:nsh
nuttx-apps:    5a7ab4200
Loaded on the main-domain R5F by Linux remoteproc; console on UART-MAIN1.

Testing logs before change: no PWM support on this arch.

The version string in the logs is from the tested build; the commits were
GPG-signed afterwards, which rewrites hashes. The code is unchanged.

Testing logs after change:

make distclean && ./tools/configure.sh t3-gem-o1:nsh && make -j
  -> nuttx ELF 541496 bytes, 0 compiler warnings

Console:
nsh> pwm -p /dev/pwm0 -f 1000 -d 50 -t 1
pwm_main: starting output with frequency: 1000 channel: 1 duty: 00007fff channel: 2 duty: 00007fff
pwm_main: stopping output
nsh> pwm -p /dev/pwm1 -f 1000 -d 50 -t 1
pwm_main: starting output with frequency: 1000 channel: 1 duty: 00007fff channel: 2 duty: 00007fff
pwm_main: stopping output
nsh>

Test plan result:
console_alive            PASS  prompt responsive
version                  PASS  NuttX version 0.0.0 d4055f59a2 Sep 10 2026 13:48:45 t3-gem-o1:nsh
procfs                   PASS  procfs readable
tasks                    PASS  2 task lines
dev_nodes                PASS  all expected nodes present
pwm_pwm0                 PASS  /dev/pwm0 1 kHz / 50% for 1 s
pwm_pwm1                 PASS  /dev/pwm1 1 kHz / 50% for 1 s

PASS=7

Measured time base, captured 2026-09-11. The log above only shows the ioctl
returning; this reads the registers back from the A53 over /dev/mem while
NuttX is driving the output.

NuttX:  nsh> pwm -p /dev/pwm0 -f 1000 -d 50 -t 25 &

A53, while that is running (32-bit reads: the peripheral returns 0 for an
8-bit access, so the 16-bit registers are taken as halves of a word):

  0x23000000 = 67640        -> TBCTL = 0x0838
  0x23000008 = 4095981386   -> TBCNT = 46922, TBPRD = 62499
  0x23000010 = 2047934464   -> CMPA  = 31249

  TBCTL 0x0838: HSPCLKDIV field 0 -> divider 1, CLKDIV field 2 -> divider 4
  frequency = 250 MHz / (1 * 4 * (62499 + 1)) = 1000.00 Hz
  duty      = 31249 / 62500                   = 49.998 %

  TBCNT sampled twice 0.4 s apart: 62272 -> 61319, so the time base is
  clocked and running, not merely loaded.

/dev/pwm1 at 0x23010000 reads identically: TBCTL 0x0838, TBPRD 62499,
CMPA 31249 -> 1000.00 Hz, 49.998 %, TBCNT 46456 -> 8224.

CTRLMMR_EPWM_TB_CLKEN (0x00104130) = 0x5, so the EPWM0 clock gate the
driver opens during bring-up is in fact open.

PR verification Self-Check

  • This PR introduces only one functional change.
  • I have updated all required description fields above.
  • My PR adheres to Contributing Guidelines and Documentation.
  • My PR is still work in progress (not ready for review).
  • My PR is ready for review and can be safely merged into a codebase.

halak0013 and others added 7 commits September 10, 2026 15:43
Adds the AM67 GPIO lower half and a polled MCU_MCSPI0 master driver, with the
pad configuration both need.  The K3 instance is not the OMAP2 layout: an HL
header block precedes the functional registers.

Chip select is released only after CHSTAT.EOT, since a high SCLK otherwise
drops it mid-word and truncates the write, and CHCTRL.EN stays asserted between
transfers.

t3-gem-o1 registers /dev/spi0 for its ICM-20948 (CS3) and LPS22DF (CS1), and
raises NSH_MAXARGUMENTS to 16 so the spi tool can address a device.

Verified on t3-gem-o1: WHO_AM_I reads 0xEA on CS3 and 0xB4 on CS1, and the
ICM-20948 streams continuous accelerometer samples over the bus.

Co-authored-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
Assisted-by: Cursor
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
Add a Peripheral Support section to the board page listing the GPIO and
MCU_MCSPI0 drivers, and replace the "UART console only" warning on both
the chip and board pages -- it no longer describes the port.  The
replacement states what actually constrains the port: NuttX runs on the
R5F under RemoteProc and depends on the bootloader or Linux Device
Manager having powered and clocked the peripherals, because there is no
TISCI client yet.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
Adds an I2C master driver for the AM67 I2C instances, completing transfers on
ARDY as the K3 controller signals.

Bring-up is deferred to the first transfer, because the Linux Device Manager
enables the I2C clocks late and touching the bus during early board init is not
safe here.  The last reference drop clears the flag so the next transfer
re-initialises the hardware.

t3-gem-o1 registers WKUP_I2C0 as /dev/i2c2.

Verified on t3-gem-o1: i2c dev finds 0x30, 0x40, 0x51 and 0x68, the RTC at
0x68 reads a ticking BCD seconds register, repeated reads are consistent, and
NACK recovery returns the bus to a usable state.

Assisted-by: Claude Code:claude-fable-5
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
Record the WKUP_I2C0 master in the board's Peripheral Support list.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
Adds a PWM lower-half for EPWM0 and EPWM1, covering both output channels of
each.  The CTRL_MMR EPWM clock enables are unlocked once during board bring-up.

t3-gem-o1 registers /dev/pwm0 and /dev/pwm1 with PWM_NCHANNELS=2.

Verified on t3-gem-o1: all four outputs (EPWM0 A+B, EPWM1 A+B) drive physical
pins, jumpered into a Linux GPIO input -- 50% and 20% duty read back at the
expected sample ratios, and gpiomon timed a 50 Hz half-period at 9.998-10.002
ms.  examples/pwm starts and stops a 1 kHz train cleanly.

Assisted-by: Claude Code:claude-fable-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
Record the EPWM0 and EPWM1 outputs in the board's Peripheral Support
list.

Assisted-by: Claude Code:claude-opus-5
Signed-off-by: Ulaş Sertan Kemeç <sertan.usk@gmail.com>
arch/arm/am67: Add EPWM0/EPWM1 PWM lower-half driver.
@github-actions github-actions Bot added Area: Documentation Improvements or additions to documentation Arch: arm Issues related to ARM (32-bit) architecture Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces. Board: arm labels Sep 14, 2026
@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Area: Documentation Improvements or additions to documentation Board: arm Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants