Commit graph zephyr/drivers
Author SHA1 Message Date
Anas Nashif
1f4ecea7f6 drivers: timer: cortex_m_systick: keep the drift-comp VAL sample raw
The conversion to the generic timer core had elapsed() return its
SysTick->VAL sample through an out-parameter so that
timer_driver_set_reload() can reuse it gap-free for the drift
compensation. The value handed out was the wrap-realigned one
(0 -> last_load), but the drift-compensation formula operates on raw
register samples: the pre-conversion driver read a fresh raw
SysTick->VAL for it.

When the counter genuinely reads zero, the realigned sample makes the
compensation compute (val1=last_load) - (val2=0) and credit a full
timer period that never elapsed. On hardware VAL==0 is a single-cycle
transient, but QEMU's SysTick holds VAL at zero for up to 10 us of
virtual time after every reprogram (deferred ptimer reload plus the
10 us timeout floor), so any two set_timeout() calls landing within
that window inject the whole previous period as phantom elapsed
cycles. With preemptive time-slicing constantly re-arming the timer,
an idle arm followed by a slice re-arm advanced the software clock by
the full 16.7M-cycle idle span in one step: uptime raced ahead of
real time and every k_timeout fired far too early in wall-clock
terms.

Store the out-parameter before the realignment so the caller gets the
sample as read. The zero-window then contributes zero drift, matching
the pre-conversion behaviour, and the genuine-wrap cases are
unchanged: the wrap itself is accounted through COUNTFLAG/overflow_cyc
and the compensation only adds the small post-wrap remainder.

Assisted by Claude (claude-opus-4-8).
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-21 22:52:09 -05:00
Benjamin Cabé
7aac0120ca drivers: input: pmw3610: Use the cached device in the work handler
The work handler already caches data->dev in a local, so reuse it in
both input_report_rel() calls instead of dereferencing data->dev again.

Assisted-by: Claude:opus-4.8
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-21 18:04:41 -04:00
Benjamin Cabé
d1cfc8e88a drivers: can: xmc4xxx: Read the receive error counter
get_state_from_status() read the transmit error counter into both
tec and rec, so the reported RX error count mirrored the TX count
and the error-passive state could be reported incorrectly. Use the
receive error counter accessor for rec.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-21 18:04:31 -04:00
Raffael Rostagno
f9506e67ac drivers: serial: uart: esp32: Reject non-DMA TX buffers
Return -ENOTSUP when async TX uses a buffer GDMA cannot read.
Allow flash/DROM TX only on SoCs with SOC_DMA_CAN_ACCESS_FLASH.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 18:04:20 -04:00
Nicolas Pitre
dde56fe906 drivers: timer: esp32_sys_timer: use the generic timer core
Convert the ESP32 systimer to system_timer_generic.h. The free-running
64-bit systimer counter with a one-shot alarm is a COMPARE backend: the
driver keeps z_clock_cycle_get() (the counter) and z_clock_set_compare()
(arm the alarm), and the core takes over the tick accounting, the deadline
math, the range clamp and the announce. The hand-rolled last_count
baseline and the sys_clock_elapsed() / set_timeout() tick math move into
the core; the ISR reduces to clearing the alarm interrupt and announcing.

z_clock_set_compare() keeps the target at least MIN_DELAY ahead so one
that latency left too close is not missed. Both the cycle read and the
alarm arm keep their systimer_hal.dev NULL guard, so a call before the
timer is brought up, or after sys_clock_disable() has torn the HAL down,
does not dereference a cleared dev. The light-sleep compensation
(CONFIG_PM) is preserved: on exit the driver advances the stalled counter
by the missed cycles and lets the core announce the resulting delta.

Build-verified on esp32c3_devkitm, with and without CONFIG_PM. No QEMU
target runs this driver, so this is a build-only conversion.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
72d14283bd drivers: timer: intel_adsp_timer: use the generic timer core
Convert the Intel ADSP wall clock timer to system_timer_generic.h. The
free-running 64-bit wall clock (external to the CPUs, shared across SMP)
with an absolute comparator is a COMPARE backend: the driver keeps
z_clock_cycle_get() (the counter) and z_clock_set_compare() (arm the
comparator), and the core takes over the tick accounting, the deadline
math, the range clamp and the announce. The hand-rolled last_count
baseline and the sys_clock_elapsed() / set_timeout() tick math move into
the core; the ISR reduces to acknowledging the trigger and announcing.

Arming disarms and rearms the comparator, so z_clock_set_compare() keeps
the target at least MIN_DELAY ahead of the counter, so that sequence
cannot race the counter past it. The efficient single-register cycle read
(count32(), one read rather than the three the 64-bit read needs) is kept
as sys_clock_cycle_get_32().

The wall clock is a genuine 64-bit counter on this 32-bit CPU, so
CYCLES_WIDTH is set to 64 to use its full range; the native-width default
would clamp announce deltas to 32 bits.

The previous build assertion requiring MIN_DELAY to be smaller than one
tick is dropped. A minimum comparator delay larger than a tick is not
fatal: it only coarsens the granularity, and the core copes by announcing
whatever actually elapsed, so it no longer needs to be a build-time
constraint.

Build-verified on intel_adsp/ace15_mtpm. No QEMU target runs this driver
(its targets are the ADSP simulator and hardware), so this is a build-only
conversion.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
b63136f402 drivers: timer: apic_tsc: use the generic timer core
Convert the x86 APIC TSC timer to system_timer_generic.h. The free-running
64-bit TSC with an absolute deadline (the TSC_DEADLINE MSR, or the local
APIC timer ICR in one-shot mode as the fallback) is a COMPARE backend: the
driver keeps z_clock_cycle_get() (rdtsc) and z_clock_set_compare()
(set_trigger), and the core takes over the tick accounting, the deadline
math, the range clamp and the announce. The hand-rolled last_cycle
baseline and the sys_clock_elapsed() / set_timeout() tick math move into
the core; the ISR reduces to an announce, and smp_timer_init() keeps
copying CPU0's LVT to each secondary.

The frequency is a build-time constant here (this driver is not
runtime-frequency), so the core derives cycles-per-tick from
CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC as before. CYCLES_WIDTH defaults to the
unsigned long width, matching the driver's former native-register divisor.

The deadline arm range narrows from the driver's former three-quarter
span to the core's default half span. Half the span reserves the upper
half as IRQ-latency headroom, so a late announce of a maximum-length arm
still yields an in-range delta; the three-quarter bound did not keep that
margin. The realistic tick range is far below either bound, so this is not
a functional change.

The one dropped behaviour is the set_timeout() guard that pinned a deadline
to UINT64_MAX when the computed deadline wrapped the 64-bit TSC: it guarded
an unreachable, untestable case (the 64-bit TSC takes centuries to wrap,
about 585 years at 1 GHz) and has no clean place in the core, whose range
clamp already bounds the realistic range.

Build-verified on qemu_x86_64 and qemu_x86 (the 64- and 32-bit unsigned
long paths) with the TSC deadline comparator, and on qemu_x86_64 with the
APIC_TIMER_TSC ICR fallback. No QEMU target runs this driver (qemu_x86*
default to HPET, and forcing the TSC timer on QEMU's atom model delivers no
deadline interrupts, on mainline too), so this is a build-only conversion;
its real users are ACRN and x86 hardware.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
e8163a1052 drivers: timer: native_sim_timer: use the generic timer core
Convert the native_sim timer to system_timer_generic.h. The simulator has
no compare register; its time base is the microsecond counter
nsi_hws_get_time() and its only lever is hwtimer_set_silent_ticks(), which
skips that many periodic tick interrupts before raising the next. That
still maps onto a COMPARE backend: z_clock_cycle_get() reads the counter
and z_clock_set_compare() converts the core's absolute, tick-aligned
deadline into the number of ticks to skip (rounding up to the next tick
boundary, since the simulator only interrupts on boundaries and the
counter may sit mid-tick after a busy-wait). The counter is 64-bit and
never wraps (CYCLES_WIDTH 64), and the deadline is a full 64-bit value, so
the long fast-forward idle periods the simulator relies on are preserved
(a 32-bit RELOAD reload would have capped them).

The hand-rolled last_tick_time baseline, the ISR elapsed computation and
sys_clock_elapsed() move into the core; the ISR reduces to an announce.
sys_clock_disable() and the test ISR hook are unchanged.

timer_api, timer_behavior, context, sleep, tickless and common pass on
native_sim, timer_api and context pass on native_sim/native/64, and
timer_api passes on native_sim with CONFIG_TICKLESS_KERNEL=n.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
112ed46350 drivers: timer: leon_gptimer: use the generic timer core
Convert the LEON GPTIMER to system_timer_generic.h. GPTIMER has no
absolute compare register, only a relative reload, so it is a RELOAD
backend: subtimer 1 free-runs as the cycle source and subtimer 0 is
loaded with the relative delay the core derives from a tick-aligned
deadline. The driver keeps z_clock_cycle_get() (the free-running counter)
and z_clock_set_reload() (program subtimer 0); the core takes over the
tick accounting, the deadline math, the range clamp and the announce.

The subtimers run at the system rate divided by the shared prescaler, so
the core works in that (divided) cycle domain: z_clock_cycle_get() and
CYC_PER_TICK share it, and only the public sys_clock_cycle_get_32() scales
back up to the system cycle rate. The hand-rolled announce baseline and
the sys_clock_elapsed()/set_timeout() tick math move into the core; the
ISR reduces to acknowledging (one-shot stop when tickless, keep periodic
otherwise) and announcing.

timer_api, context, sleep and tickless pass on qemu_leon3, and timer_api
passes there with CONFIG_TICKLESS_KERNEL=n (the periodic path).

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
fe872510f5 drivers: timer: openrisc_tick_timer: use the generic timer core
Convert the OpenRISC tick timer to system_timer_generic.h. The
free-running TTCR count with an equality-match TTMR compare is a COMPARE
backend: the driver keeps z_clock_cycle_get() (TTCR) and
z_clock_set_compare() (TTMR), and the core takes over the tick
accounting, the deadline math, the range clamp and the announce.

The compare field TTMR.TP is only 28 bits while TTCR is 32, so the
counter is declared 28-bit wide (CYCLES_WIDTH) and the core clamps arming
to that span, which subsumes the driver's open-coded half-range clamp.
Because TTMR matches only TTCR[27:0] == TP, z_clock_set_compare() keeps a
minimum-delay bump (in the 28-bit domain) so an already-past target is not
missed until the count wraps.

The hand-rolled last_count baseline, the private spinlock and the
sys_clock_elapsed()/set_timeout() tick math move into the core; the ISR
reduces to disarming the compare (tickless) and announcing.

timer_api, context, sleep and tickless pass on qemu_or1k.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
4b0877cebe drivers: timer: xtensa_sys_timer: use the generic timer core
Convert the Xtensa CCOUNT/CCOMPARE timer to system_timer_generic.h. The
free-running 32-bit CCOUNT with an equality-match CCOMPARE is a COMPARE
backend: the driver keeps z_clock_cycle_get() (CCOUNT) and
z_clock_set_compare() (CCOMPARE), and the core takes over the tick
accounting, the deadline math, the range clamp and the announce. Because
CCOMPARE fires only on CCOUNT == CCOMPARE, z_clock_set_compare() keeps the
driver's minimum-delay bump so an already-past target is not missed until
CCOUNT wraps, matching the core's "must not miss a past deadline"
contract.

The hand-rolled last_count baseline, the tickful re-arm and the
sys_clock_elapsed()/set_timeout() tick math all move into the core.
smp_timer_init() primes the per-CPU timer through z_clock_smp_prime().

The low-power compensation is preserved: ccount() still adds the
compensation offset, so the cycle count and every announced delta pick it
up for free, and the Espressif LPM hook
(CONFIG_XTENSA_TIMER_LPM_TIMER_HOOK) now just folds the missed cycles into
that offset and lets the core announce. The non-low-power idle path drops
to the weak sys_clock_idle_enter() default (which arms through
sys_clock_set_timeout()).

timer_api, context, sleep and tickless pass on qemu_xtensa/dc233c.
Build-verified on esp32 with the LPM hook (CONFIG_PM=y) and with SMP.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
2b432e151b drivers: timer: renesas_ra_ulpt: use the generic timer core
Convert the Renesas RA ULPT timer to system_timer_generic.h. ULPT
instance 1 free-runs and provides the cycle counter (its down-counter
read back inverted counts up); ULPT instance 0 is armed with a relative
delay and its underflow announces ticks. That is a RELOAD backend whose
cycle source is a genuine free-running counter, so the driver keeps only
z_clock_cycle_get() (~INST1 counter) and z_clock_set_reload() (arm INST0),
and the core takes over the tick accounting and the tick-aligned deadline.

This removes the driver's open-coded "ticks - 1" adjustment and round-up
dance (the code carrying the "preserve the original behavior even though
it looks wrong; to be revisited" comment): the core computes the reload
from an absolute tick-aligned deadline, which is the correct behavior. The
private spinlock and the announce baseline (cycle_announced) go with it.

Compile-verified on ek_ra8p1 (RENESAS_RA_ULPT_TIMER forced on; the driver
is the default system timer there when CONFIG_PM is enabled). No QEMU
target runs this driver, so this is a build-only conversion.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
72b15164ac drivers: timer: arcv2_timer0: use the generic timer core (non-SMP)
Convert the non-SMP ARCv2 timer0 path to system_timer_generic.h. Timer0
is an up-counter that counts to LIMIT and resets on match: a RELOAD
backend, and the compare-match-reset variant of the reload family (the
cmsdk/systick down-counters were the down-to-zero variant). The driver
keeps its synthesized cycle count with the wrap-aware elapsed() (it folds
a pending overflow in via the IP bit, so the count stays monotonic) and
programs the next LIMIT in z_clock_set_reload(); the core takes over the
tick accounting, the deadline-to-reload conversion, the range clamp and
the announce, replacing the driver's own unannounced/round-up math.

The SMP path (a separate implementation on the gfrc wall clock) is left
unchanged, guarded so only the non-SMP build pulls in the core and its
emitted sys_clock_* entry points.

timer_api and context pass on qemu_arc/qemu_arc_em.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
d277540ce0 drivers: timer: cortex_m_systick: use the generic timer core
Convert the Cortex-M SysTick to system_timer_generic.h. SysTick is an
auto-reload 24-bit down-counter: a RELOAD backend. The driver keeps its
hardware-specific parts, the synthesized cycle count with COUNTFLAG-based
wrap detection (timer_driver_cycle_get) and the reprogram-with-drift-
compensation of the LOAD register (timer_driver_set_reload, the val1/val2
recovery), and the core takes over the tick accounting: announced_cycles
and last_elapsed move into the core, and the deadline-to-reload
conversion, the range clamp and the announce come from it. The 24-bit
LOAD caps the arm at TIMER_CORE_CYCLES_MAX; the reload floor is the
min_delay from the preceding commit (TIMER_CORE_MIN_DELAY).

The driver carries no cycles-per-tick of its own. With the reload floor
no longer expressed in ticks, the only remaining need for that value is
establishing the one-tick LOAD at init and on the low-power restart, which
reads the core's TIMER_CORE_CYC_PER_TICK; the core derives it from the
counter rate (the system clock rate), so the driver no longer defines it.
The former "tickless does nothing" pragma goes too: the core already
build-asserts a non-zero cycles-per-tick.

Care was taken to preserve the subtle behaviour of this driver:

  - The overflow commit at ISR entry runs under the clock lock, held
    through the announce (via the core's timer_core_announce_from() entry
    that takes an already-acquired key), so a higher-priority interrupt
    reading the cycle counter never sees a half-committed overflow, as
    before. sys_clock_idle_exit() adds the missed low-power cycles under
    the same lock and hands off the same way.

  - The drift compensation keeps the gap-free val1 sampling of the
    approved fix in PR #109574: elapsed() returns its SysTick->VAL
    snapshot through an out-parameter, so timer_driver_set_reload() reads
    no separate SysTick->VAL and loses no function-return cycles.

  - With a 64-bit cycle counter the synthesized count is set as the core
    counter width (CYCLES_WIDTH = 64) so the core does not mask announce
    deltas to 32 bits: a low-power sleep longer than 2^32 cycles reports
    a >32-bit delta, and truncating it would announce far too few ticks
    (the k_sleep-never-wakes failure addressed by PR #112806).

  - The reload is computed in the counter's cycle domain, not from the
    linear absolute deadline, so it stays correct across a counter wrap;
    a starved ISR collapses to the reload floor as the old unannounced<0
    guard did.

The runtime frequency update rescales the synthesized counter and, via
the core's timer_core_rescale(), the announce baseline. The reprogrammed
LOAD is now a pure cycle-domain scaling in both modes: the tickless
remainder and the tickful one-tick period are each the previous value
scaled by the new/old rate ratio, so the rescale needs no cycles-per-tick.
The low-power companion and the 64-bit and sloppy-idle-stop paths are all
kept.

Validated on qemu_cortex_m3 and mps2/an385: timer_api and context pass
tickless (default) and tickful, with CORTEX_M_SYSTICK_64BIT_CYCLE_COUNTER,
and the sys_clock_hw_cycles_update test passes (the frequency-rescale
path). The low-power companion path is compile-verified on frdm_mcxa153
with CONFIG_PM; it has no QEMU target to run here.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
1b608c64c9 drivers: timer: cortex_m_systick: derive min timeout from cycle rate
MIN_DELAY is the floor of the SysTick LOAD register: the closest-in
timeout the driver will program. It must exceed the longest the SysTick
interrupt can stay masked, otherwise the 24-bit counter can wrap more than
once between elapsed() reads and lose a LOAD's worth of cycles. That is a
wall-clock property, but the default was a fixed cycle count:

	MAX(1024, CYC_PER_TICK/16)

A fixed cycle count is a different wall-clock time on every clock. On a
32 kHz SysTick the 1024-cycle floor is ~31 ms (31 ticks), so the driver
could never schedule a timeout shorter than 31 ticks and every such board
had to override zephyr,min-timeout-cycles by hand.

Compute it instead as a fixed wall-clock budget scaled to the actual
frequency (min_delay = SYSTICK_MIN_DELAY_US * HW_CYCLES_PER_SEC), resolved
at init and refreshed on a runtime frequency change, so it also works when
the frequency is only known at runtime. At ~10 us this matches the old
1024 cycles near 100 MHz and scales sensibly elsewhere. The tick rate is
not involved; if the budget exceeds a tick on some clock, sub-tick timeouts
are simply unavailable there. A dts override still takes precedence.

Floor the result at two cycles: LOAD is programmed as (cycles - 1) and a
LOAD of zero stops the counter, so the smallest usable reload is two cycles
(LOAD 1). On a slow clock such as a 32 kHz SysTick the 10 us budget rounds
below that, so the hardware floor is what applies and the board still needs
no override.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
b5e4dc82a4 drivers: timer: cmsdk_apb: use the generic timer core
Convert the ARM CMSDK APB timer to system_timer_generic.h, the first
driver to exercise the core's RELOAD backend. The auto-reload
down-counter keeps its synthesized cycle count (timer_driver_cycle_get)
and its reprogram-with-drift-compensation (timer_driver_set_reload, the
val1/val2 recovery that loses no cycles between reading and rewriting the
counter); the core takes over the tick accounting, the deadline-to-reload
conversion, the range clamp and the announce. The driver no longer states
its own cycles-per-tick: with the reload floor derived from the cycle rate
by the preceding commit, the only remaining use is the one-tick init
reload, which reads the core's TIMER_CORE_CYC_PER_TICK. sys_clock_unused()
reloads the longest interval the core's range allows under sloppy idle
(capped at TIMER_CORE_CYCLES_MAX, since a full-span reload would wrap the
32-bit synthesized count and alias the wrap announce), as an auto-reload
counter cannot simply stop being reprogrammed. The public cycle counter
carries forward the wrap-safe read from the preceding commits.

Being the first RELOAD user, it exercises two core paths for the first
time:

  - The non-tickless path: a COMPARE timer re-arms its comparator each
    ISR, but an auto-reload counter free-runs from the LOAD set at init,
    so the core skips the per-tick re-arm for RELOAD.

  - The reload is computed in the counter's cycle domain (cycles to the
    deadline minus the masked cycles already elapsed since the last
    announce), not from the linear absolute deadline. The synthesized
    counter wraps at its width while the announce baseline is linear, so
    the absolute form would diverge once the counter passes its wrap;
    the domain-relative form stays correct, and a starved ISR still
    collapses to the reload floor.

Verified behaviour-preserving by pointing mps2/an385's chosen
system-timer at its cmsdk timer0 and running timer_api: it passes,
including under QEMU icount. No in-tree board selects cmsdk as the system
timer, so this configuration is not otherwise exercised in CI.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
b2a4659e5e drivers: timer: cmsdk_apb: derive min timeout from cycle rate
MIN_DELAY_CYCLES is the floor of the reload the driver will program: the
closest-in timeout it can schedule. It must exceed the longest the timer
interrupt can stay masked, otherwise the counter can wrap more than once
between elapsed_cyc() reads and lose a period. That is a wall-clock
property, but the default was a fixed cycle count:

	MAX(1024, CYC_PER_TICK/16)

A fixed cycle count is a different wall-clock time on every clock. On a
slow counter the 1024-cycle floor is tens of milliseconds, so the driver
could never schedule a short timeout and such a board would have to
override CMSDK_APB_TIMER_MIN_DELAY_CYCLES by hand.

Compute it instead as a fixed wall-clock budget scaled to the actual
frequency (k_us_to_cyc_ceil32(CMSDK_MIN_DELAY_US)), resolved at init, so
it also tracks a runtime frequency. At ~10 us this matches the old 1024
cycles near 100 MHz and scales sensibly elsewhere. The
CMSDK_APB_TIMER_MIN_DELAY_OVERRIDE Kconfig still takes precedence.

Floor the result at two cycles so the reload is never degenerate on a
slow clock where the time budget rounds below that; elapsed_cyc()'s reads
still straddle at most one wrap.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
9a29bf5fac drivers: timer: cmsdk_apb: make the cycle read wrap-safe
sys_clock_cycle_get_32() and sys_clock_elapsed() return
cycle_count + elapsed(), where elapsed() is only the in-period offset
(load - value). Between a counter wrap (the down-counter reloads) and the
ISR crediting that period to cycle_count, that offset drops back near
zero, so the reported hardware cycle count briefly goes backwards. A
non-monotonic cycle counter breaks k_busy_wait() and the tick accounting
built on it.

The window is a race under real time, but QEMU icount makes the timing
deterministic and hits it every idle wake, so kernel.timer.timer_api's
test_timer_k_define fails when a cmsdk timer is selected as the system
timer under icount.

Account the pending wrap in the read path the way cortex_m_systick does:
sample the counter either side of the interrupt-status flag and add a
full period if the flag is set or the counter was seen reloading. It is
added to the returned value only; the ISR still commits the period into
cycle_count and clears the flag, so it is never counted twice. The
separate elapsed_monotonic() keeps sys_clock_set_timeout()'s reprogram
math on the raw offset, unchanged.

Reproduce (no in-tree board selects the cmsdk timer as its system timer,
so it has to be chosen by hand; mps2/an385 already has cmsdk timer0 in
its devicetree and runs QEMU with icount):

  $ cat > cmsdk.overlay <<'DTS'
  / { chosen { zephyr,system-timer = &timer0; }; };
  DTS
  $ cat > cmsdk.conf <<'CONF'
  CONFIG_CORTEX_M_SYSTICK=n
  CONFIG_CMSDK_APB_TIMER=y
  CONF
  $ west build -b mps2/an385 tests/kernel/timer/timer_api \
        -- -DEXTRA_DTC_OVERLAY_FILE=cmsdk.overlay \
        -DEXTRA_CONF_FILE=cmsdk.conf
  $ west build -t run

  Before this change test_timer_k_define fails (a spurious
  multi-thousand-tick announce races uptime ahead of the cycle-based
  busy-wait); after it the suite passes 17/17.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
86b421a8e0 drivers: timer: mips_cp0: use the generic timer core
Convert the MIPS CP0 timer to system_timer_generic.h. The CP0 Count
counter with its Compare register is a COMPARE backend, and the first
converted driver whose counter actually wraps during operation: on
32-bit MIPS CYCLES_WIDTH defaults to the native 32 bits, so the core
masks every delta at the 2^32 boundary.

Compare raises the interrupt only on Count == Compare, so an already-past
target is missed until Count wraps all the way around. z_clock_set_compare
therefore bumps the target until it is at least MIN_DELAY ahead, which is
the core's "must not miss a past deadline" contract; the read-back loop
replaces the driver's former open-coded MIN_DELAY handling in both
set_timeout and the ISR. Writing Compare also clears the interrupt.

The core now owns the tick accounting (previously the driver resynced its
baseline to the raw count each ISR, discarding the sub-tick remainder and
drifting slow; the core keeps the baseline tick-aligned, so that is fixed
too) and the locking, so the driver's private spinlock is gone.

timer_api and context pass on qemu_malta.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
8f0b89f00d drivers: timer: hpet: use the generic timer core
Convert the HPET to system_timer_generic.h. The free-running 64-bit
counter with its comparator is a COMPARE backend: the driver keeps
z_clock_cycle_get() (the counter) and z_clock_set_compare()
(hpet_timer_comparator_set_safe), and the core takes over the tick
accounting, the deadline math, the range clamp and the announce.
CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME resolves the cycle rate to
the value read from the counter period at init.

Two HPET specifics stay: the level-trigger interrupt acknowledge in the
ISR, and the sloppy-idle stop / resume in sys_clock_unused() /
sys_clock_idle_exit(). The equality-match comparator (it fires only on
count == cmp) is why z_clock_set_compare() uses the read-back retry;
that is exactly the core's "must not miss a past deadline" contract.

Under QEMU SMP the shared counter can be observed reading backwards; the
driver enables the core's Z_CLOCK_COUNTER_NONMONOTONIC hook to treat such
a read as no elapse, which also drops the arm limit to a quarter span so
the backwards test stays unambiguous. This is HPET's first user.

timer_api and context pass on qemu_x86_64 (SMP, so the backwards hook and
the runtime frequency path are exercised) and qemu_x86.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
d367b01e88 drivers: timer: riscv_supervisor: use the generic timer core
Convert the RISC-V supervisor timer to system_timer_generic.h. The "time"
CSR with the SBI set-timer deadline is a COMPARE backend: the driver
keeps z_clock_cycle_get() (stime) and z_clock_set_compare()
(sbi_set_timer), and the core takes over the tick accounting, the
deadline math, the range clamp and the announce. smp_timer_init() primes
the timer through z_clock_smp_prime().

This also drops the driver's private spinlock: it now runs under the
kernel timer lock via the core's sys_clock_lock() / announce_locked(),
which is the intended locking for a system-timer driver.

timer_api and context pass on qemu_riscv64/qemu_virt_riscv64/smode
(supervisor timer under OpenSBI).

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
772b66b9af drivers: timer: arm_arch: use the generic timer core
Convert the ARM generic timer to system_timer_generic.h. The
free-running system counter with its absolute compare register is a
COMPARE backend; the driver keeps z_clock_cycle_get() (the counter) and
z_clock_set_compare() (set the comparator and unmask), and the core takes
over the tick accounting, the deadline math, the range clamp and the
announce. CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME still resolves
CYC_PER_TICK to the value cached at init. smp_timer_init() primes the
per-CPU comparator through z_clock_smp_prime().

The ISR keeps its hardware specifics: the Cortex-A9 erratum 740657
spurious-interrupt handling, and masking the level-asserted compare in
tickless mode (the core's rearm unmasks it). The counter uses the core's
default cycle-get; declaring its 64-bit width with TIMER_CORE_CYCLES_WIDTH
removes the driver's former CONFIG_GDBSTUB-only widening of the cycle
diff, which existed only because the width was not stated. Behaviour is
unchanged; timer_api and context pass on qemu_cortex_a53 UP and SMP.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
23ad0c4df5 drivers: timer: riscv_machine: use the generic timer core
Convert the RISC-V machine timer to system_timer_generic.h. The mtime
counter with its absolute mtimecmp compare is a COMPARE backend: the
driver keeps only z_clock_cycle_get() (mtime) and z_clock_set_compare()
(set_mtimecmp), and the core takes over the cycle-to-tick accounting, the
deadline math, the range clamp and the announce. smp_timer_init() primes
the per-hart comparator through z_clock_smp_prime() rather than reaching
into the core's baseline.

The public cycle counter applies the DT clock divider to raw mtime, so it
overrides the core's default sys_clock_cycle_get_32/64() via
Z_CLOCK_HAVE_CYCLE_GET_32/64. Behaviour is unchanged; timer_api and
context pass on qemu_riscv64.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
ca254d5a1d drivers: timer: add generic tickless system-timer core
Every tickless system-timer driver reimplements the same tick accounting
by hand: the cycle-to-tick division, the announce baseline
(last_cycle/last_tick/last_elapsed), the tick-aligned deadline
computation and the range clamp. The logic is identical across the
free-running-compare drivers (arm_arch_timer, riscv_machine_timer, hpet,
...) down to the copied overflow-guard constant, and the small
divergences between the hand-rolled copies are a recurring source of
timer bugs.

Add system_timer_generic.h, an implementation header a driver includes
to get that accounting for free. It emits the tick-facing contract the
kernel calls (sys_clock_set_timeout(), sys_clock_elapsed(),
sys_clock_cycle_get_32/64()) and owns the baseline state, so the driver
is left with only cycle-domain primitives: read the counter, arm the
comparator (or program a relative reload), acknowledge the interrupt.

The header is included, not linked: the driver defines its constants and
static-inline primitives first, so the core inlines and constant-folds
against them (the per-tick divide becomes a multiply-shift, an unused
backend path is eliminated) on a plain -Os build with no LTO. Because
the header defines the global sys_clock_* symbols, a build that pulls in
two system timers fails at link time, which is the correct outcome. It
lives beside the drivers rather than under include/, as it is private to
them.

The core is complete on its own; the conversions that follow only use
it, they do not extend it:

  - Two backends: COMPARE (free-running counter plus an absolute compare
    register) and RELOAD (a relative down-counter, assumed to auto-reload
    so a non-tickless kernel needs no per-tick re-arm).

  - Counter width is a CYCLES_WIDTH knob: the core masks every delta to
    that width, so a counter narrower than 64 bits is used as-is, without
    software extension. The default is the native register width.

  - CYCLES_MAX bounds how far ahead a deadline is armed: half the counter
    span by default (the upper half is IRQ-latency headroom), a quarter
    span with Z_CLOCK_COUNTER_NONMONOTONIC, where the upper half instead
    flags a counter that momentarily reads backwards (a global timer seen
    from another CPU under QEMU SMP), so such a read is reported as no
    elapse rather than a huge forward jump.

  - The cycle rate is a CYCLES_PER_SEC knob (default the kernel system
    clock rate), from which the core derives the cycles per tick: a
    build-time-constant rate folds the division; a run-time rate
    (CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) is precomputed once in
    z_clock_init() and refreshed by z_clock_rescale() on a frequency
    change, so the driver never states cycles-per-tick itself.

  - Init and SMP bring-up helpers (z_clock_init(), z_clock_smp_prime()),
    and a z_clock_announce_from() entry for a driver that must keep work
    atomic with the announce.

No driver includes the header yet; conversions follow.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
fa9b836416 kernel: timeout: drop the idle argument of sys_clock_set_timeout()
With low-power idle handoff now going through sys_clock_idle_enter(),
nothing passes idle == true to sys_clock_set_timeout() any more, so the
argument is dead. Drop it: sys_clock_set_timeout(uint32_t ticks) now
means exactly "program the next tick, N ticks out", nothing else.

This updates the prototype, the weak default, every in-tree timer driver
definition (including the out-of-tree-style board timer under boards/),
and the core call sites. For the five drivers with low-power behaviour
this only removes the now-unused idle argument that the previous change
left on set_timeout(); the handling itself stays in their
sys_clock_idle_enter().

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
7d0bb85adc kernel: timeout: add sys_clock_idle_enter() for low-power idle handoff
The idle argument of sys_clock_set_timeout() carries a distinct signal:
the CPU is entering low-power idle, here is its wakeup. Only the PM and
SoC power paths produce it (the timeout core always passes false), and
only a few drivers act on it to hand off to a low-power wakeup timer.

Introduce a dedicated sys_clock_idle_enter() hook for that, so the two
idle==true callers (subsys/pm and soc/nxp/rw) call it instead of
sys_clock_set_timeout(). Its weak default just programs the wakeup via
sys_clock_set_timeout(), so a driver with no low-power handling needs
nothing.

The five drivers that acted on idle (cortex_m_systick, esp32, xtensa,
mcux_os, stm32_lptim) move that handling into their own
sys_clock_idle_enter(), keeping their exact behaviour. Where the idle
path was self-contained it moves wholesale (cortex_m_systick, mcux_os,
stm32_lptim); where it shares the timeout programming, idle_enter()
calls set_timeout() first and then does its idle work (esp32), or shares
a small private helper (xtensa). set_timeout() keeps its now-unused idle
argument for the moment; nobody passes idle==true to it any more, which
lets the next change drop the argument entirely.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
e5903e4796 drivers: timer: mcux_os: track the no-deadline state in sys_clock_unused()
mcux_os keeps a wait_forever flag (consumed by the counter-overflow wakeup
path) that it set when sys_clock_set_timeout() was called with the
SYS_CLOCK_MAX_WAIT sentinel. The kernel no longer passes that value; the
no-deadline case now arrives via sys_clock_unused(). Set the flag there and
program the match as far out as the hardware allows; clear it on a real
sys_clock_set_timeout().

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
269e2e618a drivers: timer: stop the clock via sys_clock_unused()
The kernel now signals "no timeout pending, uptime may drift" by
calling sys_clock_unused() instead of passing the SYS_CLOCK_MAX_WAIT
sentinel to sys_clock_set_timeout(). Move each driver's sloppy-idle
handling out of sys_clock_set_timeout() and into a sys_clock_unused()
implementation, and drop the ticks == SYS_CLOCK_MAX_WAIT comparisons.

Drivers that actively stop the counter (cortex_m_systick, arcv2, hpet,
mcux_sysctr, mcux_lptmr, sam0, ite, infineon, mchp_xec, realtek,
stm32_lptim) do so in sys_clock_unused(). The free-running compare
timers (nrf_rtc, mcux_rtc_jdp, max32_rv32) instead follow the renesas
model and simply stop reprogramming: the last compare still catches the
counter wrap and the next real timeout re-arms them, so an explicit
maximum-length wait would only add a needless periodic wakeup. nrf_rtc
keeps a one-line sys_clock_unused() that clears the flag consumed by its
overflow-trigger path; mcux_rtc_jdp and max32_rv32 need no override at
all, like the renesas drivers.

cmsdk_apb is the exception: it is an auto-reload down-counter, so not
reprogramming would keep firing at the previous (possibly short)
interval. It programs the maximum reload instead, matching what
non-sloppy idle already does, with a note that stopping the counter
would be the better but riskier improvement.

Resume is unchanged: the next sys_clock_set_timeout() restarts the
driver.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
926f7c4c0f kernel: timeout: add sys_clock_unused() and decide sloppy idle centrally
The "no timeout pending, stop the clock" decision under
CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE was expressed by next_timeout()
returning SYS_CLOCK_MAX_WAIT verbatim as a magic sentinel, which every
timer driver then had to recognise. Move the decision into the core and
give it an explicit, resumable interface.

Add a weak sys_clock_unused() hook (no-op default): the kernel calls it
when the timeout list is empty and sloppy idle allows uptime to drift,
in place of programming a wait. A driver may override it to actively
halt its counter; one that does not simply stops being reprogrammed and
quiesces on its own, so sloppy idle now works for every driver. Resume
is the next sys_clock_set_timeout(), exactly as before; the core keeps
no paused state.

next_timeout() no longer special-cases sloppy idle, so its empty-list
and far-timeout arms collapse to the same capped budget and
SYS_CLOCK_MAX_WAIT loses its sentinel meaning. The decision lives in
reprogram_next(), used only at the two sites where the list can drain
(abort, end of announce); the add path always has a pending timeout and
calls sys_clock_set_timeout() directly.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Nicolas Pitre
7e681dbfbd drivers: timer: esp32_sys_timer: adopt the sys_clock_lock() scheme
The driver kept a private spinlock and used the legacy sys_clock_announce()
even though the kernel already holds its timer lock across the driver's
sys_clock_set_timeout() and sys_clock_elapsed() callbacks. Take that same
lock instead: the ISR and sys_clock_idle_exit() now use sys_clock_lock()
with sys_clock_announce_locked(), and set_timeout()/elapsed() simply assert
the lock is held rather than acquiring one of their own.

This drops a redundant lock and lets the upcoming low-power idle handling
avoid any locking of its own.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 18:02:43 -04:00
Fin Maaß
3df5fa4d3f drivers: ethernet: stm32: ptp: use BUILD_ASSERT
use BUILD_ASSERT for checking constant values.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-07-21 14:10:18 -04:00
Dhanoo Surasarang
390259c1cd drivers: flash: nrf_mramc: Resolve MRAM node from DT instance
The driver hardcodes DT_NODELABEL(cpuapp_mram) which does not exist
when building for cpuflpr since the node is deleted in the cpuflpr
dtsi. Use DT_INST(0, soc_nv_flash) to resolve whichever soc-nv-flash
child is present under the controller, matching the RRAM driver.

Signed-off-by: Dhanoo Surasarang <dhanoo.surasarang@nordicsemi.no>
2026-07-21 14:09:29 -04:00
Fin Maaß
a87d486e19 net: ethernet: remove ETHERNET_PTP from caps
net_eth_get_ptp_clock can be used instead to
check if ptp is supported, so remove ETHERNET_PTP.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-07-21 14:07:22 -04:00
Benjamin Cabé
e88ca1047e drivers: ethernet: xmc4xxx: Cache RX fragment in refill
Read dev_data->rx_frag_list[tail] once into a local when preparing
each RX DMA descriptor instead of dereferencing it twice.

Assisted-by: Claude:opus-4.8
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-21 10:17:17 -04:00
Benjamin Cabé
44aff43597 drivers: input: paw32xx: Use the cached device in the work handler
The motion work handler already caches data->dev in a local, so reuse it
in both input_report_rel() calls instead of dereferencing data->dev
again.

Assisted-by: Claude:opus-4.8
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-21 10:17:04 -04:00
Farsin Nasar V A
1180ffd0ab drivers: rtc: mchp: Initialize unsupported rtc_time fields
The get_time() and get_alarm_time() APIs left tm_yday, tm_isdst,
and tm_nsec uninitialized after populating the rtc_time structure.

Initialize tm_yday and tm_isdst to -1 (unsupported/unknown) and
tm_nsec to 0, matching the convention used by other RTC drivers
in Zephyr.

Signed-off-by: Farsin Nasar V A <farsin.nasarva@microchip.com>
2026-07-21 10:16:55 -04:00
Gang Li
4685e0927a drivers: wifi: nxp: Add Kconfig for external antenna gain
Add NXP_WIFI_EXT_ANT_GAIN Kconfig option to enable runtime
configuration of net antenna gain per sub-band via host command
API.
This kconfig is only applicable to RW61x.

Signed-off-by: Gang Li <gang.li_1@nxp.com>
2026-07-21 10:16:10 -04:00
Zafer SEN
0c1b0c7996 drivers: modem: tolerate extra OK responses during startup queries
Accept extra `OK` responses after `AT+KSELACQ?` and `AT+KSRAT?`
during HL78xx initialization. This keeps the chat script aligned
on firmware versions that return an additional `OK` for these queries.

Signed-off-by: Zafer SEN <zafersn93@gmail.com>
2026-07-21 10:14:36 -04:00
Zafer SEN
249511bb6e drivers: modem: hl78xx: skip GSM band configuration in AutoRAT mode
Treat AutoRAT operation the same as GSM when determining whether
band configuration should be skipped on HL7812 devices.

Do not attempt to configure band selection when GSM is enabled.

This includes AutoRAT mode, since the modem may fall back to 2G if the
other configured RATs are unavailable. Because GSM band configuration
is not supported in this context, band programming should be skipped
whenever GSM can be selected by the modem.

This avoids sending unsupported band configuration commands and aligns
the band configuration logic with the modem's RAT capabilities.

Signed-off-by: Zafer SEN <zafersn93@gmail.com>
2026-07-21 10:14:36 -04:00
Krzysztof Chruściński
ab802f362d drivers: clock_control: nrf: Start HFXO before starting HFXO24M
Even though HFXO24M automatically starts HFXO, it is much easier to
manage if HFXO is managed by software. Add requesting of HFXO when
HFXO24M is started.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
2026-07-21 10:14:19 -04:00
Sylvio Alves
4fcf816317 drivers: spi: esp32: select the peripheral clock source
The driver reads the rate of the configured clock source and
calculates the timing divider against it, but never programs
the hardware mux that selects that source. The mux keeps its
reset value, so the peripheral runs from XTAL while the
divider assumes a PLL rate.

On esp32p4 the default source is the 480 MHz SPLL and the
reset value selects the 40 MHz XTAL, making every transfer 12
times slower than requested: a 1 MHz request measures 83 kHz.
Program the mux at init so it matches the rate the divider is
calculated from.

Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
2026-07-21 10:14:08 -04:00
Liam Ogletree
184f1f8ad0 drivers: haptics: Documentation cleanup for haptic drivers
Unifies documentation for haptic drivers. Previously, CS40L26/27
showed up under "Files" in Haptics documentation while the other
three drivers showed up under "Topics".

Signed-off-by: Liam Ogletree <liam.ogletree@cirrus.com>
2026-07-21 10:12:25 -04:00
Raffael Rostagno
dd7855f7bb drivers: i2c: esp32: Attach sleep retention modules
Attach sleep retention modules to effectively enable TOP PD power down.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 10:12:17 -04:00
Raffael Rostagno
af80c9c022 drivers: counter: esp32: Fix sleep retention
Adopt gptimer retention API and attach sleep retention modules
to effectively enable TOP PD power down.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 10:12:17 -04:00
Raffael Rostagno
a3351d28f3 drivers: watchdog: esp32: Attach sleep retention modules
Attach sleep retention modules to effectively enable TOP PD power down.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 10:12:17 -04:00
Raffael Rostagno
3fbf8cc6c8 drivers: mcpwm: esp32: Fix sleep retention
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>
2026-07-21 10:12:17 -04:00
Raffael Rostagno
e3e916d448 drivers: ledc: esp32: Attach sleep retention modules
Attach sleep retention modules to effectively enable TOP PD power down.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 10:12:17 -04:00
Raffael Rostagno
a23d5c192b drivers: spi: esp32: Attach sleep retention modules
Attach sleep retention modules to effectively enable TOP PD power down.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 10:12:17 -04:00
Raffael Rostagno
0f3a61dfc3 drivers: serial: esp32: Attach sleep retention modules
Attach sleep retention modules to effectively enable TOP PD power down.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 10:12:17 -04:00
Raffael Rostagno
3868992de7 drivers: dma: esp32: Attach sleep retention modules
Without ATTR_ATTACH and sleep_retention_module_attach(), GDMA channels
are created but not retained, so peripheral_domain_pd_allowed() stays
false and TOP never powers down in light sleep. Fix lowers light sleep
current when GDMA and peripheral power down are enabled.

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
2026-07-21 10:12:17 -04:00