The SENSOR_CHAN_MTCH9010_OUT_STATE fetch path called gpio_pin_get_dt()
unconditionally, dereferencing a NULL port when the optional
output-gpios property is absent (e.g. UART-only configurations). Return
-ENOTSUP in that case, mirroring the guard used by the other fetch path.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
config->sleep_time holds the devicetree enum index used as the UART
command argument, but the fetch timeout math treated it as seconds, so
any sleep period of 4 s or more timed out early. Store the period in
seconds separately and widen the timeout values to uint32_t, since
256 s no longer fits in uint16_t once converted to milliseconds.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The decode entry guard rejected any buffer whose first character was
not a digit, so DELTA-only packets carrying a negative delta (e.g.
"-99\n\r") always failed with -EINVAL. Allow a leading minus sign; the
per-format range checks still reject negative measurements.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
Use controller/peripheral and SDO/SDI terminology in sensor drivers,
following coding guideline rule A.2: switch the SPI configuration
constants to SPI_OP_MODE_CONTROLLER and update SPI wiring comments.
For the Broadcom AFBR-S50 sensor, the spi-sdi-gpios/spi-sdo-gpios
devicetree properties (named from the sensor's own perspective per
the OSHWA resolution) replace spi-mosi-gpios/spi-miso-gpios. The old
property names are still accepted, marked as deprecated in the
binding, and used as fallbacks; the Zephyr platform glue in
modules/hal_afbr is updated to the renamed fields. The Broadcom
Argus API names (s2pi_slave_t, S2PI_*) come from the vendor library
and keep their names.
Occurrences that concern I2C rather than SPI (I2C controller ACK
behavior comments in NXP drivers, the lsm6dso sensor-hub I2C master
code using ST HAL APIs and application note quotes) and vendor
register names (TDK MPUREG_MASTER_LOCK) are out of scope and keep
their wording.
Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Add device power management so the sensor can sit under a power domain
that may be unpowered at init. Bring-up moves to a PM_DEVICE_ACTION_TURN_ON
handler, and RESUME/SUSPEND toggle the config register shutdown bit.
One-shot mode keeps the sensor shut down between fetches, so RESUME
leaves the shutdown bit set in that configuration.
Signed-off-by: Corey Wharton <xodus7@cwharton.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>
I belive that
tmp = (int16_t)data->current
is more descriptive and straightforward than
if (INA219_SIGN_BIT(data->current)) {
data->current = ~data->current + 1;
sign = -1;
}
tmp = sign * data->current
Thus to make it consistent with signed conversion which is already
done for SENSOR_CHAN_VSHUNT I propose such cosmetic fix.
Signed-off-by: Lukasz Wiecaszek <lukasz.wiecaszek@gmail.com>
Implementation of ina219 was missing support for
shunt voltage readouts (SENSOR_CHAN_VSHUNT).
This commit fixes that issue.
Signed-off-by: Lukasz Wiecaszek <lukasz.wiecaszek@gmail.com>
Cap the reinitialization retries in the recovery path: after a fixed
number of consecutive failures, with a growing backoff between
attempts, fail the submission with -EIO instead of retrying forever,
so a detached or dead device cannot spin the RTIO work queue.
Guard the hand-off points the recovery flow relies on: submitting a
work item without a checked-out submission is rejected, and an error
reported with no submission in progress returns the driver to idle so
the next submission can recover. Complete a successful recovery with
rtio_iodev_sqe_ok() instead of an error completion carrying result 0.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
Stopping and restarting the measurement timer does not bring the device
back once it reports an error: the data stream stays dead until the
board is rebooted. Argus_StopMeasurementTimer() also blocks, and it was
called for every data-ready trigger seen while the device was in error,
delaying the data evaluation that frees the internal buffer and holding
the device in the failed state.
Track the error and the recovery as explicit states so the stop is done
once per error occurrence and an in-progress recovery is distinguishable
from a new failure. Recover by tearing the Argus handle down and
initializing it again through a shared reinitialization sequence, which
restores the stream in place. The initialization and configuration steps
that afbr_s50_init open-coded are factored into that shared sequence so
the recovery path and the initial bring-up run the same code.
Signed-off-by: Luis Ubieda <luisf@croxel.com>
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
The interrupt handler only exited its drain loop once every data ready
flag in STATUS_REG was clear, but those flags are cleared by reading the
output registers, which only happens from a registered handler. A flag
set for a source with no handler (or a handler deferring the fetch) made
the loop spin forever and never re-enable the GPIO interrupt. Only
consider sources that have a handler registered, cap the number of
iterations, and re-arm the interrupt on a status read error as well.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The enable_{t,xl,g}_int() helpers hardcoded the data-ready route bit
to 1, so a sensor_trigger_set() with a NULL handler never cleared
INT1_CTRL/INT2_CTRL and the sensor kept asserting the interrupt line.
Assign the enable parameter to the route bit instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The sensor hub humidity converters stored the whole relative humidity
value scaled by 1e6 into val2 instead of only the fractional remainder,
so the reading was counted twice (e.g. 45.5 %RH became 90.5 %RH) and
val2 exceeded the 1000000 micro-unit bound. Use
sensor_value_from_float() to pack the value correctly.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The die temperature conversion multiplied the int16_t raw sample by
1000000 in 32-bit arithmetic, which overflows (signed overflow UB) once
the temperature is more than ~8.4 C away from 25 C. Widen to 64-bit
before scaling, matching the lsm6dsv16x driver.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The SENSOR_ATTR_CONFIGURATION handler in lsm6dso16is_gyro_config()
called lsm6dso16is_xl_hm_mode_set(), leaving the gyroscope power mode
untouched while silently changing the accelerometer one. Use
lsm6dso16is_gy_hm_mode_set() so the attribute acts on CTRL7_G.g_hm_mode.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The gyroscope full-scale tables were copied from the lsm6dso driver and
used that part's FS_G encoding, so a gyro-range of 2000 dps yielded a
zero gain (readings always 0 rad/s), 125 dps read past the end of the
tables, and the other ranges applied a wrong sensitivity. Lay the tables
out per the LSM6DSO16IS encoding and index them through a helper that
maps the FS_125 register value.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The RM3100 streaming read acquires five bus SQEs one at a time and, on a
short pool, calls rtio_sqe_drop_all() to clean up. rtio_sqe_drop_all frees
every SQE queued on the shared bus RTIO context, including SQEs still in
flight from another read chain, returning an in-use SQE to the pool. A
later allocation then hands out that SQE with a corrupted back-pointer and
the completion path dereferences it, hard-faulting in the RTIO executor
(observed on I2C RM3100 hardware as a bus fault in the sensor work queue
after "Failed to acquire RTIO SQEs").
Acquire the five SQEs of a chain as one array with rtio_sqe_acquire_array,
which pushes nothing until all five are held and rolls its own back on
shortage, so a partial acquire can no longer orphan or double-free an SQE.
The incomplete NULL check that omitted the two status SQEs is retired with
it. Double the bus context pool from 8 to 16 so a five-SQE chain does not
run the pool short under streaming load.
The one-shot read path still acquires its SQEs individually and returns
early on shortage without preparing them. That is a lower-pressure path
outside the streaming scope of this change and is left to a follow-up.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
In a streaming read-config the channels union member holds the trigger
array, so the encoded channel mask was computed from reinterpreted
trigger data and came out 0, making every streamed frame fail decode
with -ENODATA. A data-ready event always carries all three axes, so
encode a fixed MAGN_XYZ channel spec in the stream path.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
The bus read helpers unconditionally OR the SPI read-address flag into
the register address. On I2C the register address must be sent raw:
with the flag set every read addresses a nonexistent register and
returns zeros, so the sensor appears dead on I2C buses.
Gate the flag on the RTIO bus type so I2C transfers send the plain
register address while SPI behavior is unchanged.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
The event handler drops an interrupt whenever a stream is already in
progress or no submission is armed. During a stall these fire on every
data-ready edge, and one warning per event floods the log backend and
can starve the threads that would clear the stall. Count the dropped
events and emit at most one summary per second so the fault stays
visible without flooding.
A summary that carries the suppressed count is used rather than a plain
rate-limited log (LOG_WRN_RATELIMIT) so the operator sees how many edges
were dropped in the interval, not just that dropping occurred. The
counters and the report deadline live in per-instance driver data so a
two-IMU system attributes and rate-limits each sensor independently
instead of aggregating them into one shared total.
An alternative that removes the busy-path re-entries outright, disabling
the DRDY interrupt on entry to ICM45686_STREAM_BUSY and re-arming it
from icm45686_stream_submit, was considered and set aside: it changes
the pulse-mode interrupt timing for every user of this driver, so it is
left for a separate change validated on hardware.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
icm45686_event_handler loaded read_cfg from
data->stream.iodev_sqe->sqe.iodev->data at function entry, before the
guard that checks whether iodev_sqe is NULL. A data-ready edge that
arrives before a streaming submission is armed therefore dereferenced a
NULL pointer. Handle the no-submission case in its own guard that
ignores the spurious interrupt and returns, keep the cancelled
submission path separate, and defer the read_cfg load until after both
checks.
Add a driver test that invokes the handler with no submission armed and
confirms the interrupt is ignored. The test compiles the stream
translation unit directly with stubbed bus helpers so the guard can be
exercised without a full bus and device instance, and enables
CONFIG_ICM45686_STREAM through Kconfig so the driver data layout matches
the streaming build.
Signed-off-by: James Goppert <james.goppert@gmail.com>
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
icm45686_stream_init passed an uninitialized int_config to
icm456xx_set_config_int, whose purpose there is to disable every INT1
source. The unwritten fields are stack garbage, so the call could
instead enable arbitrary INT1 sources and assert a data-ready edge
before the RTIO stream is armed. The APEX (icm45686.c) and trigger
(icm45686_trigger.c) init paths already memset it to INV_IMU_DISABLE
first, so do the same on the streaming path.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
pgain was shifted by one instead of two, so the selection landed below
the PGAIN field of register 0x8F and was masked away entirely: every
board ran at 1x proximity gain no matter what devicetree asked for.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
The ppulse-length selection was OR'd straight into ppcount, landing in
the PPULSE pulse-count bits instead of PPLEN (bits 7:6) of register
0x8E. Every configuration therefore ran with 4 us pulses, and the 16 and
32 us selections corrupted the pulse count on top of that.
Shift the selection into PPLEN and mask the count to the six bits the
field actually has.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
The pgain, again, ppulse-length and pled-boost enums spelled the 2-bit
register fields they select in hex, i.e. 0x00/0x01/0x10/0x11, so the
last two selections were really 16 and 17 and reached the registers as
such. The pgain entries were also mislabelled, listing 4x twice instead
of the 1x/2x/4x/8x the part supports.
Express each enum as the physical value it selects - gain multipliers,
microseconds and percent - and let DT_INST_ENUM_IDX() turn the selection
back into the register field value, which the enums are already ordered
to match. Devicetree now describes the sensor instead of its register
encoding, and the defaults keep selecting the same settings as before.
While here, give every default the justification the binding guidelines
require, and bound ppulse-count to the 1 to 64 pulses the PPULSE field
can encode.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
The OUTPUT_GAIN register codes 0..3 select a gain of 1/4/8/16, but the
12-bit frequency conversion used the raw code as a power-of-two exponent,
so any non-zero gain reported twice the actual frequency (and a quarter of
the actual capacitance). Map the code to its real log2(gain) instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
fdc2x1x_raw_to_freq() converted raw data using the raw controller
clock, ignoring the per-channel CHx_FREF_DIVIDER the driver programs
at init. The datasheet defines the conversion against the divided
reference f_REFx = f_CLK / CHx_FREF_DIVIDER, so frequency and
capacitance were wrong on any channel with a divider other than 1.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The CHx_FREF_DIVIDER field of CLOCK_DIVIDERS_CHx is 10 bits wide, but
the SET/GET accessors masked it to 9 bits while the field mask covered
bits 9:0, so any divider from 512 to 1023 was programmed as value-512.
Widen both accessors to 0x3FF to match the mask and the binding.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The channel mult/div scale factors are uint32_t, so the sign-extended
sample was converted to unsigned and the division performed unsigned,
turning negative readings into large positive ones (e.g. INA226 shunt
voltage, which uses 2500/1000). Scale in signed 64-bit arithmetic.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
struct ina230_data did not start with a struct ina2xx_data, so the
shared ina2xx_sample_fetch()/ina2xx_channel_get() code, which casts
dev->data to struct ina2xx_data *, wrote raw register bytes over the
cached device pointer used by the alert trigger. Embed the common data
struct as the first member and drop the now unused value fields.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The PM hook only handled TURN_OFF, which the PM core rejects unless the
device is already suspended, so the shutdown and wake sequences were
unreachable and the gauge kept running. Handle SUSPEND to enter shutdown
mode and accept TURN_ON/TURN_OFF as no-ops.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
Exiting shutdown mode causes a POR that reverts the gauge data memory
to its ROM defaults, but data->configured was never cleared, so devices
using zephyr,lazy-load kept reporting values computed from the default
design parameters. Clear the flag on resume so the next sample fetch
reprograms the gauge.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
Following the standard pattern for sensor Kconfig files and
allows access to the named choice symbol QMI8658A_TRIGGER_MODE
from out-of-tree Kconfig files. Also add conditional GPIO select
when any binded DTS node expose a int-gpios property.
Signed-off-by: Stephan Linz <linz@li-pro.net>
The streaming path wrote full interrupt-route structs containing only
its own bit, so arming the DRDY stream trigger cleared the FIFO
watermark/full routing and vice versa, silently losing events when both
are requested. Read-modify-write the route as the trigger path already
does. Also honor the trigger disable flag in the DRDY path, which
unconditionally enabled the route even when asked to disable it.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
On sensor_clock_get_cycles() failure, the submit-sample path called
rtio_iodev_sqe_err() and then jumped to the shared err label, which
called rtio_iodev_sqe_err() again on the same (already freed) SQE.
Drop the first call so the err block performs the single completion.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The FIFO decoder mapped the SLAVEn tag index directly onto the
compile-time sensor hub list, ignoring the runtime detected-device
mapping (shub_ext), so frames were decoded as the wrong channel when
a compiled-in external sensor was not populated. Carry shub_ext and
num_ext_dev in the FIFO header and index through them, and fix the
off-by-one bounds check in lsm6dsv16x_shub_type().
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
lsm6dsv16x_hum_convert() stored the entire relative humidity value in
micro-percent in val2, so converting the sensor_value back to a float
roughly doubled the reading. Store only the fractional remainder in
val2, as required by the sensor_value contract.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
data->accel_freq and data->gyro_freq hold the full mode-encoded ODR
byte (mode in the upper nibble, e.g. 0x18 for HA01 500 Hz), so using
them directly as a column index into lsm6dsv16x_odr_map[3][13] reads
out of bounds for high-accuracy devicetree ODRs. Mask to the low
nibble, which is the actual CTRL ODR field; the mode nibble is already
handled via the row index.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The data-ready streaming path stored the raw full-scale register
index in accel_fs_idx, while the decoder tables are ordered by
g-value. On LSM6DSV32X this made decoded accel samples half their
true value. Convert with LSM6DSV16X_ACCEL_FS_VAL_TO_FS_IDX() as the
one-shot and FIFO paths already do.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The I3C instantiation macro used the non-existent UNTIL_AND instead of
UTIL_AND, making IF_ENABLED silently expand to nothing and dropping the
.rtio_ctx, .iodev and .bus_type initializers, so I3C streaming faulted
on the first interrupt via a NULL RTIO context.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
lsm6dsv16x_sample_fetch() accumulated the return value of the
accel/gyro/temp/shub fetch helpers in 'ret' but ended with 'return 0;',
so bus errors during a fetch were reported as success and stale data
could be served by channel_get. Return 'ret' instead, matching the
sibling lsm6dso driver.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
adxl345_decoder_decode() routes on is_fifo at byte offset 0 to decide
whether to call adxl345_decode_stream(). adxl345_submit_fetch() passes
adxl345_read_sample() a raw RTIO mempool buffer, which is not zeroed,
and adxl345_read_sample() never sets is_fifo, so the flag is whatever
the previous user of that block left behind.
With CONFIG_ADXL345_STREAM=y, a one-shot sensor_read() can therefore be
misrouted into adxl345_decode_stream(), which reads a 12-byte struct
adxl345_fifo_data header out of a buffer sized for the 10-byte struct
adxl345_sample and then iterates on an out-of-bounds fifo_byte_count.
Clear is_fifo explicitly, as adxl362, adxl367 and adxl372 already do.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Maureen Helm <maureen.helm@analog.com>
The streaming decoder divided the raw temperature code by a rounded,
decoder-local 15 LSB/degC before applying the q31 scale, quantising the
result to whole degrees and disagreeing with adxl362_temp_convert().
Scale with the shared ADXL362_TEMP_MC_PER_LSB first and divide last, so
both paths report the same 0.065 degC resolution.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
adxl362_process_fifo_samples_cb() never set the accel_odr field of the
FIFO header, leaving it with stale RTIO pool contents that the decoder
uses to index accel_period_ns[], yielding wrong sample periods or an
out-of-bounds table read. Set it from the cached output data rate.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The RTIO submit path forces a single measurement via CNTL2 but never
updated the cached mode, so after the device automatically returned to
power-down the blocking fetch path skipped its CNTL2 write and failed
with -EBUSY forever. Update the cached mode to power-down accordingly.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The wake-up threshold was only validated against full scale, but WK_THS
is a 6-bit field, so thresholds just below full scale computed a register
value of 64 that the HAL masked down to an almost-zero threshold. Clamp
the computed value to 63 LSBs instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
LIS2DW12_ODR_TO_REG() had no encoding for the power off state, so a
cached ODR of 0 was mapped to 1.6 Hz and PM_DEVICE_ACTION_RESUME
restarted conversions on a sensor configured with odr = <0>. Add an OFF
arm to the macro and keep the cached ODR in sync when a runtime power
off succeeds.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The ODR map was copied from the LSM6DSO driver and listed 1.66/3.33/
6.66 kHz, but the IIS2ICLX ODR_XL field only encodes 0..7 (up to
833 Hz), so requesting a higher rate programmed a reserved code and
reported success. Truncate the map so such requests return -EINVAL.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
iis2iclx_channel_get() accepted SENSOR_CHAN_ACCEL_Z on this 2-axis
part and discarded the -ENOTSUP returned by its helpers, so callers
got success with an untouched sensor_value. Drop the Z case, return
the helper status, and fill the third slot of ACCEL_XYZ with zero.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5