Adopt existing pdl based pwm driver to support CYT4DN and
adapted the clock implemetation of cyt4dn to this pwm
driver.
Signed-off-by: Alexpandi Muniyandi <alexpandi@linumiz.com>
A zero period used to return -ENOTSUP, so a channel set up once had
no way back -- the pin stayed driven for the life of the instance.
Treat zero period as a release: drop to kFTM_NoPwmSignal, clear
ELSB:ELSA, and forget the saved setup. A zero pulse still means a
constant level, not a release, so a mismatched pulse now fails
-EINVAL instead. The counter keeps running throughout.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
A PWM waveform has no completion event -- nothing bounds how long it
must keep coming out except the consumer asking for something else,
and the system can otherwise idle the FTM mid-drive. A capture is in
the same spot: the busy flag only holds off system PM with
CONFIG_PM_NEED_ALL_DEVICES_IDLE=y, so the SoC could still enter a
state that stops the counter halfway through a measurement.
Hold a power state lock against the node's zephyr,disabling-power-states
for as long as a channel drives or a pair captures, keyed on a held flag
so every path stays balanced. A one-shot capture ends in the ISR, so the
flag sits behind a spinlock. Inert without a declared state.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
The driver only brought itself up once from init(), with no PM
hooks, so the clock and counter kept running through every low
power transition.
Implement all four PM actions: SUSPEND halts the counter, gates the
clock and tears down any capture; RESUME reprograms from scratch and
replays the saved setup. TURN_OFF and TURN_ON are no-ops; RESUME
always follows TURN_ON. Capture is never replayed -- a restarted
counter invalidates it.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
A dual edge capture reads the counter at both edges, so it can't
halt mid-measurement -- but nothing told PM that, leaving a reading
free to be cut in half by a low power transition.
Hold pm_device_busy_set() while a pair is armed, and drop it once no
pair is capturing, checking mcux_ftm_capture_pending() rather than
assuming. The flag is advisory outside CONFIG_PM_NEED_ALL_DEVICES_IDLE=y,
but a capture needs the whole instance left alone.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
CNTIN sits at zero, so a period lasts MOD + 1 ticks, but the driver
loaded the tick count straight into MOD: one tick too long, and 100%
unreachable, since output only holds high the full period once CnV
exceeds MOD -- leaving a one-tick notch at 100%.
Subtract one on both paths that program MOD. The capture path now
rolls over every 0xFFFF ticks, matching the period_cycles it records.
The capture math made the same mistake: it counted each rollover as
MOD ticks, so every overflow between the two edges lost one tick.
Count it as MOD + 1.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
The MCPWM timer period was always applied at once. Shrinking the
period while the timer runs can leave the counter above the new
peak, so it counts up to the 16-bit limit before it wraps and the
output stalls for seconds.
Apply the new period on the next TEZ event once the timer has
been started, as is already done for the compare value. The first
configuration of a timer still takes the period at once.
Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
Since commit a0f307bbcb ("drivers: clock_control: esp32:
initialize the clock tree"), an ESP32-P4 module clock source
stays gated until a driver enables it. The MCPWM driver selects
its source without enabling it, so the first MCPWM register read
in init raises a load access fault on ESP32-P4.
Enable the default MCPWM clock source before selecting it, as the
other Espressif drivers already do.
Assisted-by: Claude:opus-5
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
This commit introduces PM policy state locks
in the RTS5912 driver. It dynamically holds
the lock when the PWM duty cycle is strictly
between 0% and 100%, ensuring the clock
remains active during dimming.
Signed-off-by: Jack Lai <jack_lai@realtek.com>
Signed-off-by: Elmo Lan <elmo_lan@realtek.com>
With CONFIG_PWM_CAPTURE, pwm_stm32_set_cycles() resets the trigger
input to LL_TIM_TS_ITR0 and clears the MSM bit before it enables a PWM
output. LL_TIM_TS_ITR0 is not defined on STM32WBA23/WBA25, which have
no TIM1, or on STM32WB0, and STM32WB0 has no
LL_TIM_DisableMasterSlaveMode(), so the driver fails to build for them.
Skip the trigger reset where LL_TIM_TS_ITR0 is not defined, as the
trigger input is unused while slave mode is disabled, and the MSM reset
on series whose timers have no master mode and hence no MSM bit. Commit
50cd54c80f ("drivers: pwm: stm32: guard slave trigger against missing
LL_TIM_TS_ macros") fixed the same problem for the devicetree slave
trigger.
Fixes#120935
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: YunHung Hua <oliverhua.us@gmail.com>
The PWT reports a partial measurement on the first pulse-width-ready
event after the timer starts: capture is enabled asynchronously to the
input signal, so it can begin mid-pulse and one of the two pulse-width
registers only times a fraction of its phase. Which register is short
depends on the phase alignment at enable time, so single-shot captures
failed intermittently (~80% in CI) and period capture, which needs
both the positive and negative width, failed outright.
Two changes fix this:
- Keep enableFirstCounterLoad disabled (the HAL default). With it set,
the PWT loads that first incomplete measurement, where the negative
pulse width reads ~0 because PWTRDY fires after the first positive
pulse but before a full negative pulse has been timed.
- Track a first_sample flag per capture and drop the first PWTRDY event
in the ISR, reporting the next one instead. The second event always
spans a complete positive and negative phase, so both pulse-width
registers hold full measurements regardless of enable-time alignment.
Verified on FRDM-KE17Z (frdm_ke17z/mke17z7) with a PTB14->PTE11
loopback: tests/drivers/pwm/pwm_loopback now passes all capture
subtests across 6 consecutive runs (previously ~80% probabilistic
failure on the pulse/period inverted subtests).
Fixes#114920
Assisted-by: Vero-Coder:claude-opus-4-8
Signed-off-by: Holt Sun <holt.sun@nxp.com>
Fix K_MSEC and other timing functions and macros being undefined
in the pwm driver when logging is disabled (CONFIG_LOG=n).
Signed-off-by: Camille BAUD <mail@massdriver.space>
As it has been done for STM32MP2X (Copro setup), the STM32MP15
make Zephyr run on Cortex-M4 coprocessor next to Cortex-A7 that
controls timer kernel clocks.
In this condition, the STM32MP15 can also benefit from the
fallback newly done in the driver if only one single clock is
described in the device tree timer node.
Signed-off-by: Erwan SZYMANSKI <erwan.szymanski@st.com>
The ESP32-C5 MCPWM prescaler registers store the programmed
prescaler value minus one.
Increment the group and timer prescaler values before passing
them to the ESP HAL low-level functions. Without this adjustment,
the generated PWM frequency differs from the requested frequency.
Signed-off-by: Yoichi Tachibana <kombunorino2@gmail.com>
On the STM32MP2 the Cortex-M33 only controls the timer gate: the timer
kernel clock is set up by the Cortex-A35 firmware and there is no source
clock to describe. On this series, when a single clock is described,
read the timer clock rate from the gate instead of failing, so such
timers do not need a duplicated clock entry.
Other series keep requiring a source clock and still fail with "Timer
clock source is not specified".
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Jerome LAMY <jerome.lamy@savoirfairelinux.com>
Update extended configuration and replace the FSP start API
with the FSP enable API to align with the MTU module workflow.
Add an explicit `(void *)` cast when assigning the const device pointer to
the FSP context field to avoid the build warning.
Signed-off-by: Duc Bui <duc.bui.vt@bp.renesas.com>
Signed-off-by: Tien Nguyen <tien.nguyen.zg@renesas.com>
Passing a wait of K_NO_WAIT to the pwm_capture_cycles() function causes
the k_sem_take function to return -EBUSY unless the capture has
completed. This condition is not tested for and causes the function
to ignore the error case and allow the function to use capture status
and data values that have not been initialized, reporting success
whenever the data happens to be zero. The capture is also left armed
with a pointer to the stack frame being unwound.
A single capture cannot complete without waiting, so change the
pwm_capture_cycles() function to reject a K_NO_WAIT timeout with -EINVAL
before configuring a capture. Update the API documentation to reflect
this behavior.
Assisted-by: Copilot:claude-opus-5
Signed-off-by: John Batch <john.batch@infineon.com>
z_vrfy_pwm_capture_cycles() left its period/pulse locals uninitialized
and copied them out without consulting the return value.
z_impl_pwm_capture_cycles() leaves both untouched on all of its error
paths, so the values written back were not ones it had set.
Zero-initialize both locals and copy out only on success.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:opus-5
The i.MX PWM block on the i.MX8M family had no Zephyr driver. The
existing `fsl,imx27-pwm` driver covers the same IP but is built on the
legacy device_imx.h HAL, which only supports i.MX6SX and i.MX7D.
Add a driver on top of the MCUX ipwm HAL, binding to `nxp,ipwm`. The
prescaler comes from devicetree and fixes the counter rate reported
by `pwm_get_cycles_per_sec()` polarity is mapped onto `PWMCR.POUTC`.
No interrupt is used, as a single PWMSAR write sustains the output.
`set_cycles()` only guards against a full sample FIFO, returning
`-EAGAIN` rather than blocking the caller. Changing the period or the
polarity stops the counter and drains the FIFO first, since queued
samples no longer match the new configuration.
Signed-off-by: Guilherme Freire <guilherme.almeida@toradex.com>
This commit enables the new clock managers by switching the device
tree to use the new bindings. It also moves some initialization code
from the old clock manager to soc_early_init_hook() since some clocks
configuration needs to be done before the clock drivers are initialized.
Signed-off-by: Martin Hoff <martin.hoff@silabs.com>
Reword PWM driver Kconfig prompts to follow the style guide
from #95132, using the "{Driver Name} PWM driver" format,
following the same pattern as the merged reset (#115694)
and dac (#116400) PRs.
Also fixes a copy-paste bug in Kconfig.xmc4xxx_ccu8,
which incorrectly referenced CCU4 instead of CCU8 in its prompt text.
Part of #7272.
Signed-off-by: Harini G <harinig1818@gmail.com>
CTIMER_SetupPwmPeriod() only rewrites the match registers; it does
not touch TC. Shrinking the period while the timer is running can
leave TC above the new MR[period_channel] value, so the reset-on-
match condition never fires again until TC wraps around 32 bits,
freezing the output for up to 2^32 timer cycles.
Reset the counter whenever the period value actually changes.
Duty-cycle-only updates keep the counter running, so they introduce
no phase discontinuity.
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
Implement the PWM capture API for the NXP eMIOS driver using the
Single Action Input Capture (SAIC) mode.
Three capture API functions are implemented:
- configure_capture: switches the channel to SAIC mode using
both-edge triggering (EDSEL=1). Bit 31 of the A register
(RISING_FALLING_EDGE_MASK) identifies which edge fired, so a
single interrupt path handles all capture type combinations.
This mode uses internal counter with range [0, 0xFFFF] to
maximize the measurement window.
- enable_capture / disable_capture: gate the channel and counter
bus prescalers and the channel FEN interrupt bit.
The ISR (pwm_nxp_emios_isr) reads GFLAG to service all pending
channels efficiently. Per-channel state machine (3 states):
- state 0: wait for first active edge
- state 1: wait for opposite edge (pulse) or next active edge
(period-only)
- state 2: wait for second active edge to close period+pulse
Wrap-around is handled by pwm_nxp_emios_elapsed() by masking
32-bit unsigned subtraction to 16 bits without a conditional
branch.
Signed-off-by: William Tang <william.tang@nxp.com>
Add a new PWM driver for the NXP Enhanced Modular I/O Subsystem
(eMIOS) peripheral, targeting MCX E-series devices.
The driver supports the following PWM output modes:
- OPWFMB: output PWM with Frequency-Modulated Buffered mode,
using the channel's internal counter.
- OPWMB: output PWM with Modulus counter Buffered mode, using
a shared counter bus (A/B/C/D/F) as the period reference.
- OPWMCB (trailing/leading edge): center-aligned PWM with dead
time insertion, using a shared counter bus (A/B/C/D/F) as the
period reference.
The standard pwm_driver_api is implemented:
- set_cycles: dispatches to the per-mode handler based on the
DT-configured mode for each channel.
- get_cycles_per_sec: returns emios_clk / (global_prescaler *
channel_prescaler).
PWM_POLARITY_NORMAL and PWM_POLARITY_INVERTED are both supported.
Phase-shift (OPWMB leading edge offset) is taken from DT.
Signed-off-by: William Tang <william.tang@nxp.com>
Init left each channel's timer in dual 8-bit PWM mode with
timerCompare = 0, always enabled and its output routed to the pin.
Since a FlexIO timer has no start bit, the pin free-ran at
flexio_clk / prescaler / 2 until the first pwm_set_cycles().
Park it disabled with output zero so the pin stays driven low;
pwm_set_cycles() reprograms it anyway.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
match_event is the PWM period event, so the counter overflow
interrupt fires at whatever period the application picked. It was
armed from enable_capture() onwards, and the only place that disables
it is reached after a capture completes. With no signal on the capture
input the capture never completes, so a short PWM period becomes an
unbounded interrupt storm that starves the CPU.
The wrap count is only consumed as a difference between the two
capture edges, so wraps seen before the first edge cancel out. Arm the
interrupt when a first edge is captured and release it once the
measurement is done, tracking the users of the shared event in a
bitmask.
Reproduced on lpcxpresso55s36/lpc55s36 with the loopback jumper
removed: the suite hung at test_capture_busy with the core stuck in
the SCT0 ISR, and completes with this change.
Fixes: #117696
Assisted-by: Claude:claude-opus-5
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
A 0% duty cycle leaves the pulse match at 0 while the period match
still sets the output. As that match is also the counter limit it fires
every period, producing a one tick pulse instead of the constant
inactive level the PWM API requires of a zero length pulse.
The existing static level path was guarded by configured_chan == 1, which
missed a channel being configured for the first time and any case with
several channels active. Detach the output from its events and drive it
directly instead, after the normal channel setup has run.
Measured on lpcxpresso55s36/lpc55s36: an 889 ns pulse every 88.9 us before,
no transitions over 1 s after.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
Two-line copyright notices were wrapped in the SPDX "<text>...</text>"
construct, which is only valid in an SPDX document, not a file header.
The REUSE tool then folds the literal "<text>" into the holder name
and drops the second line from the SBOM.
Remove the markers and tag the continuation line. Holder, year and
e-mail are left unchanged; only the syntax is fixed.
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
Added pm_action suspend/resume/turn_on routine for PWM
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Richard Mc Sweeney <Richard.McSweeney@infineon.com>
Generates periodic CNV trigger pulses at a configurable rate and duty
cycle to drive ADC conversions, exposed through the standard Zephyr PWM
API. Supports both v1 and v2 register layouts.
CONFIG_PWM_ADI_AXI_PWMGEN is auto-selected when
DT_HAS_ADI_AXI_PWMGEN_ENABLED.
Signed-off-by: Iustin Stolniceanu <iustin.stolniceanu@analog.com>
pwm_resume applies the pinctrl from devicetree, sets the gpio to the
idle value, respecting the nordic,inverted flag in the pinctrl nodes.
However, the IDLEOUT register is not set on socs which include this
register. The IDLEOUT register takes precedent over the GPIO setting,
it must thus be set to match the pin polarity, otherwise glitches
will be observed when PWM goes idle, see issue #114343.
This commit adds setting the channel idle state as part of pwm_resume.
An nrfy function is used since the nrfx_pwm driver sets this idle
states on nrfx_pwm_init, which is run before pinctrl is set, and thus
before the driver is able to get the nordic,inverted setting, since
it reads this by reading the pin out setting set by pinctrl.
Signed-off-by: Bjarki Arge Andreasen <bjarki.andreasen@nordicsemi.no>
The mux subsystem redefines the "nxp,inputmux" binding as a mux
controller (#mux-control-cells / #mux-state-cells). The SCTimer PWM
capture path still programmed the INPUTMUX directly through the
fsl_inputmux HAL using two parallel "input-channels" /
"inputmux-connections" arrays, so on SoCs that expose the mux
controller node the two models conflicted. Move SCTimer capture onto
the generic mux model:
- nxp,lpc55S3x: add the INPUTMUX mux controller node (disabled by
default) so capture consumers can reference it; enabled per board.
- nxp,sctimer-pwm.yaml: drop the input-channels / inputmux-connections
arrays and include mux-consumer.yaml; the capture routing is now a
single "mux-states" phandle-array carrying <&inputmuxN index
connection>.
- pwm_mcux_sctimer: drop the direct fsl_inputmux HAL calls and apply
the routing through mux_state_apply(), guarded by device_is_ready().
The mux controllers init at priority 40, before PWM at 50, so they
are ready at SCTimer init time.
- Migrate the lpcxpresso55s36 pwm_loopback overlay to the mux-states
syntax and enable the INPUTMUX node.
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
The mux subsystem redefines the "nxp,inputmux" binding as a mux
controller (#mux-control-cells / #mux-state-cells), which collided with
the previous ctimer PWM-capture use of the same compatible through a
"specifier-space: inputmux" phandle-array. Reconcile the two by moving
ctimer PWM capture onto the generic mux model:
- nxp,mcxa153: switch the inputmux node from #inputmux-cells to
#mux-control-cells / #mux-state-cells.
- nxp,ctimer-pwm.yaml: drop the local inputmux-connections property and
include mux-consumer.yaml; routing is now described with "mux-states".
- pwm_mcux_ctimer: drop the direct fsl_inputmux HAL calls and apply the
routing through mux_state_apply() guarded by device_is_ready(). The
route is applied when capture is configured, where all devices are
ready. Update the test overlay to the mux-states syntax.
Signed-off-by: Felix Wang <fei.wang_3@nxp.com>
Use #include <> instead of #include "" to include a header file which path
is not relative to the directory path of the file emitting the #include
directive.
This change was made running scripts/check_quoted_includes.py script
proposed in https://github.com/zephyrproject-rtos/zephyr/pull/112135
with Linux shell commands like the one below and manually selecting the
applicable changes: only those located in drivers/ since soc/, boards/,
samples/ and tests/ content related to Espressif is addressed in
pull request https://github.com/zephyrproject-rtos/zephyr/pull/112190.
$ ./scripts/check_quoted_includes.py -w \
`./scripts/get_maintainer.py list "Espressif Platforms"`
Also update drivers/clock_control/clock_control_esp32_priv.h that was
not listed by './scripts/get_maintainer.py list "Espressif Platforms"'.
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
num_channels is a count and channels are used as 0-based CC indices,
but both guards used '>', letting channel == num_channels index one
element past the valid range. Use '>='.
Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Valid channels are 0 to MAX31790_CHANNEL_COUNT - 1, but both checks
used '>', accepting channel 6 and addressing registers beyond the
per-channel ranges. Use '>='.
Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Adopt mcpwm retention API and attach sleep retention modules to
effectively enable TOP PD power down.
Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
Replace explicit == true/false comparisons with idiomatic boolean
expressions in pwm_siwx91x_set_cycles().
Signed-off-by: Martin Hoff <martin.hoff@silabs.com>
This patch adds PM runtime management for the PWM peripheral. It allows
to block CPU from entering the sleep state when PWM is active.
Signed-off-by: Martin Hoff <martin.hoff@silabs.com>
The z_vrfy_* functions forward parameters to the corresponding z_impl_*
with identical casts — (const struct device *)dev and (uint64_t *)cycles
— that are redundant since the variables already have those types. Drop
the casts to let the compiler type-check the arguments unobstructed.
Signed-off-by: Flavio Ceolin <flavio@hubble.com>
This patch adds driver support for TI ECAP module which can capture an
external input or work as a standalone APWM generator.
Signed-off-by: Amneesh Singh <amneesh@ti.com>
Add interrupt-driven PWM event callback functionality to the TI AM3352
EHRPWM driver. Note that only one event can be enabled at a time, hence we
require all callbacks to have same event trigger or none at all.
Signed-off-by: Amneesh Singh <amneesh@ti.com>