resolution-gpios is read as two lines, RES0 and RES1, through
GPIO_DT_SPEC_INST_GET_BY_IDX_OR() with an empty fallback, while
have_resolution_pins only checks that the property exists. A node with
one entry, or with one of the two set to <0>, builds and then fails at
init with -ENODEV because that spec has no port.
Make both a build error. Omitting the property stays valid, the binding
says the pins may be hard-wired.
Signed-off-by: Hsiu-Chi Tsai <hctsai@linux.com>
transceive_packet() left the RX interrupt enabled after a receive
timeout, so late bytes were written through rx_buf.data into the stack
frame of the function that had already returned.
Signed-off-by: Flavio Ceolin <flavio@hubble.com>
The packet length from the sensor header was passed to uart_fifo_read()
without checking it against the receive buffer, letting a declared body
larger than the buffer overflow the caller's stack packet.
Signed-off-by: Flavio Ceolin <flavio@hubble.com>
The pressure compensation computed X2 as B1 * B6^2 / 2^27 because the
divisor constant was 0x8000000 instead of 0x10000000. The datasheet
specifies X2 = (B1 * (B6 * B6 / 2^12)) / 2^16, i.e. B1 * B6^2 / 2^28,
so reported pressure was too low by up to ~10 hPa at temperature
extremes.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The SQE-exhaustion error path cleared data->stream.iodev_sqe before
passing it to rtio_iodev_sqe_err(), so the pending submission was always
completed with a NULL pointer. Cache the pointer in a local first, as the
two neighbouring error paths already do.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The millimetre conversion evaluated 2^31 / (2^shift * 1e6) as an integer
division before applying it, truncating the scale factor to 0 for shift
>= 12 and to a ~4.6% low value otherwise. Fold the 2^31/2^shift into a
single left shift applied before the 1e6 divide.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The streaming path only read the RESOLUTION X/Y LOWER registers, leaving
the high bytes of the packed 16-bit resolution values in the RTIO
mempool buffer uninitialized, which made the decoder compute a bogus CPI
and shift. Read all four registers, as the one-shot path already does,
so the resolution comes from the sensor itself.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The stream completion callback armed the data-ready backup timer before
flushing the bus CQEs, then errored the SQE without clearing
data->stream.iodev_sqe, so the timer later dereferenced an SQE already
returned to the RTIO pool. Arm the timer only after the error check, use
handle_result_on_error() on the failure path, and stop the timer there.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
paa3905_stream_submit() and pat9136_stream_submit() switched on
read_config->channels[i].chan_type while comparing SENSOR_TRIG_*
values and reading triggers[i].opt. channels and triggers alias the
same union but have different strides unless enums are 2 bytes wide,
so any entry past index 0 decoded garbage and the stream was rejected
with -ENOTSUP. Switch on read_config->triggers[i].trigger instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
After an I2C software reset the FXAS21002 NACKs bus transactions
until its boot sequence finishes. The datasheet states that the
digital interface is accessible 50 ms after VDD/VDDIO power-up or
reset. Sleep that interval before polling CTRL_REG1 so initialization
does not fail while the device is still booting.
Signed-off-by: Sudarshan Iyengar <sudarshan.iyengar@alifsemi.com>
The return value of icm4xxxx_set_accel_ln_bw() was dropped, so the
following "if (err < 0)" guard re-tested the stale gyro result and
could never catch a failure. Assign the result to err so that a
failing accel low-pass filter configuration aborts initialization.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The FIFO flush branch of the stream completion handler prepared the
FIFO_CONFIG2 write SQEs but never submitted them, leaving the flush
stranded in the bus RTIO queue until an unrelated submission ran it.
Submit the bus context right after preparing the write.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The event handler dereferenced data->stream.iodev_sqe to fetch the
read config before the NULL/canceled guard that exists precisely to
handle a missing submission. Defer the assignment until after the
guard. The same defect in icm566xx is fixed as well.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
icm45686_get_shift() did not handle ICM45686_DT_GYRO_FS_15_625, so
decoding any gyro channel failed with -EINVAL (and left the FIFO
decoder's shift uninitialized) when that full-scale range was
selected in devicetree. Add the missing case with shift 4, following
the existing progression.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The SENSOR_CHAN_APEX_MOTION case in icm45686_channel_get() had no
break statement, so it fell through to the default case and always
returned -ENOTSUP even though valid APEX data had been written to
the output values. Add the missing break so the channel returns 0.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The driver read the WHO_AM_I register under a "Confirm ID Value
matches" comment but never compared the result, so init succeeded on
any device that ACKed. Store the expected per-variant ID in the
config and return -ENODEV on mismatch.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The SPI burst read discarded 3 leading bytes, but the device's address
phase is only 2 bytes long, so every sample was shifted by one register.
Skip 2 bytes instead, matching the single-byte read and write paths.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
Fixes various issues with Kconfigs, including:
- Redundent `default n` on bools
- Not select deprecated on supposed deprecated symbols
- Using the wrong indentation
- Not having [DEPRECATED] in the prompt, or not having it at the
end
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
Add a locking to synchronize fetch with the actual sample fetching, on
by default as that's the API contract, but leave an option to turn it
off if needed, noting that that's not the normal API behavior.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
The current rts sample_fetch() implementation has a sleep loop up to
50ms to wait for the most recent sample, this can be problematic if the
function is called from a shared thread, for example from the sysworkq.
The advantage is it guarantees to get a recent sample, but in practice
that's rarely necessary for a fan control loop, and having the most
recent sample is probably good enough, and that's actually how other EC
tachometer drivers are implemented.
Rework the rts5912 tach driver to remove the sample_fetch() sleep
function, instead use the sample_fetch() function to start a sample
fetching asynchronously and let channel_get() return the most recent
available sample.
Note that the tachometer relies on the system clock, hence it returns
bogus values if the system happens to go into sleep during sampling.
Additionally it returns bogus samples on the first iteration after
waking up (presumably because it was already sampling from a partially
idle clock) and for the next sample as well (no idea why), so add the
necessary guards to keep the system awake during sampling, but also a
function to optionally discard the first two samples.
The discard option is off by default as in the normal use case of this
device the fan is only used while the application processor is on, and
in that condition the EC is normally stopped from entering suspend state
entirely, so it probably won't be needed, but there's no harm leaving
some code to handle that condition if it becomes necessary down the
road.
Note that there's quite few checks on the asynchronous functions to
avoid various potential race conditions between the interrupt and
overflow counter.
Also note, the tach seems to have a "limit" register and interrupt that
seemingly could work in place of timeout, but I wasn't able to make it
work correctly for some reasons.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
The runtime magnetometer ODR table started with a bogus 0 Hz entry
copied from the accelerometer table, shifting every M_ODR code by one
so each requested rate programmed the next one up, and 100 Hz wrote a
reserved code. Drop the leading entry so the array index matches the
CTRL_REG5_XM M_ODR encoding used by LSM9DS0_MFD_MAGN_DEFAULT_M_ODR.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
SENSOR_CHAN_DIE_TEMP returned the raw OUT_TEMP_[LH]_XM count directly
as val1, so a die a few degrees above the reference was reported as
hundreds of degrees. Scale the 12-bit right-justified two's complement
sample by its 8 LSB/degC sensitivity and apply the ~25 degC reference
offset, re-normalising the sign from bit 11.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The chip communicates in SPI mode 3 with a maximum clock of 2 MHz
(PAA3905E1-Q datasheet, section 6.0). The bus configuration left the
clock polarity and phase at mode 0, where every register read returns
the value shifted right by one bit: the product ID 0xA2 reads back as
0x51 and probing fails unless the devicetree node happens to set
spi-cpol and spi-cpha. Set both mode bits in the driver and assert the
clock limit at build time, so correct operation does not depend on
per-board devicetree flags and an out-of-spec node fails the build
instead of running the bus out of contract.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
A stationary sensor reports no motion for every sample, so at the
12.6 Hz streaming rate the warning floods the console with a condition
that is expected rather than exceptional.
Signed-off-by: Luis Ubieda <luisf@croxel.com>
The chip rewrites the LED control register on its own when its
automatic mode switching runs, so the state written during
configuration does not persist: a device configured with the LED
disabled ends up strobing again a few seconds after init. Extract the
LED control sequence into paa3905_apply_led_config() and re-apply it
from the stream path roughly once a second, so the devicetree
configured state is authoritative across mode switches.
Signed-off-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
lis2dh_trigger_anym_tap_set() tears down both INT2 event sources
(any-motion and tap) and disables the GPIO interrupt before storing the
new handler, but returned early on handler == NULL, permanently killing
the other trigger still registered on that line. Only return early when
neither handler is registered, so lis2dh_start_trigger_int2() re-arms
whichever source remains.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The runtime ODR setter only rejected 1620 Hz outside low power mode,
so 5376 Hz wrote the reserved CTRL_REG1 code 0b1010 in normal/high
resolution mode, and 1344 Hz in low power mode programmed code 0b1001
which means 5376 Hz there. Reject both unsupported combinations with
-ENOTSUP.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The raw temperature is a left-justified two's complement value, so the
fractional bits are always a positive addend to the signed integer part.
Negating the fraction for sub-zero readings moved them further from zero
(-0.25 C was reported as -1.75 C); renormalize val1/val2 instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
lis2dh_spi_update_reg() discarded the result of the register read and
merged the mask into an uninitialized stack byte, writing garbage bits
back to the device while reporting success. Propagate the read error
instead, matching the I2C backend's contract.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
lis2de12_enable_xl_int() hard-coded the CTRL_REG3 I1_ZYXDA routing bit
to 1, so disabling the data-ready trigger left INT1 asserted with a NULL
handler, wedging lis2de12_handle_interrupt() in an endless status-read
loop. Program the bit from the enable argument and leave the handling
loop when no handler is registered.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
Implement a generic emulated sensor that echoes back configured sensor
readings. This simplifies testing of higher level libraries and drivers
that depend upon querying a device exposing the sensor API.
Signed-off-by: Jordan Yates <jordan@embeint.com>
The decoder scaled the compensated gas resistance by 2^11 and narrowed
the int64 product to int32 without saturating, so readings above
1,048,576 ohms wrapped and were decoded as negative resistances. Widen
BME680_GAS_SHIFT to 24 to cover the ~13.2 Mohm output range of the
Bosch compensation, and clamp the conversion result to int32 range.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The RTIO chain waited for the heater duration plus a flat 25 ms, which
does not cover the TPH and gas conversion time (43 ms with the default
oversampling), so the FIELD0 read consumed the previous measurement.
Compute the wait from the configured oversampling settings instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
bme680_sample_fetch() polled the new-data status bit for a hard-coded
250 ms, which is far shorter than the 1943 ms heater duration selected by
CONFIG_BME680_HEATR_DUR_ULP, so every fetch returned -EAGAIN. Derive the
poll budget from BME680_HEATR_DUR_MS instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The channel configuration loop accumulated vbus_mode into the byte
written as the NEG_PWR_FSR MSB (CFG_VS1..VS4) and vsense_mode into the
LSB (CFG_VB1..VB4), so both full-scale ranges were programmed into the
wrong halves of the register while the sample decoding still used the
modes as declared in devicetree, yielding silently wrong readings.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The 128-bit overflow guard shifted int128_t.high, an unsigned field, so
any negative accumulated power made the discarded bits non-zero and the
read failed with -E2BIG. Compare the arithmetically shifted high word
against the sign of the reconstructed value instead.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
pac194x_configure_channels() ended init by setting every CHn_OFF bit
and left data->channels[].enabled cleared, so sample fetch read nothing
and every channel get returned -ENODATA. Only turn off the channels the
devicetree does not describe, and mark the configured ones enabled.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The bmp581 driver was losing 6 bits of precision when converting
the raw temperature and pressure values to compensated values.
This was due to an early truncation while parsing raw data.
Signed-off-by: Robyn MILAS <robyn.milas@valotec.com>
Add a new "self-test-enable" DT boolean property that controls whether
the driver performs a self-test during initialization. When the property
is not set, the self-test is skipped.
Previously, adxl367_probe() always ran adxl367_self_test() unconditionally.
Running the self-test adds a noticeable delay to initialization: the
routine sleeps 2 * (4 / ODR) which at the default 12.5 Hz ODR amounts to
approximately 640 ms. Making the self-test opt-in lets applications that
do not need it avoid this cost.
This change matches the semantics already in place for the sibling
adi,adxl355 driver, which uses the same "self-test-enable" property.
Signed-off-by: Dominik Chat <dominik.chat@nordicsemi.no>
adxl367_self_test() computes its post-force-test settling delay as
4 / ODR based on cfg->odr from the device tree. However, in the
probe path the hardware ODR was only programmed later via
adxl367_set_output_rate(), so the device was still running at its
reset-default rate (100 Hz) while the driver waited an interval
derived from the intended ODR.
For cfg->odr <= 100 Hz this only meant a longer-than-necessary wait,
but for 200 Hz and 400 Hz the driver waited less than 4 / 100 Hz,
which could make the self-test read stale acceleration values and
spuriously fail.
Move adxl367_set_output_rate() so it runs before adxl367_self_test(),
right after adxl367_reset(), so that the delay inside the self-test
matches the actual hardware ODR.
Signed-off-by: Dominik Chat <dominik.chat@nordicsemi.no>
Seven sensor emulators declared an empty `struct <dev>_emul_cfg` and
passed its address to EMUL_DT_INST_DEFINE() even though nothing ever
reads emul->cfg. An empty struct is a GNU extension, not valid ISO C,
and icm4268x additionally carried a dummy member under CONFIG_CPP to
keep sizeof() consistent between C and C++.
Drop the structs and their instances and pass NULL for cfg_ptr, as
ltc4286, sb_tsi, bmp581 and bmi323 already do.
Assisted-by: Claude:opus-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
The GPIO callback forwarded its first argument, which is the GPIO
controller device, to the sensor trigger handler instead of the
HDC302x device. Store a back-pointer to the sensor device in the
driver data and pass that to the handler.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
In trigger-on-demand mode, sample_fetch() issued the measurement
command and immediately read the result, but the sensor NACKs the
read until the conversion completes (up to 12.5 ms in LPM0), so every
fetch failed. Sleep for the datasheet measurement duration of the
selected power mode before reading.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The forward conversion borrowed from the integer part on a negative
remainder, producing val1 negative with val2 positive, which violates
the struct sensor_value contract. Keep the integer part truncated
toward zero and let val2 carry the sign of the result.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
The probe fused the CRC check and the ID comparison with &&, so init
only failed when both the CRC was bad and the ID mismatched, making the
identity check dead code for any CRC-valid response. Split it into two
independent guards returning -EIO and -EINVAL respectively.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:fable-5
als31300_convert_to_gauss() built a scale factor by dividing the 500 G
from the part number by the 4096 codes of the 12-bit ADC. Both halves of
that are wrong.
The raw reading is a sign-extended 12-bit quantity, so it spans 2048
codes either side of zero, not 4096. That alone made every
sensor_channel_get() magnetometer reading half the actual field.
More fundamentally, the datasheet does not define the scale as a ratio
of range to code span. It gives sensitivity directly -- 4 LSB/G typical
for the ALS31300-500 -- and states the conversion as
gauss = raw / sensitivity
with a worked example of -1018 LSB / 4 LSB/G = -254 G. The 500 G in the
part number is the "Optimized Sensing Range" (BIN), not the endpoint of
the code range: at 4 LSB/G the 2048 codes actually reach 512 G. Deriving
the scale from 500/2048 therefore implies 4.096 LSB/G, leaving a
systematic 2.3% error in a part whose own sensitivity error spec is
2.5% (3 sigma) on X/Y.
Use the specified sensitivity instead. Raw -1018 now converts to
-254.5 G, reproducing the datasheet example, and raw 2000 lands exactly
on the 500 G range endpoint. Document while here that the driver only
supports the -500 variant, since the -1000, -2000 and -JOY parts are
trimmed to different sensitivities.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:claude-opus-5
The RTIO decoder encoded readings as (value << shift), but Zephyr's Q31
sensor convention is real = q31 * 2^shift / 2^31, so an encoder has to
scale by 2^(31 - shift) to agree with the shift it publishes in the
decoded data header.
The driver advertises a shift of 16 for both magnetic field and
temperature, so every reading came out of the decoder at twice its true
value. Encode with (31 - shift) instead, matching what e.g. the BME280
decoder already does.
On the magnetometer path this was masked until now: the scale factor in
als31300_convert_to_gauss() was low by the same factor of two, so the
two errors cancelled and only the streaming temperature channel was
visibly wrong. The next commit fixes the scale factor.
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Assisted-by: Claude:claude-opus-5
Without a deadline the do/while loop can spin forever if the hardware
never asserts the Conversion Ready Flag (e.g. a faulty device). Add a
5-second timeout using k_uptime_get() so the function returns -ETIMEDOUT
instead of hanging, while preserving immediate propagation of I2C errors.
Signed-off-by: Md Shofiqul Islam <shofiqtest@gmail.com>