Commit graph zephyr/drivers
Author SHA1 Message Date
Benjamin Cabé
c28db9baf0 drivers: watchdog: andes_atcwdt200: Fix overflow in timeout conversion
The millisecond timeout was multiplied by the external clock
frequency in 32-bit arithmetic, overflowing for timeouts above
131 seconds and programming a much shorter period than requested.
Do the conversion in 64-bit.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:13:10 +01:00
Maochen Wang
3b2bef1cb2 drivers: wifi: nxp: release ETH header frag after copy in TX path
In the zero-copy TX path, nxp_wifi_internal_tx() copies the Ethernet
header into the outbuf structure but keeps the original ETH header
net_buf attached to the net_pkt. This wastes one tx_buf slot per
packet while it sits in the WMM queue waiting to be transmitted.

Under heavy TX backpressure (e.g. during roaming with continuous
traffic), this doubles the effective tx_buf consumption per queued
packet, leading to premature tx_buf pool exhaustion.

After copying the ETH header, use net_pkt_frag_del() to release the
first fragment when it contains exactly the ETH header. The payload
fragment remains attached and the cursor position is unaffected since
it already points past the ETH header.

Assisted-by: WChat:Claude
Signed-off-by: Maochen Wang <maochen.wang@nxp.com>
2026-07-22 11:13:04 +01:00
Holt Sun
5b1e30a595 drivers: counter: mcux_rtc: implement clock calibration
The counter API declares optional clock calibration ops in signed
parts-per-billion, but the Kinetis RTC counter driver did not
implement them, so counter_set/get_calibration returned -ENOSYS.

Implement them using the RTC Time Compensation Register. TCR[7:0]
configures the number of 32.768 kHz cycles per second as
(32768 - value) with value a two's-complement -128..+127, so a
positive value shortens the second and speeds the counter up,
matching the counter API sign convention. TCR[15:8] (CIR, interval
minus one) is kept at 0 to compensate every second, giving
ppb = value * 1e9 / 32768 (~30518 ppb per LSB, range ~+/-3.9M ppb).
set() rejects out-of-range values with -EINVAL and get() reports the
programmed (quantized) TCR/CIR value so a set()/get() round-trips at
the hardware resolution. The register is double buffered and safe to
write while the counter runs. Compensation counts oscillator cycles,
so the ops return -ENOTSUP when the prescaler runs from the LPO
clock.

Validated on frdm_k64f with tests/drivers/counter/counter_basic_api
(CONFIG_COUNTER_CALIBRATION=y): suite passes including the new
set/get calibration case sweeping +/-200000 ppb.

Link: K64 Sub-Family Reference Manual Rev.2 - ch44 RTC_TCR (44.2.4)
Signed-off-by: Holt Sun <holt.sun@nxp.com>
2026-07-22 11:12:57 +01:00
Benjamin Cabé
db3897bb6c drivers: display: max7219: Store shadow buffer row at loop index
The write loop read the retained row state from digit_buf[py] but
stored the updated segment back to digit_buf[y], so only the first
row of the shadow buffer was ever updated and later partial writes
merged against stale row data. Store at the loop index.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:12:31 +01:00
Benjamin Cabé
d36d911cfb drivers: display: renesas_lcdc: Derive HSYNC polarity from hsync-active
The HSYNC polarity was computed from the vsync-active timing
property, a copy-paste from the VSYNC line above, so a panel with
different sync polarities got the wrong HSYNC polarity. Use
hsync-active.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:12:19 +01:00
Benjamin Cabé
0a5bbe5524 drivers: flash: si32: Fix alignment check return values
flash_si32_valid_range() returns bool, but the write alignment
checks returned -EINVAL, which converts to true and marks
misaligned writes as valid. An odd size then made the write loop
read one byte past the source buffer. Return false as the other
checks do.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:12:10 +01:00
Benjamin Cabé
3260dea043 drivers: adc: ad405x: Fix async read callback name
The API table referenced ad405x_adc_read_async, which does not exist;
the function is adc_ad405x_read_async, so builds with
CONFIG_ADC_ASYNC failed.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:12:01 +01:00
Benjamin Cabé
57bdff230d drivers: pwm: silabs_timer: Fix channel bounds checks
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>
2026-07-22 11:11:50 +01:00
Benjamin Cabé
a12a50f713 drivers: pwm: max31790: Fix channel bounds checks
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>
2026-07-22 11:11:39 +01:00
Benjamin Cabé
9bcf962b9b drivers: clock_control: alif: Convert source field width to a mask
The clock source mux update used the encoded field width (in bits)
directly as the clear mask, so only part of a multi-bit source field
was cleared and stale select bits could survive. Convert the width to
a bit mask with BIT_MASK().

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:11:30 +01:00
Benjamin Cabé
5a0f490e5b drivers: gpio: mcux_rgpio: Fix pinmux copy size
The memcpy used sizeof(pin_cfg), reading a whole pinctrl_soc_pin from
a single pinmux array element and past the end for the last pin. Use
sizeof(pin_cfg.pinmux).

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:11:20 +01:00
Benjamin Cabé
652d3ca81b drivers: pinctrl: rza2m: Fix POC0/POCSEL0 clear mask
The PIN_POSEL case AND-ed the two disjoint bit masks, producing 0, so
the old POC0/POCSEL0 values were never cleared and could not be set
back to zero. OR the masks, matching the POC2/POC3 cases.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:11:08 +01:00
Benjamin Cabé
b3bb5c89a0 drivers: clock_control: rza2m: Return an error for invalid dividers
The invalid divider-combination path returned !EINVAL, which is 0, so
rejected FRQCR combinations were reported as success without
programming the register. Return -EINVAL.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:10:57 +01:00
Benjamin Cabé
2377f6d625 drivers: spi: smartbond: Pass device to PM lock release in ISR
The async completion path handed the driver data pointer to
spi_smartbond_pm_policy_state_lock_put(), which expects the device and
forwards it to pm_device_runtime_put(). Pass dev, as every other call
site does.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:10:47 +01:00
Benjamin Cabé
33d45497e0 drivers: clock_control: mcux_scg: Fix FIRCDIV1 feature guard
The FIRC async div1 case was guarded by a misspelled
FSL_FEATURE_FSL_FEATURE_SCG_HAS_FIRCDIV1 macro that never exists, so
the clock was compiled out on every SoC and rate queries returned
-EINVAL. Use the correct feature macro name.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:10:20 +01:00
Benjamin Cabé
a3d7303542 drivers: intc: intel_vtd: Fix delivery mode selection
The fallback condition used ||, which is always true for two different
constants, so every interrupt was forced to IOAPIC_LOW delivery and a
requested IOAPIC_FIXED mode was discarded. Use &&.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:09:45 +01:00
Benjamin Cabé
5634d9097e drivers: intc: nxp_pint: Fix pin bounds checks
Four functions validated the pin index with '>' against
ARRAY_SIZE(pin_pint_id), letting pin == ARRAY_SIZE read one element
past the end of the array. Use '>=', matching nxp_pint_pin_enable().

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:08:43 +01:00
Benjamin Cabé
e4ce091487 drivers: clock_control: stm32f4: Fix missing comma in PLL SAI config
The STM32F413/F423 PLL configuration merged the R divider and post-R
divider into one macro argument due to a missing comma, so
LL_RCC_PLL_ConfigDomain_SAI() received four arguments instead of five
and the branch did not compile when selected.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:08:21 +01:00
Benjamin Cabé
c07bc03d9d drivers: clock_control: stm32mp13: Use SPI clock getter for SPI1
The SPI1 rate query passed an SPI clock-source selector to
LL_RCC_GetUARTClockFreq(), returning a bogus frequency. Call
LL_RCC_GetSPIClockFreq() like the other SPI cases and the mp1/mp2
drivers.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:08:21 +01:00
Benjamin Cabé
f474b557bf drivers: clock_control: stm32h7: Fix TIMPCLK2 base clock
The APB2 timer clock computed its rate from apb1_clock while testing
the APB2 prescaler, so APB2 timers reported APB1's frequency whenever
the prescaler exceeded the threshold. Use apb2_clock, as the H7RS
branch and every sibling series driver do.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:08:21 +01:00
Benjamin Cabé
9d47b1c967 drivers: sensor: icm40627: Fix undefined variable in init error path
icm40627_init() logged a failed bus check through an undeclared
'config' pointer and a nonexistent bus.bus member, breaking the build
when the driver is compiled. Point LOG_ERR_DEVICE_NOT_READY at the
underlying I2C bus device.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:07:46 +01:00
Benjamin Cabé
8d1d65c4b6 drivers: sensor: mpu9250: Make die temperature channel unconditional
The SENSOR_CHAN_DIE_TEMP case sat inside the CONFIG_MPU9250_MAGN_EN
guard, so temperature reads returned -ENOTSUP with the magnetometer
disabled even though the register is always fetched.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:07:46 +01:00
Benjamin Cabé
fc09bf7096 drivers: sensor: tad214x: Fix angle full-scale divisor and overflow
The angle conversion divided by 65635 instead of the 16-bit full
scale 65535, and raw_val * 36000 overflows signed 32-bit for large
readings. Use 65535 and widen to uint32_t.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:07:46 +01:00
Benjamin Cabé
0f2e48108e drivers: sensor: tsl2540: Fix analog gain configuration
CFG2 was written with the CFG1 bit pattern so the AGAINMAX/AGAINL
bits were never programmed, and the 128x case loaded the CFG2
register value (20) into the lux gain instead of TSL2540_AGAIN_S128
(140).

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:07:37 +01:00
Benjamin Cabé
456baea0d3 drivers: sensor: si7210: Fix 2000G scale coefficient OTP addresses
The 2000G A3-A5 OTP addresses jumped from 0x29 to 0x30-0x32 instead
of continuing at 0x2A-0x2C, pointing at the wrong registers.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:07:29 +01:00
Benjamin Cabé
a74c96af99 drivers: gpio: adp5585: Configure input pins as inputs
The GPIO_INPUT branch wrote adp5585_pin_output into the direction
register, so pins requested as inputs were driven as outputs.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:07:15 +01:00
Benjamin Cabé
d1fabcf3a7 drivers: i2c: bflb: Clamp phase3 based on its own value
The phase3 clamp tested phase0, so phase3 could overflow its one-byte
register field. Test phase3.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:06:50 +01:00
Benjamin Cabé
0993ce94a3 drivers: serial: silabs: Fix IRQ lock leak in usart rx_buf_rsp
uart_silabs_async_rx_buf_rsp() returned -EBUSY/-EACCES without
releasing the irq_lock taken at entry, leaving interrupts disabled.
Unlock before the early returns.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:06:30 +01:00
Benjamin Cabé
b41c729139 drivers: serial: silabs: Fix IRQ lock leak in eusart rx_buf_rsp
eusart_async_rx_buf_rsp() returned -EBUSY/-EACCES without releasing
the irq_lock taken at entry, leaving interrupts disabled. Unlock
before the early returns.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:06:30 +01:00
Benjamin Cabé
b6938fb624 drivers: serial: uart_rzt2m: Fix baud table bounds check
The enum index guard used '>' against ARRAY_SIZE, allowing a read one
element past the end of baud_settings[]. Use '>='.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:06:08 +01:00
Benjamin Cabé
68319b378d drivers: input: renesas_ra_ctsu: Report touched buttons as pressed
The button callback runs only for buttons whose status bit is set but
reported value 0, so presses were never delivered. Report 1 like the
renesas_rx_ctsu driver.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:05:30 +01:00
Benjamin Cabé
58f4292cd9 drivers: sensor: mmc56x3: Apply new auto-self-reset value on change
The reconfigure path detected an auto_sr change but programmed the
old value, so the attribute never took effect. Pass the new value.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:05:18 +01:00
Benjamin Cabé
02240c6b0e drivers: sensor: afbr_s50: Fix misplaced comparison in BUILD_ASSERT
The dual-frequency assertion placed '== 0' inside the DT_INST_PROP
property-name argument. Move the comparison outside the macro call,
matching the assertion below it.

Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
2026-07-22 11:05:07 +01:00
Venkatesh Odela
91d808ec34 drivers: mdio: xlnx_gem: extend MDIO idle timeout
Replace fixed retry polling (~500 us) with WAIT_FOR() and a configurable
idle timeout defaulting to 1 s, so slow PHY bring-up on some platforms
can complete before read/write operations fail with -ETIMEDOUT

Signed-off-by: Venkatesh Odela <venkatesh.odela@amd.com>
2026-07-22 11:04:37 +01:00
Jordan Yates
41a65298dd modem: cellular: default 127 byte MTU for nRF93M1
Default to the larger MTU when using a nRF93M1, the default size fails
to boot `samples/net/cellular_modem` due to dropped frames.

Signed-off-by: Jordan Yates <jordan@embeint.com>
2026-07-22 11:04:22 +01:00
Jordan Yates
67b7fb5810 modem: cellular: vendor: move PPP pointer to config
Move the PPP instance pointer from the `struct modem_cellular_data`
object to `struct modem_cellular_config`. The pointer is automatically
discovered in the `MODEM_CELLULAR_DEFINE_INSTANCE` macro through
`&MODEM_CELLULAR_INST_NAME(ppp, inst)`, which works for all in-tree
modems.

As a result, there are no longer any fields in
`struct modem_cellular_data` that are set at compile time. This saves
~4kB on ROM (for nRF93M1) as the variable no longer needs to exist in
`.data`.

Signed-off-by: Jordan Yates <jordan@embeint.com>
2026-07-22 11:03:27 +01:00
Jordan Yates
abc251ab61 modem: cellular: vendor: move chat config to vendor struct
Move the specification of the chat delimiter and filter strings to the
vendor configuration strings. This is a step towards removing all
compile time field setting of the `struct modem_cellular_data` object
in drivers.

Signed-off-by: Jordan Yates <jordan@embeint.com>
2026-07-22 11:03:27 +01:00
Jordan Yates
523b878e17 modem: cellular: vendor: lex10q1: fix compilation
The `lex10q1` driver was merged without any tests, and therefore no
longer compiles. Fix the driver, and add tests.

Signed-off-by: Jordan Yates <jordan@embeint.com>
2026-07-22 11:03:27 +01:00
Paulo Santos
c19ef4f72b modem: cellular: report EG25-G serving-cell info via QENG
Add AT+QENG="servingcell" to the Quectel EG25-G periodic script and decode
the LTE serving-cell report into the generic network-status event, so
consumers receive cell identity (MCC/MNC/CI/PCI/TAC), EARFCN, band and
RSRP/RSRQ rather than only registration state and RSSI.

The handler fills struct cellular_evt_network_status and reports it via
modem_cellular_emit_network_status(). Only the LTE report is decoded;
other radio access technologies use a different field layout and a shorter
report (state SEARCH/LIMSRV) is ignored via an argument-count guard.

Signed-off-by: Paulo Santos <pauloxrms@gmail.com>
2026-07-22 11:02:14 +01:00
Paulo Santos
3381a2bb4c modem: cellular: emit nrf93m1 network status only on change
Route the nrf93m1 %BCINFO handler through
modem_cellular_emit_network_status() so the periodic poll raises
CELLULAR_EVENT_NETWORK_STATUS_CHANGED only when the serving cell differs
from the last report.

Signed-off-by: Paulo Santos <pauloxrms@gmail.com>
2026-07-22 11:02:14 +01:00
Paulo Santos
b699833666 modem: cellular: cache and expose last network status
Cache the last reported serving-cell status and add an optional
get_network_status driver op plus cellular_get_network_status(), so it can
be read on demand rather than only through the
CELLULAR_EVENT_NETWORK_STATUS_CHANGED callback. The snapshot is returned
under the API lock; -ENODATA before the first report or after a
registration change until the next poll, -ENOSYS where unimplemented.

modem_cellular_emit_network_status() stores the latest status and emits the
event only when it changed, ignoring signal quality (rsrp/rsrq) so periodic
pollers do not re-fire it on signal fluctuation. The cache is dropped on a
registration change so a stale serving cell is not reported after
re-registering.

Signed-off-by: Paulo Santos <pauloxrms@gmail.com>
2026-07-22 11:02:14 +01:00
Fin Maaß
7233acb33d drivers: ethernet: mdio: use mdio without ethernet
allow use of mdio without ethernet and networking.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-07-22 11:01:22 +01:00
Aric Radzin
b7d95129cc drivers: adc: add periodic read option to adc shell
Add an optional `period_ms` argument to the `read` command of adc shell
that makes the `read` command periodcially read and print until any key is
pressed.

Signed-off-by: Aric Radzin <aric.radzin@gmail.com>
2026-07-22 10:59:55 +01:00
Muhammed Asif
be1fdf2cf7 drivers: microchip: pic32cmjh: Updates counter tcc g1 driver
- Updates the driver to support families which have only one
  IRQ line for all the channel interrupts and overflow interrupt
- Adds single ISR for handling the interrupts for such cases.
- Updates custom return values to standard return values

Signed-off-by: Muhammed Asif <asifp3104@gmail.com>
2026-07-22 10:59:44 +01:00
minyuan xue
ba9f12abd1 drivers: pwm: add ameba pwm driver
Add realtek ameba pwm driver.

Signed-off-by: minyuan xue <minyuan_xue@realsil.com.cn>
2026-07-22 10:58:45 +01:00
Nicolas Pitre
4f6aebf11c drivers: timer: core: skip redundant rearms and protect catch-up reloads
The kernel re-evaluates its earliest timeout on every add and abort; a
timeslice reset is one of each, so a syscall-heavy thread produces a
sustained stream of sys_clock_set_timeout() calls, most of them landing
on the same tick boundary as the previous one. For a RELOAD backend
every reprogram restarts the hardware counter, so such a stream keeps
any period from ever completing and can postpone the announce for the
stream's duration; it also multiplies the reprogram windows in which
emulated timers misbehave (QEMU's SysTick holds VAL at zero around a
reprogram, and its cancelled-period callbacks race the vCPU).

Two guards in timer_core_arm(), both cheap and backend-agnostic:

- Deadline dedup: cache the armed tick-aligned deadline and program the
  hardware only when it moves. The announce invalidates the cache, as
  do the drivers whose sys_clock_unused() stops or reprograms the
  hardware behind the core's back (cortex_m_systick, cmsdk_apb).

- Catch-up latch: when the reload is floored at TIMER_CORE_MIN_DELAY
  (deadline due, or the un-announced span about to overrun
  TIMER_CORE_CYCLES_MAX), leave an already in-flight floored reload
  alone instead of restarting it, so the fire that resolves the
  catch-up gets through even under a rearm stream faster than the
  floor. Cleared by the announce.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 22:52:09 -05:00
Nicolas Pitre
2e1bbb20d0 drivers: timer: openrisc: do not drop a comparator match when rearming
Writing TTMR clears a pending TTMR.IP. The kernel rearms the comparator
on every timeout add and abort (a timeslice reset is one of each), so
under a rearm-heavy workload the write that follows a comparator match
can eat the match before the exception is taken. Announces then only
happen when a later target is reached cleanly; with the 28-bit compare
domain a long enough streak of eaten matches lets the masked elapsed
delta saturate and alias, and uptime drifts behind real time.

Write TTMR with IP set when arming (IP is cleared by writing 0 and
unaffected by writing 1) so a match that raced the rewrite stays
pending, and acknowledge only in the ISR, which now clears the pending
bit in both the tickless and the tickful case.

The rearm catch-up loop in this driver has a livelock of its own,
addressed separately (it also affects mips_cp0 and xtensa).

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 22:52:09 -05:00
Nicolas Pitre
c7fa0dbf01 drivers: timer: riscv_supervisor: declare the 64-bit counter width
Same omission as the one fixed for apic_tsc, hpet and
riscv_machine_timer: the driver reads the 64-bit "time" CSR and
declares TIMER_CORE_64BIT_CYCLES, but without TIMER_CORE_CYCLES_WIDTH
the generic core masks deltas at the native register width, so an RV32
build aliases any delta beyond 2^32 cycles and the SBI deadline ends up
a whole 2^32-cycle period behind the counter.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2026-07-21 22:52:09 -05:00
Anas Nashif
11b5349051 drivers: timer: declare 64-bit counter widths to the generic core
The generic timer core masks announce deltas to TIMER_CORE_CYCLES_WIDTH,
which defaults to the native register width. The hpet, riscv_machine
and apic_tsc conversions kept their genuinely 64-bit counters but did
not declare the width, so a 32-bit build silently masks every delta to
32 bits (TIMER_CORE_64BIT_CYCLES only emits sys_clock_cycle_get_64(),
it does not widen the mask). The pre-conversion drivers all carried
full 64-bit tick math.

On 32-bit x86 with the HPET this is fatal as soon as more than 2^32
cycles (43 s at 100 MHz) elapse without an announce: the masked delta
aliases modulo 2^32, the announce reports ~0 ticks, and the re-armed
deadline lands a whole 2^32-cycle period behind the counter. The
comparator helper checks its target against the full 64-bit count, so
it treats the deadline as past and pins the comparator to "now",
firing immediately; the following announce again aliases to 0 ticks
and re-arms behind. The result is a permanent interrupt storm with
kernel time frozen at tick zero.

Declare TIMER_CORE_CYCLES_WIDTH 64 in all three drivers, as the
arm_arch, intel_adsp and esp32 conversions already do. For riscv
(64-bit mtime on RV32) and apic_tsc (64-bit TSC) the aliasing is the
same latent defect awaiting a long enough gap.

Assisted by Claude (claude-opus-4-8).
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-21 22:52:09 -05:00
Anas Nashif
0bbd4843fa drivers: timer: fix the equality-match compare catch-up livelock
The generic-core conversions gave the equality-match COMPARE drivers
(openrisc_tick_timer, mips_cp0_timer, xtensa_sys_timer) a catch-up
loop that pushes a too-near target ahead of the counter:

  while (diff(next, now) < MIN_DELAY) {
          next = now + MIN_DELAY;
          set_compare(next);
          now = get_count();
  }

The exit condition demands the target still be a full MIN_DELAY ahead
after re-reading the counter, but the counter keeps moving between the
compare write and the re-read, and each retry re-arms exactly
MIN_DELAY ahead of the previous, already stale, read. The loop can
therefore only exit if the counter advances zero cycles per iteration.
Wherever it advances every iteration the loop spins forever: under
QEMU icount (qemu_or1k runs with -icount shift=6, advancing TTCR ~1.3
cycles per instruction) entry means a deterministic livelock, and on
real hardware whose count runs at CPU speed (Xtensa CCOUNT) the same
holds.

An equality comparator only requires that the target was still ahead
of the count when the compare register was written, and a post-write
count read that is still behind the target proves exactly that. Relax
the exit check to accept any strictly-future target, the same
convergent form hpet.c already uses; a retry then lands MIN_DELAY
ahead of a fresh read and is confirmed by the next one. The other
COMPARE conversions are unaffected: hpet already checks this way, and
esp32/intel_adsp bump once before the write against >=-style alarms.

Assisted by Claude (claude-opus-4-8).
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-21 22:52:09 -05:00