* [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor
@ 2026-03-17 15:03 Francesco Lavra
2026-03-17 15:03 ` [PATCH v8 1/6] iio: imu: st_lsm6dsx: Fix check for invalid samples from FIFO Francesco Lavra
` (5 more replies)
0 siblings, 6 replies; 19+ messages in thread
From: Francesco Lavra @ 2026-03-17 15:03 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Lorenzo Bianconi, linux-iio, linux-kernel
This series adds support for the rotation sensor functionality present in
some chips from the ST LSM6DSX IMU family.
The IIO ABI has been amended to allow the use of floating-point data and
a "quaternion axis" channel modifier in IIO buffers.
Tested on LSM6DSV16X.
Changes from v7 [7]:
- added Lorenzo's Acked-by tag to patch 1
- in st_lsm6dsx_buffer.c, added st_lsm6dsx_check_data() helper function
(Lorenzo)
- added definition of IIO_SCAN_FORMAT_* symbolic constants to restrict
flexibility of what can go in .format (Jonathan)
- re-added @sign description in kernel.doc comment for
struct iio_scan_type, mentioning that @format should be used in new code
(Jonathan)
- in tools/iio/iio_generic_buffer, replaced legacy __fp16 type with
standard-compliant _Float16 (David)
- in tools/iio/iio_generic_buffer, added check for compiler support
(David), so that compilation does not fail with compilers that don't
support _Float16: tested with gcc for x86-64 (supported), for aarch64
(supported), for riscv-64 (not supported), clang for x86-64 (not
supported)
- in tols/iio/iio_utils.h, replaced unsigned with char type for `format`
field in struct iio_channel_info (David)
- renamed "partial quaternion" modifier to "quaternion axis"
- moved new modifier value at the end of enum iio_modifier (David)
- squashed the two words together in the modifier name (Jonathan)
- in ABI doc for new modifier, fixed typo and angle units (David)
- in ABI doc for new modifier, fixed kernel-doc warning (kernel test robot)
- in st_lsm6dsx_fusion.c, added missing header includes (Andy)
Changes from v6 [6]:
- dropped patches 1 and 2 (already picked up by Jonathan)
- added floating-point support to iio-tools (Andy)
- replaced `sign` field in struct iio_scan_type with union instead of
`format` field (David, Jonathan)
- changed [s|u|f] to [f|s|u] in ABI and driver documentation files (Andy)
- removed IIO_CUSTOM channel type in favor of IIO_MOD_PARTIAL_QUATERNION
modifier (David, Andy)
- replaced "sf" with "fusion" in type, variable and function names (David)
- added copyright statement in st_lsm6dsx_fusion.c (David)
- added `ret` variable in st_lsm6dsx_fusion_probe() for better readability
(Andy)
- modified data structure holding the list of available frequencies in
order to replace device attribute with .read_avail callback (David)
Changes from v5 [5]:
- cleaned up FIFO data representation in st_lsm6dsx_read_tagged_fifo() to
avoid casting (Andy, Jonathan)
- renamed 'sign' field to `format` in struct iio_scan_type
- added support for IEEE 754 floating-point format in buffer scan elements
- added custom data type in the ABI (IIO_CUSTOM in enum iio_chan_type)
(Jonathan)
- added driver document in Documentation/iio/ (Jonathan)
Changes from v4 [4]:
- changed data parameter in st_lsm6dsx_push_tagged_data() to __le16 *
(Andy)
Changes from v3 [3]:
- added patch 3 (Andy)
- removed unneeded checks for negative return values in st_lsm6dsx_fusion.c
(Andy)
- replaced st_lsm6dsx_sf_set_page function with
st_lsm6dsx_sf_page_enable/disable (Andy)
- used reversed xmas tree ordering for local variables (Andy)
- added parentheses to MILLI / MICRO in st_lsm6dsx_sf_write_raw (Andy)
- added check for string truncation in st_lsm6dsx_sf_probe (Andy)
Changes from v2 [2]:
- amended description of patch 2 to point out that there are no supported
gyro events (Jonathan)
- removed superfluous parentheses in st_lsm6dsx_fifo_setup (Lorenzo)
- added Lorenzo's acked-by tag to patch 3
- added missing checks of st_lsm6dsx_sf_set_page() return value (Jonathan)
- added comment in st_lsm6dsx_sf_write_raw (Jonathan)
Changes from v1 [1]:
- swapped patches 1 and 2 (Jonathan)
- miscellaneous stylistic changes (Andy)
- fixed usage of MICRO and MILLI constants in st_lsm6dsx_sf_read_raw and
st_lsm6dsx_sf_write_raw (Andy)
- replaced scnprintf() with sysfs_emit_at() in
st_lsm6dsx_sf_sampling_freq_avail (Andy)
- replaced scnprintf() with snprintf() in st_lsm6dsx_sf_probe (Andy)
- clarified in a comment in st_lsm6dsx_set_fifo_odr() that only internal
sensors have a FIFO ODR configuration register (Jonathan)
- modified patch 3 description to explain justification for the extra IIO
device (Jonathan)
- moved page lock from st_lsm6dsx_sf_set_page() to the callers (Jonathan)
- s/magnetometer/gyroscope/ in patch 2 description
[1] https://lore.kernel.org/linux-iio/20260109181528.154127-1-flavra@baylibre.com/T/
[2] https://lore.kernel.org/linux-iio/20260115122431.1014630-1-flavra@baylibre.com/T/
[3] https://lore.kernel.org/linux-iio/20260119100449.1559624-1-flavra@baylibre.com/T/
[4] https://lore.kernel.org/linux-iio/20260121112758.1831077-1-flavra@baylibre.com/T/
[5] https://lore.kernel.org/linux-iio/20260122162335.2020006-1-flavra@baylibre.com/T/
[6] https://lore.kernel.org/linux-iio/20260225100421.2366864-1-flavra@baylibre.com/T/
[7] https://lore.kernel.org/linux-iio/20260304080519.2844101-1-flavra@baylibre.com/T/
Francesco Lavra (6):
iio: imu: st_lsm6dsx: Fix check for invalid samples from FIFO
iio: Replace 'sign' field with union in struct iio_scan_type
iio: tools: Add support for floating-point types in buffer scan
elements
iio: ABI: Add support for floating-point numbers in buffer scan
elements
iio: ABI: Add quaternion axis modifier
iio: imu: st_lsm6dsx: Add support for rotation sensor
Documentation/ABI/testing/sysfs-bus-iio | 48 ++--
Documentation/driver-api/iio/buffers.rst | 7 +-
Documentation/iio/iio_devbuf.rst | 3 +-
drivers/iio/imu/st_lsm6dsx/Makefile | 2 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 28 ++-
.../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 40 ++-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 58 +++++
.../iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c | 235 ++++++++++++++++++
drivers/iio/industrialio-core.c | 1 +
include/linux/iio/iio.h | 19 +-
include/uapi/linux/iio/types.h | 1 +
tools/iio/iio_event_monitor.c | 1 +
tools/iio/iio_generic_buffer.c | 59 ++++-
tools/iio/iio_utils.c | 8 +-
tools/iio/iio_utils.h | 4 +-
15 files changed, 464 insertions(+), 50 deletions(-)
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c
--
2.39.5
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v8 1/6] iio: imu: st_lsm6dsx: Fix check for invalid samples from FIFO
2026-03-17 15:03 [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
@ 2026-03-17 15:03 ` Francesco Lavra
2026-03-17 15:04 ` [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type Francesco Lavra
` (4 subsequent siblings)
5 siblings, 0 replies; 19+ messages in thread
From: Francesco Lavra @ 2026-03-17 15:03 UTC (permalink / raw)
To: Lorenzo Bianconi, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, linux-kernel
The DRDY_MASK feature implemented in sensor chips marks gyroscope and
accelerometer invalid samples (i.e. samples that have been acquired during
the settling time of sensor filters) with the special values 0x7FFFh,
0x7FFE, and 0x7FFD.
The driver checks FIFO samples against these special values in order to
discard invalid samples; however, it does the check regardless of the type
of samples being processed, whereas this feature is specific to gyroscope
and accelerometer data. This could cause valid samples to be discarded.
Fix the above check so that it takes into account the type of samples being
processed. To avoid casting to __le16 * when checking sample values, clean
up the type representation for data read from the FIFO.
Fixes: 960506ed2c69 ("iio: imu: st_lsm6dsx: enable drdy-mask if available")
Signed-off-by: Francesco Lavra <flavra@baylibre.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
.../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 31 +++++++++++++------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index 5b28a3ffcc3d..19232146bd61 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -365,8 +365,6 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr,
return 0;
}
-#define ST_LSM6DSX_IIO_BUFF_SIZE (ALIGN(ST_LSM6DSX_SAMPLE_SIZE, \
- sizeof(s64)) + sizeof(s64))
/**
* st_lsm6dsx_read_fifo() - hw FIFO read routine
* @hw: Pointer to instance of struct st_lsm6dsx_hw.
@@ -537,16 +535,24 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
}
#define ST_LSM6DSX_INVALID_SAMPLE 0x7ffd
+static bool st_lsm6dsx_check_data(u8 tag, __le16 *data)
+{
+ if ((tag == ST_LSM6DSX_GYRO_TAG || tag == ST_LSM6DSX_ACC_TAG) &&
+ (s16)le16_to_cpup(data) >= ST_LSM6DSX_INVALID_SAMPLE)
+ return false;
+
+ return true;
+}
+
static int
st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag,
- u8 *data, s64 ts)
+ __le16 *data, s64 ts)
{
- s16 val = le16_to_cpu(*(__le16 *)data);
struct st_lsm6dsx_sensor *sensor;
struct iio_dev *iio_dev;
/* invalid sample during bootstrap phase */
- if (val >= ST_LSM6DSX_INVALID_SAMPLE)
+ if (!st_lsm6dsx_check_data(tag, data))
return -EINVAL;
/*
@@ -609,7 +615,13 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw)
* must be passed a buffer that is aligned to 8 bytes so
* as to allow insertion of a naturally aligned timestamp.
*/
- u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE] __aligned(8);
+ struct {
+ union {
+ __le16 data[3];
+ __le32 fifo_ts;
+ };
+ aligned_s64 timestamp;
+ } iio_buff = { };
u8 tag;
bool reset_ts = false;
int i, err, read_len;
@@ -648,7 +660,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw)
for (i = 0; i < pattern_len;
i += ST_LSM6DSX_TAGGED_SAMPLE_SIZE) {
- memcpy(iio_buff, &hw->buff[i + ST_LSM6DSX_TAG_SIZE],
+ memcpy(&iio_buff, &hw->buff[i + ST_LSM6DSX_TAG_SIZE],
ST_LSM6DSX_SAMPLE_SIZE);
tag = hw->buff[i] >> 3;
@@ -659,7 +671,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw)
* B0 = ts[7:0], B1 = ts[15:8], B2 = ts[23:16],
* B3 = ts[31:24]
*/
- ts = le32_to_cpu(*((__le32 *)iio_buff));
+ ts = le32_to_cpu(iio_buff.fifo_ts);
/*
* check if hw timestamp engine is going to
* reset (the sensor generates an interrupt
@@ -670,7 +682,8 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw)
reset_ts = true;
ts *= hw->ts_gain;
} else {
- st_lsm6dsx_push_tagged_data(hw, tag, iio_buff,
+ st_lsm6dsx_push_tagged_data(hw, tag,
+ iio_buff.data,
ts);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-17 15:03 [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
2026-03-17 15:03 ` [PATCH v8 1/6] iio: imu: st_lsm6dsx: Fix check for invalid samples from FIFO Francesco Lavra
@ 2026-03-17 15:04 ` Francesco Lavra
2026-03-21 17:22 ` David Lechner
2026-03-17 15:04 ` [PATCH v8 3/6] iio: tools: Add support for floating-point types in buffer scan elements Francesco Lavra
` (3 subsequent siblings)
5 siblings, 1 reply; 19+ messages in thread
From: Francesco Lavra @ 2026-03-17 15:04 UTC (permalink / raw)
To: Jonathan Corbet, Shuah Khan, Jonathan Cameron, David Lechner,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
This field is used to differentiate between signed and unsigned integers.
A following commit will extend its use in order to add support for non-
integer scan elements; therefore, replace it with a union that contains a
more generic 'format' field. This union will be dropped when all drivers
are changed to use the format field.
Opportunistically replace character literals with symbolic constants that
represent the set of allowed values for the format field.
Signed-off-by: Francesco Lavra <flavra@baylibre.com>
---
Documentation/driver-api/iio/buffers.rst | 4 ++--
include/linux/iio/iio.h | 17 +++++++++++++++--
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/Documentation/driver-api/iio/buffers.rst b/Documentation/driver-api/iio/buffers.rst
index 63f364e862d1..e16abaf826fe 100644
--- a/Documentation/driver-api/iio/buffers.rst
+++ b/Documentation/driver-api/iio/buffers.rst
@@ -78,7 +78,7 @@ fields in iio_chan_spec definition::
/* other members */
int scan_index
struct {
- char sign;
+ char format;
u8 realbits;
u8 storagebits;
u8 shift;
@@ -98,7 +98,7 @@ following channel definition::
/* other stuff here */
.scan_index = 0,
.scan_type = {
- .sign = 's',
+ .format = IIO_SCAN_FORMAT_SIGNED_INT,
.realbits = 12,
.storagebits = 16,
.shift = 4,
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index a9ecff191bd9..d48a0ab01b8d 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -176,9 +176,19 @@ struct iio_event_spec {
unsigned long mask_shared_by_all;
};
+/*
+ * Format values in scan type
+ * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
+ * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
+ */
+#define IIO_SCAN_FORMAT_SIGNED_INT 's'
+#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
+
/**
* struct iio_scan_type - specification for channel data format in buffer
- * @sign: 's' or 'u' to specify signed or unsigned
+ * @sign: Deprecated, use @format instead.
+ * @format: Data format, can have any of the IIO_SCAN_FORMAT_*
+ * values.
* @realbits: Number of valid bits of data
* @storagebits: Realbits + padding
* @shift: Shift right by this before masking out realbits.
@@ -189,7 +199,10 @@ struct iio_event_spec {
* @endianness: little or big endian
*/
struct iio_scan_type {
- char sign;
+ union {
+ char sign;
+ char format;
+ };
u8 realbits;
u8 storagebits;
u8 shift;
--
2.39.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 3/6] iio: tools: Add support for floating-point types in buffer scan elements
2026-03-17 15:03 [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
2026-03-17 15:03 ` [PATCH v8 1/6] iio: imu: st_lsm6dsx: Fix check for invalid samples from FIFO Francesco Lavra
2026-03-17 15:04 ` [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type Francesco Lavra
@ 2026-03-17 15:04 ` Francesco Lavra
2026-03-21 17:26 ` David Lechner
2026-03-17 15:04 ` [PATCH v8 4/6] iio: ABI: Add support for floating-point numbers " Francesco Lavra
` (2 subsequent siblings)
5 siblings, 1 reply; 19+ messages in thread
From: Francesco Lavra @ 2026-03-17 15:04 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
linux-iio, linux-kernel
A subsequent commit will add floating-point support to the ABI; enhance
the iio_generic_buffer tool to be able to parse this new data format.
Signed-off-by: Francesco Lavra <flavra@baylibre.com>
---
tools/iio/iio_generic_buffer.c | 59 ++++++++++++++++++++++++++++++----
tools/iio/iio_utils.c | 8 ++---
tools/iio/iio_utils.h | 4 +--
3 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
index bc82bb6a7a2a..a21552c2b190 100644
--- a/tools/iio/iio_generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <poll.h>
#include <endian.h>
+#include <float.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdbool.h>
@@ -89,7 +90,7 @@ static void print1byte(uint8_t input, struct iio_channel_info *info)
*/
input >>= info->shift;
input &= info->mask;
- if (info->is_signed) {
+ if (info->format == 's') {
int8_t val = (int8_t)(input << (8 - info->bits_used)) >>
(8 - info->bits_used);
printf("%05f ", ((float)val + info->offset) * info->scale);
@@ -112,12 +113,28 @@ static void print2byte(uint16_t input, struct iio_channel_info *info)
*/
input >>= info->shift;
input &= info->mask;
- if (info->is_signed) {
+ switch (info->format) {
+ case 's': {
int16_t val = (int16_t)(input << (16 - info->bits_used)) >>
(16 - info->bits_used);
printf("%05f ", ((float)val + info->offset) * info->scale);
- } else {
+ break;
+ }
+ case 'u':
printf("%05f ", ((float)input + info->offset) * info->scale);
+ break;
+#if defined(__FLT16_MAX__)
+ case 'f': {
+ union {
+ uint16_t u;
+ _Float16 f;
+ } converter;
+
+ converter.u = input;
+ printf("%05f ", ((float)converter.f + info->offset) * info->scale);
+ break;
+ }
+#endif
}
}
@@ -135,12 +152,26 @@ static void print4byte(uint32_t input, struct iio_channel_info *info)
*/
input >>= info->shift;
input &= info->mask;
- if (info->is_signed) {
+ switch (info->format) {
+ case 's': {
int32_t val = (int32_t)(input << (32 - info->bits_used)) >>
(32 - info->bits_used);
printf("%05f ", ((float)val + info->offset) * info->scale);
- } else {
+ break;
+ }
+ case 'u':
printf("%05f ", ((float)input + info->offset) * info->scale);
+ break;
+ case 'f': {
+ union {
+ uint32_t u;
+ float f;
+ } converter;
+
+ converter.u = input;
+ printf("%05f ", (converter.f + info->offset) * info->scale);
+ break;
+ }
}
}
@@ -158,7 +189,8 @@ static void print8byte(uint64_t input, struct iio_channel_info *info)
*/
input >>= info->shift;
input &= info->mask;
- if (info->is_signed) {
+ switch (info->format) {
+ case 's': {
int64_t val = (int64_t)(input << (64 - info->bits_used)) >>
(64 - info->bits_used);
/* special case for timestamp */
@@ -167,8 +199,21 @@ static void print8byte(uint64_t input, struct iio_channel_info *info)
else
printf("%05f ",
((float)val + info->offset) * info->scale);
- } else {
+ break;
+ }
+ case 'u':
printf("%05f ", ((float)input + info->offset) * info->scale);
+ break;
+ case 'f': {
+ union {
+ uint64_t u;
+ double f;
+ } converter;
+
+ converter.u = input;
+ printf("%05f ", (converter.f + info->offset) * info->scale);
+ break;
+ }
}
}
diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
index c5c5082cb24e..f1d58db69942 100644
--- a/tools/iio/iio_utils.c
+++ b/tools/iio/iio_utils.c
@@ -70,7 +70,7 @@ int iioutils_break_up_name(const char *full_name, char **generic_name)
/**
* iioutils_get_type() - find and process _type attribute data
- * @is_signed: output whether channel is signed
+ * @format: output channel format
* @bytes: output how many bytes the channel storage occupies
* @bits_used: output number of valid bits of data
* @shift: output amount of bits to shift right data before applying bit mask
@@ -83,7 +83,7 @@ int iioutils_break_up_name(const char *full_name, char **generic_name)
*
* Returns a value >= 0 on success, otherwise a negative error code.
**/
-static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes,
+static int iioutils_get_type(char *format, unsigned int *bytes,
unsigned int *bits_used, unsigned int *shift,
uint64_t *mask, unsigned int *be,
const char *device_dir, int buffer_idx,
@@ -162,7 +162,7 @@ static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes,
else
*mask = (1ULL << *bits_used) - 1ULL;
- *is_signed = (signchar == 's');
+ *format = signchar;
if (fclose(sysfsfp)) {
ret = -errno;
fprintf(stderr, "Failed to close %s\n",
@@ -487,7 +487,7 @@ int build_channel_array(const char *device_dir, int buffer_idx,
if ((ret < 0) && (ret != -ENOENT))
goto error_cleanup_array;
- ret = iioutils_get_type(¤t->is_signed,
+ ret = iioutils_get_type(¤t->format,
¤t->bytes,
¤t->bits_used,
¤t->shift,
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
index 663c94a6c705..8c72f002d050 100644
--- a/tools/iio/iio_utils.h
+++ b/tools/iio/iio_utils.h
@@ -32,7 +32,7 @@ extern const char *iio_dir;
* @shift: amount of bits to shift right data before applying bit mask
* @mask: a bit mask for the raw output
* @be: flag if data is big endian
- * @is_signed: is the raw value stored signed
+ * @format: format of the raw value
* @location: data offset for this channel inside the buffer (in bytes)
**/
struct iio_channel_info {
@@ -46,7 +46,7 @@ struct iio_channel_info {
unsigned shift;
uint64_t mask;
unsigned be;
- unsigned is_signed;
+ char format;
unsigned location;
};
--
2.39.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 4/6] iio: ABI: Add support for floating-point numbers in buffer scan elements
2026-03-17 15:03 [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
` (2 preceding siblings ...)
2026-03-17 15:04 ` [PATCH v8 3/6] iio: tools: Add support for floating-point types in buffer scan elements Francesco Lavra
@ 2026-03-17 15:04 ` Francesco Lavra
2026-03-17 15:04 ` [PATCH v8 5/6] iio: ABI: Add quaternion axis modifier Francesco Lavra
2026-03-17 15:04 ` [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
5 siblings, 0 replies; 19+ messages in thread
From: Francesco Lavra @ 2026-03-17 15:04 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Jonathan Corbet, Shuah Khan, linux-iio, linux-kernel, linux-doc
In the data storage description of a scan element, the first character
after the colon can have the values 's' and 'u' to specify signed and
unsigned integers, respectively.
Add 'f' as an allowed value to specify floating-point numbers formatted
according to the IEEE 754 standard.
Signed-off-by: Francesco Lavra <flavra@baylibre.com>
---
Documentation/ABI/testing/sysfs-bus-iio | 33 +++++++++++++-----------
Documentation/driver-api/iio/buffers.rst | 3 ++-
Documentation/iio/iio_devbuf.rst | 3 ++-
include/linux/iio/iio.h | 2 ++
4 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 5f87dcee78f7..bd6c3305dd2b 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1510,21 +1510,24 @@ Contact: linux-iio@vger.kernel.org
Description:
Description of the scan element data storage within the buffer
and hence the form in which it is read from user-space.
- Form is [be|le]:[s|u]bits/storagebits[>>shift].
- be or le specifies big or little endian. s or u specifies if
- signed (2's complement) or unsigned. bits is the number of bits
- of data and storagebits is the space (after padding) that it
- occupies in the buffer. shift if specified, is the shift that
- needs to be applied prior to masking out unused bits. Some
- devices put their data in the middle of the transferred elements
- with additional information on both sides. Note that some
- devices will have additional information in the unused bits
- so to get a clean value, the bits value must be used to mask
- the buffer output value appropriately. The storagebits value
- also specifies the data alignment. So s48/64>>2 will be a
- signed 48 bit integer stored in a 64 bit location aligned to
- a 64 bit boundary. To obtain the clean value, shift right 2
- and apply a mask to zero the top 16 bits of the result.
+ Form is [be|le]:[f|s|u]bits/storagebits[>>shift].
+ be or le specifies big or little endian. f means floating-point
+ (IEEE 754 binary format), s means signed (2's complement), u means
+ unsigned. bits is the number of bits of data and storagebits is the
+ space (after padding) that it occupies in the buffer; when using a
+ floating-point format, bits must be one of the width values defined
+ in the IEEE 754 standard for binary interchange formats (e.g. 16
+ indicates the binary16 format for half-precision numbers). shift,
+ if specified, is the shift that needs to be applied prior to
+ masking out unused bits. Some devices put their data in the middle
+ of the transferred elements with additional information on both
+ sides. Note that some devices will have additional information in
+ the unused bits, so to get a clean value the bits value must be
+ used to mask the buffer output value appropriately. The storagebits
+ value also specifies the data alignment. So s48/64>>2 will be a
+ signed 48 bit integer stored in a 64 bit location aligned to a 64
+ bit boundary. To obtain the clean value, shift right 2 and apply a
+ mask to zero the top 16 bits of the result.
For other storage combinations this attribute will be extended
appropriately.
diff --git a/Documentation/driver-api/iio/buffers.rst b/Documentation/driver-api/iio/buffers.rst
index e16abaf826fe..8779022e3da5 100644
--- a/Documentation/driver-api/iio/buffers.rst
+++ b/Documentation/driver-api/iio/buffers.rst
@@ -37,9 +37,10 @@ directory contains attributes of the following form:
* :file:`index`, the scan_index of the channel.
* :file:`type`, description of the scan element data storage within the buffer
and hence the form in which it is read from user space.
- Format is [be|le]:[s|u]bits/storagebits[Xrepeat][>>shift] .
+ Format is [be|le]:[f|s|u]bits/storagebits[Xrepeat][>>shift] .
* *be* or *le*, specifies big or little endian.
+ * *f*, specifies if floating-point.
* *s* or *u*, specifies if signed (2's complement) or unsigned.
* *bits*, is the number of valid data bits.
* *storagebits*, is the number of bits (after padding) that it occupies in the
diff --git a/Documentation/iio/iio_devbuf.rst b/Documentation/iio/iio_devbuf.rst
index dca1f0200b0d..e91730fa3cea 100644
--- a/Documentation/iio/iio_devbuf.rst
+++ b/Documentation/iio/iio_devbuf.rst
@@ -83,9 +83,10 @@ and the relevant _type attributes to establish the data storage format.
Read-only attribute containing the description of the scan element data storage
within the buffer and hence the form in which it is read from userspace. Format
-is [be|le]:[s|u]bits/storagebits[Xrepeat][>>shift], where:
+is [be|le]:[f|s|u]bits/storagebits[Xrepeat][>>shift], where:
- **be** or **le** specifies big or little-endian.
+- **f** specifies if floating-point.
- **s** or **u** specifies if signed (2's complement) or unsigned.
- **bits** is the number of valid data bits.
- **storagebits** is the number of bits (after padding) that it occupies in the
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index d48a0ab01b8d..1f2c1cb03394 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -180,9 +180,11 @@ struct iio_event_spec {
* Format values in scan type
* @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
* @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
+ * @IIO_SCAN_FORMAT_FLOAT: Floating point.
*/
#define IIO_SCAN_FORMAT_SIGNED_INT 's'
#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
+#define IIO_SCAN_FORMAT_FLOAT 'f'
/**
* struct iio_scan_type - specification for channel data format in buffer
--
2.39.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 5/6] iio: ABI: Add quaternion axis modifier
2026-03-17 15:03 [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
` (3 preceding siblings ...)
2026-03-17 15:04 ` [PATCH v8 4/6] iio: ABI: Add support for floating-point numbers " Francesco Lavra
@ 2026-03-17 15:04 ` Francesco Lavra
2026-03-21 17:29 ` David Lechner
2026-03-17 15:04 ` [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
5 siblings, 1 reply; 19+ messages in thread
From: Francesco Lavra @ 2026-03-17 15:04 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
linux-iio, linux-kernel
This modifier applies to the IIO_ROT channel type, and indicates a data
representation that specifies the {x, y, z} components of the normalized
quaternion vector.
Signed-off-by: Francesco Lavra <flavra@baylibre.com>
---
Documentation/ABI/testing/sysfs-bus-iio | 15 +++++++++++++++
drivers/iio/industrialio-core.c | 1 +
include/uapi/linux/iio/types.h | 1 +
tools/iio/iio_event_monitor.c | 1 +
4 files changed, 18 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index bd6c3305dd2b..46fef26e5376 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1755,6 +1755,21 @@ Description:
measurement from channel Y. Units after application of scale and
offset are milliamps.
+What: /sys/bus/iio/devices/iio:deviceX/in_rot_quaternionaxis_raw
+KernelVersion: 7.1
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw value of {x, y, z} components of the quaternion vector. These
+ components represent the axis about which a rotation occurs, and are
+ subject to the following constraints:
+
+ - the quaternion vector is normalized, i.e. w^2 + x^2 + y^2 + z^2 = 1
+ - the rotation angle is within the [-pi, pi] range, i.e. the w
+ component (which represents the amount of rotation) is non-negative
+
+ These constraints allow the w value to be calculated from the other
+ components: w = sqrt(1 - (x^2 + y^2 + z^2)).
+
What: /sys/.../iio:deviceX/in_energy_en
What: /sys/.../iio:deviceX/in_distance_en
What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 22eefd048ba9..bd6f4f9f4533 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -157,6 +157,7 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_ACTIVE] = "active",
[IIO_MOD_REACTIVE] = "reactive",
[IIO_MOD_APPARENT] = "apparent",
+ [IIO_MOD_QUATERNION_AXIS] = "quaternionaxis",
};
/* relies on pairs of these shared then separate */
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index 6d269b844271..d7c2bb223651 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -113,6 +113,7 @@ enum iio_modifier {
IIO_MOD_ACTIVE,
IIO_MOD_REACTIVE,
IIO_MOD_APPARENT,
+ IIO_MOD_QUATERNION_AXIS,
};
enum iio_event_type {
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index 03ca33869ce8..df6c43d7738d 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -145,6 +145,7 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_ACTIVE] = "active",
[IIO_MOD_REACTIVE] = "reactive",
[IIO_MOD_APPARENT] = "apparent",
+ [IIO_MOD_QUATERNION_AXIS] = "quaternionaxis",
};
static bool event_is_known(struct iio_event_data *event)
--
2.39.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor
2026-03-17 15:03 [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
` (4 preceding siblings ...)
2026-03-17 15:04 ` [PATCH v8 5/6] iio: ABI: Add quaternion axis modifier Francesco Lavra
@ 2026-03-17 15:04 ` Francesco Lavra
2026-03-21 17:46 ` David Lechner
2026-03-21 18:51 ` Jonathan Cameron
5 siblings, 2 replies; 19+ messages in thread
From: Francesco Lavra @ 2026-03-17 15:04 UTC (permalink / raw)
To: Lorenzo Bianconi, Jonathan Cameron, David Lechner, Nuno Sá,
Andy Shevchenko, linux-kernel, linux-iio
Some IMU chips in the LSM6DSX family have sensor fusion features that
combine data from the accelerometer and gyroscope. One of these features
generates rotation vector data and makes it available in the hardware
FIFO as a quaternion (more specifically, the X, Y and Z components of the
quaternion vector, expressed as 16-bit half-precision floating-point
numbers).
Add support for a new sensor instance that allows receiving sensor fusion
data, by defining a new struct st_lsm6dsx_fusion_settings (which contains
chip-specific details for the sensor fusion functionality), and adding this
struct as a new field in struct st_lsm6dsx_settings. In st_lsm6dsx_core.c,
populate this new struct for the LSM6DSV and LSM6DSV16X chips, and add the
logic to initialize an additional IIO device if this struct is populated
for the hardware type being probed.
Note: a new IIO device is being defined (as opposed to adding channels to
an existing device) because the rate at which sensor fusion data is
generated may not match the data rate from any of the existing devices.
Tested on LSMDSV16X.
Signed-off-by: Francesco Lavra <flavra@baylibre.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/iio/imu/st_lsm6dsx/Makefile | 2 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 28 ++-
.../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 9 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 58 +++++
.../iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c | 235 ++++++++++++++++++
5 files changed, 325 insertions(+), 7 deletions(-)
create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c
diff --git a/drivers/iio/imu/st_lsm6dsx/Makefile b/drivers/iio/imu/st_lsm6dsx/Makefile
index 57cbcd67d64f..19a488254de3 100644
--- a/drivers/iio/imu/st_lsm6dsx/Makefile
+++ b/drivers/iio/imu/st_lsm6dsx/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
st_lsm6dsx-y := st_lsm6dsx_core.o st_lsm6dsx_buffer.o \
- st_lsm6dsx_shub.o
+ st_lsm6dsx_shub.o st_lsm6dsx_fusion.o
obj-$(CONFIG_IIO_ST_LSM6DSX) += st_lsm6dsx.o
obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) += st_lsm6dsx_i2c.o
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index 07b1773c87bd..767aadfe7061 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -294,6 +294,7 @@ enum st_lsm6dsx_sensor_id {
ST_LSM6DSX_ID_EXT0,
ST_LSM6DSX_ID_EXT1,
ST_LSM6DSX_ID_EXT2,
+ ST_LSM6DSX_ID_FUSION,
ST_LSM6DSX_ID_MAX
};
@@ -301,6 +302,17 @@ enum st_lsm6dsx_ext_sensor_id {
ST_LSM6DSX_ID_MAGN,
};
+struct st_lsm6dsx_fusion_settings {
+ const struct iio_chan_spec *chan;
+ int chan_len;
+ struct st_lsm6dsx_reg odr_reg;
+ int odr_hz[ST_LSM6DSX_ODR_LIST_SIZE];
+ int odr_len;
+ struct st_lsm6dsx_reg fifo_enable;
+ struct st_lsm6dsx_reg page_mux;
+ struct st_lsm6dsx_reg enable;
+};
+
/**
* struct st_lsm6dsx_ext_dev_settings - i2c controller slave settings
* @i2c_addr: I2c slave address list.
@@ -388,6 +400,7 @@ struct st_lsm6dsx_settings {
struct st_lsm6dsx_hw_ts_settings ts_settings;
struct st_lsm6dsx_shub_settings shub_settings;
struct st_lsm6dsx_event_settings event_settings;
+ struct st_lsm6dsx_fusion_settings fusion_settings;
};
enum st_lsm6dsx_fifo_mode {
@@ -510,6 +523,9 @@ int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u32 odr, u8 *val);
int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name);
int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable);
int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int len);
+int st_lsm6dsx_fusion_probe(struct st_lsm6dsx_hw *hw, const char *name);
+int st_lsm6dsx_fusion_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable);
+int st_lsm6dsx_fusion_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable);
int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable);
static inline int
@@ -564,12 +580,14 @@ st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev,
static inline int
st_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable)
{
- if (sensor->id == ST_LSM6DSX_ID_EXT0 ||
- sensor->id == ST_LSM6DSX_ID_EXT1 ||
- sensor->id == ST_LSM6DSX_ID_EXT2)
+ switch (sensor->id) {
+ case ST_LSM6DSX_ID_EXT0 ... ST_LSM6DSX_ID_EXT2:
return st_lsm6dsx_shub_set_enable(sensor, enable);
-
- return st_lsm6dsx_sensor_set_enable(sensor, enable);
+ case ST_LSM6DSX_ID_FUSION:
+ return st_lsm6dsx_fusion_set_enable(sensor, enable);
+ default:
+ return st_lsm6dsx_sensor_set_enable(sensor, enable);
+ }
}
static const
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index 19232146bd61..d5935106a373 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -88,6 +88,7 @@ enum st_lsm6dsx_fifo_tag {
ST_LSM6DSX_EXT0_TAG = 0x0f,
ST_LSM6DSX_EXT1_TAG = 0x10,
ST_LSM6DSX_EXT2_TAG = 0x11,
+ ST_LSM6DSX_ROT_TAG = 0x13,
};
static const
@@ -226,8 +227,11 @@ static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor,
u8 data;
/* Only internal sensors have a FIFO ODR configuration register. */
- if (sensor->id >= ARRAY_SIZE(hw->settings->batch))
+ if (sensor->id >= ARRAY_SIZE(hw->settings->batch)) {
+ if (sensor->id == ST_LSM6DSX_ID_FUSION)
+ return st_lsm6dsx_fusion_set_odr(sensor, enable);
return 0;
+ }
batch_reg = &hw->settings->batch[sensor->id];
if (batch_reg->addr) {
@@ -586,6 +590,9 @@ st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, u8 tag,
case ST_LSM6DSX_EXT2_TAG:
iio_dev = hw->iio_devs[ST_LSM6DSX_ID_EXT2];
break;
+ case ST_LSM6DSX_ROT_TAG:
+ iio_dev = hw->iio_devs[ST_LSM6DSX_ID_FUSION];
+ break;
default:
return -EINVAL;
}
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 450cb5b47346..160cc6551853 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -94,6 +94,26 @@
#define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f
+/* Raw values from the IMU are 16-bit half-precision floating-point numbers. */
+#define ST_LSM6DSX_CHANNEL_ROT \
+{ \
+ .type = IIO_ROT, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_QUATERNION_AXIS, \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_all_available = \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = 0, \
+ .scan_type = { \
+ .format = 'f', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ .repeat = 3, \
+ }, \
+ .ext_info = st_lsm6dsx_ext_info, \
+}
+
static const struct iio_event_spec st_lsm6dsx_ev_motion[] = {
{
.type = IIO_EV_TYPE_THRESH,
@@ -153,6 +173,11 @@ static const struct iio_chan_spec st_lsm6ds0_gyro_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(3),
};
+static const struct iio_chan_spec st_lsm6dsx_fusion_channels[] = {
+ ST_LSM6DSX_CHANNEL_ROT,
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
{
.reset = {
@@ -1492,6 +1517,33 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = {
},
},
},
+ .fusion_settings = {
+ .chan = st_lsm6dsx_fusion_channels,
+ .chan_len = ARRAY_SIZE(st_lsm6dsx_fusion_channels),
+ .odr_reg = {
+ .addr = 0x5e,
+ .mask = GENMASK(5, 3),
+ },
+ .odr_hz[0] = 15,
+ .odr_hz[1] = 30,
+ .odr_hz[2] = 60,
+ .odr_hz[3] = 120,
+ .odr_hz[4] = 240,
+ .odr_hz[5] = 480,
+ .odr_len = 6,
+ .fifo_enable = {
+ .addr = 0x44,
+ .mask = BIT(1),
+ },
+ .page_mux = {
+ .addr = 0x01,
+ .mask = BIT(7),
+ },
+ .enable = {
+ .addr = 0x04,
+ .mask = BIT(1),
+ },
+ },
},
{
.reset = {
@@ -2899,6 +2951,12 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
return err;
}
+ if (hw->settings->fusion_settings.chan) {
+ err = st_lsm6dsx_fusion_probe(hw, name);
+ if (err)
+ return err;
+ }
+
if (hw->irq > 0) {
err = st_lsm6dsx_irq_setup(hw);
if (err < 0)
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c
new file mode 100644
index 000000000000..74a2cc5cab12
--- /dev/null
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * STMicroelectronics st_lsm6dsx IMU sensor fusion
+ *
+ * Copyright 2026 BayLibre, SAS
+ */
+
+#include <linux/cleanup.h>
+#include <linux/errno.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/sprintf.h>
+#include <linux/types.h>
+#include <linux/units.h>
+
+#include "st_lsm6dsx.h"
+
+static int
+st_lsm6dsx_fusion_get_odr_val(const struct st_lsm6dsx_fusion_settings *settings,
+ u32 odr_mHz, u8 *val)
+{
+ int odr_hz = odr_mHz / MILLI;
+ int i;
+
+ for (i = 0; i < settings->odr_len; i++) {
+ if (settings->odr_hz[i] == odr_hz)
+ break;
+ }
+ if (i == settings->odr_len)
+ return -EINVAL;
+
+ *val = i;
+ return 0;
+}
+
+/**
+ * st_lsm6dsx_fusion_page_enable - Enable access to sensor fusion configuration
+ * registers.
+ * @hw: Sensor hardware instance.
+ *
+ * Return: 0 on success, negative value on error.
+ */
+static int st_lsm6dsx_fusion_page_enable(struct st_lsm6dsx_hw *hw)
+{
+ const struct st_lsm6dsx_reg *mux;
+
+ mux = &hw->settings->fusion_settings.page_mux;
+
+ return regmap_set_bits(hw->regmap, mux->addr, mux->mask);
+}
+
+/**
+ * st_lsm6dsx_fusion_page_disable - Disable access to sensor fusion
+ * configuration registers.
+ * @hw: Sensor hardware instance.
+ *
+ * Return: 0 on success, negative value on error.
+ */
+static int st_lsm6dsx_fusion_page_disable(struct st_lsm6dsx_hw *hw)
+{
+ const struct st_lsm6dsx_reg *mux;
+
+ mux = &hw->settings->fusion_settings.page_mux;
+
+ return regmap_clear_bits(hw->regmap, mux->addr, mux->mask);
+}
+
+int st_lsm6dsx_fusion_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable)
+{
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ const struct st_lsm6dsx_reg *en_reg;
+ int err;
+
+ guard(mutex)(&hw->page_lock);
+
+ en_reg = &hw->settings->fusion_settings.enable;
+ err = st_lsm6dsx_fusion_page_enable(hw);
+ if (err)
+ return err;
+
+ err = regmap_assign_bits(hw->regmap, en_reg->addr, en_reg->mask, enable);
+ if (err) {
+ st_lsm6dsx_fusion_page_disable(hw);
+ return err;
+ }
+
+ return st_lsm6dsx_fusion_page_disable(hw);
+}
+
+int st_lsm6dsx_fusion_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable)
+{
+ const struct st_lsm6dsx_fusion_settings *settings;
+ struct st_lsm6dsx_hw *hw = sensor->hw;
+ u8 data;
+ int err;
+
+ guard(mutex)(&hw->page_lock);
+
+ err = st_lsm6dsx_fusion_page_enable(hw);
+ if (err)
+ return err;
+
+ settings = &hw->settings->fusion_settings;
+ if (enable) {
+ const struct st_lsm6dsx_reg *reg = &settings->odr_reg;
+ u8 odr_val;
+
+ st_lsm6dsx_fusion_get_odr_val(settings, sensor->hwfifo_odr_mHz,
+ &odr_val);
+ data = ST_LSM6DSX_SHIFT_VAL(odr_val, reg->mask);
+ err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
+ data);
+ if (err)
+ goto out;
+ }
+
+ err = regmap_assign_bits(hw->regmap, settings->fifo_enable.addr,
+ settings->fifo_enable.mask, enable);
+ if (err)
+ goto out;
+
+ return st_lsm6dsx_fusion_page_disable(hw);
+
+out:
+ st_lsm6dsx_fusion_page_disable(hw);
+
+ return err;
+}
+
+static int st_lsm6dsx_fusion_read_raw(struct iio_dev *iio_dev,
+ struct iio_chan_spec const *ch,
+ int *val, int *val2, long mask)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = sensor->hwfifo_odr_mHz / MILLI;
+ *val2 = (sensor->hwfifo_odr_mHz % MILLI) * (MICRO / MILLI);
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int st_lsm6dsx_fusion_write_raw(struct iio_dev *iio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
+ const struct st_lsm6dsx_fusion_settings *settings;
+ int err;
+
+ settings = &sensor->hw->settings->fusion_settings;
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ: {
+ u32 odr_mHz = val * MILLI + val2 * (MILLI / MICRO);
+ u8 odr_val;
+
+ /* check that the requested frequency is supported */
+ err = st_lsm6dsx_fusion_get_odr_val(settings, odr_mHz, &odr_val);
+ if (err)
+ return err;
+
+ sensor->hwfifo_odr_mHz = odr_mHz;
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int st_lsm6dsx_fusion_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type,
+ int *length, long mask)
+{
+ struct st_lsm6dsx_sensor *sensor = iio_priv(indio_dev);
+ const struct st_lsm6dsx_fusion_settings *settings;
+
+ settings = &sensor->hw->settings->fusion_settings;
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *vals = settings->odr_hz;
+ *type = IIO_VAL_INT;
+ *length = settings->odr_len;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info st_lsm6dsx_fusion_info = {
+ .read_raw = st_lsm6dsx_fusion_read_raw,
+ .read_avail = st_lsm6dsx_fusion_read_avail,
+ .write_raw = st_lsm6dsx_fusion_write_raw,
+ .hwfifo_set_watermark = st_lsm6dsx_set_watermark,
+};
+
+int st_lsm6dsx_fusion_probe(struct st_lsm6dsx_hw *hw, const char *name)
+{
+ const struct st_lsm6dsx_fusion_settings *settings;
+ struct st_lsm6dsx_sensor *sensor;
+ struct iio_dev *iio_dev;
+ int ret;
+
+ iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor));
+ if (!iio_dev)
+ return -ENOMEM;
+
+ settings = &hw->settings->fusion_settings;
+ sensor = iio_priv(iio_dev);
+ sensor->id = ST_LSM6DSX_ID_FUSION;
+ sensor->hw = hw;
+ sensor->hwfifo_odr_mHz = settings->odr_hz[0] * MILLI;
+ sensor->watermark = 1;
+ iio_dev->modes = INDIO_DIRECT_MODE;
+ iio_dev->info = &st_lsm6dsx_fusion_info;
+ iio_dev->channels = settings->chan;
+ iio_dev->num_channels = settings->chan_len;
+ ret = snprintf(sensor->name, sizeof(sensor->name), "%s_fusion", name);
+ if (ret >= sizeof(sensor->name))
+ return -E2BIG;
+ iio_dev->name = sensor->name;
+
+ /*
+ * Put the IIO device pointer in the iio_devs array so that the caller
+ * can set up a buffer and register this IIO device.
+ */
+ hw->iio_devs[ST_LSM6DSX_ID_FUSION] = iio_dev;
+
+ return 0;
+}
--
2.39.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-17 15:04 ` [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type Francesco Lavra
@ 2026-03-21 17:22 ` David Lechner
2026-03-23 16:04 ` Francesco Lavra
0 siblings, 1 reply; 19+ messages in thread
From: David Lechner @ 2026-03-21 17:22 UTC (permalink / raw)
To: Francesco Lavra, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On 3/17/26 10:04 AM, Francesco Lavra wrote:
> This field is used to differentiate between signed and unsigned integers.
> A following commit will extend its use in order to add support for non-
> integer scan elements; therefore, replace it with a union that contains a
> more generic 'format' field. This union will be dropped when all drivers
> are changed to use the format field.
> Opportunistically replace character literals with symbolic constants that
> represent the set of allowed values for the format field.
>
> Signed-off-by: Francesco Lavra <flavra@baylibre.com>
> ---
> Documentation/driver-api/iio/buffers.rst | 4 ++--
> include/linux/iio/iio.h | 17 +++++++++++++++--
> 2 files changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/driver-api/iio/buffers.rst b/Documentation/driver-api/iio/buffers.rst
> index 63f364e862d1..e16abaf826fe 100644
> --- a/Documentation/driver-api/iio/buffers.rst
> +++ b/Documentation/driver-api/iio/buffers.rst
> @@ -78,7 +78,7 @@ fields in iio_chan_spec definition::
> /* other members */
> int scan_index
> struct {
> - char sign;
> + char format;
> u8 realbits;
> u8 storagebits;
> u8 shift;
> @@ -98,7 +98,7 @@ following channel definition::
> /* other stuff here */
> .scan_index = 0,
> .scan_type = {
> - .sign = 's',
> + .format = IIO_SCAN_FORMAT_SIGNED_INT,
> .realbits = 12,
> .storagebits = 16,
> .shift = 4,
> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> index a9ecff191bd9..d48a0ab01b8d 100644
> --- a/include/linux/iio/iio.h
> +++ b/include/linux/iio/iio.h
> @@ -176,9 +176,19 @@ struct iio_event_spec {
> unsigned long mask_shared_by_all;
> };
>
> +/*
> + * Format values in scan type
> + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> + */
We could make this proper kernel doc format with one comment per macro.
> +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
> +
> /**
> * struct iio_scan_type - specification for channel data format in buffer
> - * @sign: 's' or 'u' to specify signed or unsigned
> + * @sign: Deprecated, use @format instead.
> + * @format: Data format, can have any of the IIO_SCAN_FORMAT_*
> + * values.
> * @realbits: Number of valid bits of data
> * @storagebits: Realbits + padding
> * @shift: Shift right by this before masking out realbits.
> @@ -189,7 +199,10 @@ struct iio_event_spec {
> * @endianness: little or big endian
> */
> struct iio_scan_type {
> - char sign;
> + union {
> + char sign;
> + char format;
> + };
> u8 realbits;
> u8 storagebits;
> u8 shift;
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 3/6] iio: tools: Add support for floating-point types in buffer scan elements
2026-03-17 15:04 ` [PATCH v8 3/6] iio: tools: Add support for floating-point types in buffer scan elements Francesco Lavra
@ 2026-03-21 17:26 ` David Lechner
0 siblings, 0 replies; 19+ messages in thread
From: David Lechner @ 2026-03-21 17:26 UTC (permalink / raw)
To: Francesco Lavra, Jonathan Cameron, Nuno Sá, Andy Shevchenko,
linux-iio, linux-kernel
On 3/17/26 10:04 AM, Francesco Lavra wrote:
> A subsequent commit will add floating-point support to the ABI; enhance
> the iio_generic_buffer tool to be able to parse this new data format.
>
> Signed-off-by: Francesco Lavra <flavra@baylibre.com>
> ---
> tools/iio/iio_generic_buffer.c | 59 ++++++++++++++++++++++++++++++----
> tools/iio/iio_utils.c | 8 ++---
> tools/iio/iio_utils.h | 4 +--
> 3 files changed, 58 insertions(+), 13 deletions(-)
>
> diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
> index bc82bb6a7a2a..a21552c2b190 100644
> --- a/tools/iio/iio_generic_buffer.c
> +++ b/tools/iio/iio_generic_buffer.c
> @@ -26,6 +26,7 @@
> #include <string.h>
> #include <poll.h>
> #include <endian.h>
> +#include <float.h>
> #include <getopt.h>
> #include <inttypes.h>
> #include <stdbool.h>
> @@ -89,7 +90,7 @@ static void print1byte(uint8_t input, struct iio_channel_info *info)
> */
> input >>= info->shift;
> input &= info->mask;
> - if (info->is_signed) {
> + if (info->format == 's') {
To be consistent, maybe change this one to a switch case too and print
an error if we accidentally have a 1-byte float format.
> int8_t val = (int8_t)(input << (8 - info->bits_used)) >>
> (8 - info->bits_used);
> printf("%05f ", ((float)val + info->offset) * info->scale);
> @@ -112,12 +113,28 @@ static void print2byte(uint16_t input, struct iio_channel_info *info)
> */
> input >>= info->shift;
> input &= info->mask;
> - if (info->is_signed) {
> + switch (info->format) {
> + case 's': {
> int16_t val = (int16_t)(input << (16 - info->bits_used)) >>
> (16 - info->bits_used);
> printf("%05f ", ((float)val + info->offset) * info->scale);
> - } else {
> + break;
> + }
> + case 'u':
> printf("%05f ", ((float)input + info->offset) * info->scale);
> + break;
> +#if defined(__FLT16_MAX__)
> + case 'f': {
> + union {
> + uint16_t u;
> + _Float16 f;
> + } converter;
> +
> + converter.u = input;
> + printf("%05f ", ((float)converter.f + info->offset) * info->scale);
> + break;
> + }
Should we have #else here and print an error if it isn't supported?
> +#endif
> }
> }
>
> @@ -135,12 +152,26 @@ static void print4byte(uint32_t input, struct iio_channel_info *info)
> */
> input >>= info->shift;
> input &= info->mask;
> - if (info->is_signed) {
> + switch (info->format) {
> + case 's': {
> int32_t val = (int32_t)(input << (32 - info->bits_used)) >>
> (32 - info->bits_used);
> printf("%05f ", ((float)val + info->offset) * info->scale);
> - } else {
> + break;
> + }
> + case 'u':
> printf("%05f ", ((float)input + info->offset) * info->scale);
> + break;
> + case 'f': {
> + union {
> + uint32_t u;
> + float f;
> + } converter;
> +
> + converter.u = input;
> + printf("%05f ", (converter.f + info->offset) * info->scale);
> + break;
> + }
> }
> }
>
> @@ -158,7 +189,8 @@ static void print8byte(uint64_t input, struct iio_channel_info *info)
> */
> input >>= info->shift;
> input &= info->mask;
> - if (info->is_signed) {
> + switch (info->format) {
> + case 's': {
> int64_t val = (int64_t)(input << (64 - info->bits_used)) >>
> (64 - info->bits_used);
> /* special case for timestamp */
> @@ -167,8 +199,21 @@ static void print8byte(uint64_t input, struct iio_channel_info *info)
> else
> printf("%05f ",
> ((float)val + info->offset) * info->scale);
> - } else {
> + break;
> + }
> + case 'u':
> printf("%05f ", ((float)input + info->offset) * info->scale);
> + break;
> + case 'f': {
> + union {
> + uint64_t u;
> + double f;
> + } converter;
> +
> + converter.u = input;
> + printf("%05f ", (converter.f + info->offset) * info->scale);
> + break;
> + }
> }
> }
>
> diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
> index c5c5082cb24e..f1d58db69942 100644
> --- a/tools/iio/iio_utils.c
> +++ b/tools/iio/iio_utils.c
> @@ -70,7 +70,7 @@ int iioutils_break_up_name(const char *full_name, char **generic_name)
>
> /**
> * iioutils_get_type() - find and process _type attribute data
> - * @is_signed: output whether channel is signed
> + * @format: output channel format
> * @bytes: output how many bytes the channel storage occupies
> * @bits_used: output number of valid bits of data
> * @shift: output amount of bits to shift right data before applying bit mask
> @@ -83,7 +83,7 @@ int iioutils_break_up_name(const char *full_name, char **generic_name)
> *
> * Returns a value >= 0 on success, otherwise a negative error code.
> **/
> -static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes,
> +static int iioutils_get_type(char *format, unsigned int *bytes,
> unsigned int *bits_used, unsigned int *shift,
> uint64_t *mask, unsigned int *be,
> const char *device_dir, int buffer_idx,
> @@ -162,7 +162,7 @@ static int iioutils_get_type(unsigned int *is_signed, unsigned int *bytes,
> else
> *mask = (1ULL << *bits_used) - 1ULL;
>
> - *is_signed = (signchar == 's');
> + *format = signchar;
Should we also rename signchar to formatchar?
> if (fclose(sysfsfp)) {
> ret = -errno;
> fprintf(stderr, "Failed to close %s\n",
> @@ -487,7 +487,7 @@ int build_channel_array(const char *device_dir, int buffer_idx,
> if ((ret < 0) && (ret != -ENOENT))
> goto error_cleanup_array;
>
> - ret = iioutils_get_type(¤t->is_signed,
> + ret = iioutils_get_type(¤t->format,
> ¤t->bytes,
> ¤t->bits_used,
> ¤t->shift,
> diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
> index 663c94a6c705..8c72f002d050 100644
> --- a/tools/iio/iio_utils.h
> +++ b/tools/iio/iio_utils.h
> @@ -32,7 +32,7 @@ extern const char *iio_dir;
> * @shift: amount of bits to shift right data before applying bit mask
> * @mask: a bit mask for the raw output
> * @be: flag if data is big endian
> - * @is_signed: is the raw value stored signed
> + * @format: format of the raw value
> * @location: data offset for this channel inside the buffer (in bytes)
> **/
> struct iio_channel_info {
> @@ -46,7 +46,7 @@ struct iio_channel_info {
> unsigned shift;
> uint64_t mask;
> unsigned be;
> - unsigned is_signed;
> + char format;
> unsigned location;
> };
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 5/6] iio: ABI: Add quaternion axis modifier
2026-03-17 15:04 ` [PATCH v8 5/6] iio: ABI: Add quaternion axis modifier Francesco Lavra
@ 2026-03-21 17:29 ` David Lechner
0 siblings, 0 replies; 19+ messages in thread
From: David Lechner @ 2026-03-21 17:29 UTC (permalink / raw)
To: Francesco Lavra, Jonathan Cameron, Nuno Sá, Andy Shevchenko,
linux-iio, linux-kernel
On 3/17/26 10:04 AM, Francesco Lavra wrote:
> This modifier applies to the IIO_ROT channel type, and indicates a data
> representation that specifies the {x, y, z} components of the normalized
> quaternion vector.
>
> Signed-off-by: Francesco Lavra <flavra@baylibre.com>
> ---
Reviewed-by: David Lechner <dlechner@baylibre.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor
2026-03-17 15:04 ` [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
@ 2026-03-21 17:46 ` David Lechner
2026-03-21 18:51 ` Jonathan Cameron
1 sibling, 0 replies; 19+ messages in thread
From: David Lechner @ 2026-03-21 17:46 UTC (permalink / raw)
To: Francesco Lavra, Lorenzo Bianconi, Jonathan Cameron, Nuno Sá,
Andy Shevchenko, linux-kernel, linux-iio
On 3/17/26 10:04 AM, Francesco Lavra wrote:
> Some IMU chips in the LSM6DSX family have sensor fusion features that
> combine data from the accelerometer and gyroscope. One of these features
> generates rotation vector data and makes it available in the hardware
> FIFO as a quaternion (more specifically, the X, Y and Z components of the
> quaternion vector, expressed as 16-bit half-precision floating-point
> numbers).
>
> Add support for a new sensor instance that allows receiving sensor fusion
> data, by defining a new struct st_lsm6dsx_fusion_settings (which contains
> chip-specific details for the sensor fusion functionality), and adding this
> struct as a new field in struct st_lsm6dsx_settings. In st_lsm6dsx_core.c,
> populate this new struct for the LSM6DSV and LSM6DSV16X chips, and add the
> logic to initialize an additional IIO device if this struct is populated
> for the hardware type being probed.
> Note: a new IIO device is being defined (as opposed to adding channels to
> an existing device) because the rate at which sensor fusion data is
> generated may not match the data rate from any of the existing devices.
>
> Tested on LSMDSV16X.
>
We should mention that this depends on [1] to get the correct sizing
of the buffer in userspace.
[1]: https://lore.kernel.org/linux-iio/20260307-iio-fix-timestamp-alignment-v2-4-d1d48fbadbbf@baylibre.com/
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor
2026-03-17 15:04 ` [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
2026-03-21 17:46 ` David Lechner
@ 2026-03-21 18:51 ` Jonathan Cameron
1 sibling, 0 replies; 19+ messages in thread
From: Jonathan Cameron @ 2026-03-21 18:51 UTC (permalink / raw)
To: Francesco Lavra
Cc: Lorenzo Bianconi, David Lechner, Nuno Sá, Andy Shevchenko,
linux-kernel, linux-iio
On Tue, 17 Mar 2026 16:04:26 +0100
Francesco Lavra <flavra@baylibre.com> wrote:
> Some IMU chips in the LSM6DSX family have sensor fusion features that
> combine data from the accelerometer and gyroscope. One of these features
> generates rotation vector data and makes it available in the hardware
> FIFO as a quaternion (more specifically, the X, Y and Z components of the
> quaternion vector, expressed as 16-bit half-precision floating-point
> numbers).
>
> Add support for a new sensor instance that allows receiving sensor fusion
> data, by defining a new struct st_lsm6dsx_fusion_settings (which contains
> chip-specific details for the sensor fusion functionality), and adding this
> struct as a new field in struct st_lsm6dsx_settings. In st_lsm6dsx_core.c,
> populate this new struct for the LSM6DSV and LSM6DSV16X chips, and add the
> logic to initialize an additional IIO device if this struct is populated
> for the hardware type being probed.
> Note: a new IIO device is being defined (as opposed to adding channels to
> an existing device) because the rate at which sensor fusion data is
> generated may not match the data rate from any of the existing devices.
>
> Tested on LSMDSV16X.
>
> Signed-off-by: Francesco Lavra <flavra@baylibre.com>
> Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Hi Francesco
Just a few really minor last (hopefully!) things from me. On the whole
this set is looking very nice.
Jonathan
> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
> index 450cb5b47346..160cc6551853 100644
> --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
> diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c
> new file mode 100644
> index 000000000000..74a2cc5cab12
> --- /dev/null
> +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c
> @@ -0,0 +1,235 @@
> +
> +int st_lsm6dsx_fusion_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable)
> +{
> + const struct st_lsm6dsx_fusion_settings *settings;
> + struct st_lsm6dsx_hw *hw = sensor->hw;
> + u8 data;
> + int err;
> +
> + guard(mutex)(&hw->page_lock);
I missed this before, but mixing cleanup and gotos is generally not
seen in a good light even when it doesn't introduce bugs. See the comments in
cleanup.h Easiest solution here is probably a helper function doing
the stuff after the fusion page is enabled. That can return directly
and we can then handle any error out here.
> +
> + err = st_lsm6dsx_fusion_page_enable(hw);
> + if (err)
> + return err;
> +
> + settings = &hw->settings->fusion_settings;
> + if (enable) {
> + const struct st_lsm6dsx_reg *reg = &settings->odr_reg;
> + u8 odr_val;
> +
> + st_lsm6dsx_fusion_get_odr_val(settings, sensor->hwfifo_odr_mHz,
> + &odr_val);
> + data = ST_LSM6DSX_SHIFT_VAL(odr_val, reg->mask);
> + err = regmap_update_bits(hw->regmap, reg->addr, reg->mask,
> + data);
> + if (err)
> + goto out;
> + }
> +
> + err = regmap_assign_bits(hw->regmap, settings->fifo_enable.addr,
> + settings->fifo_enable.mask, enable);
> + if (err)
> + goto out;
> +
> + return st_lsm6dsx_fusion_page_disable(hw);
> +
> +out:
> + st_lsm6dsx_fusion_page_disable(hw);
> +
> + return err;
> +}
> +int st_lsm6dsx_fusion_probe(struct st_lsm6dsx_hw *hw, const char *name)
> +{
> +
> + /*
> + * Put the IIO device pointer in the iio_devs array so that the caller
Really minor but why the leading double spaces? 1 should be enough I think.
> + * can set up a buffer and register this IIO device.
> + */
> + hw->iio_devs[ST_LSM6DSX_ID_FUSION] = iio_dev;
> +
> + return 0;
> +}
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-21 17:22 ` David Lechner
@ 2026-03-23 16:04 ` Francesco Lavra
2026-03-23 16:08 ` David Lechner
2026-03-23 16:49 ` Andy Shevchenko
0 siblings, 2 replies; 19+ messages in thread
From: Francesco Lavra @ 2026-03-23 16:04 UTC (permalink / raw)
To: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> On 3/17/26 10:04 AM, Francesco Lavra wrote:
> > This field is used to differentiate between signed and unsigned
> > integers.
> > A following commit will extend its use in order to add support for non-
> > integer scan elements; therefore, replace it with a union that contains
> > a
> > more generic 'format' field. This union will be dropped when all
> > drivers
> > are changed to use the format field.
> > Opportunistically replace character literals with symbolic constants
> > that
> > represent the set of allowed values for the format field.
> >
> > Signed-off-by: Francesco Lavra <flavra@baylibre.com>
> > ---
> > Documentation/driver-api/iio/buffers.rst | 4 ++--
> > include/linux/iio/iio.h | 17 +++++++++++++++--
> > 2 files changed, 17 insertions(+), 4 deletions(-)
> >
> > diff --git a/Documentation/driver-api/iio/buffers.rst
> > b/Documentation/driver-api/iio/buffers.rst
> > index 63f364e862d1..e16abaf826fe 100644
> > --- a/Documentation/driver-api/iio/buffers.rst
> > +++ b/Documentation/driver-api/iio/buffers.rst
> > @@ -78,7 +78,7 @@ fields in iio_chan_spec definition::
> > /* other members */
> > int scan_index
> > struct {
> > - char sign;
> > + char format;
> > u8 realbits;
> > u8 storagebits;
> > u8 shift;
> > @@ -98,7 +98,7 @@ following channel definition::
> > /* other stuff here */
> > .scan_index = 0,
> > .scan_type = {
> > - .sign = 's',
> > + .format = IIO_SCAN_FORMAT_SIGNED_INT,
> > .realbits = 12,
> > .storagebits = 16,
> > .shift = 4,
> > diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> > index a9ecff191bd9..d48a0ab01b8d 100644
> > --- a/include/linux/iio/iio.h
> > +++ b/include/linux/iio/iio.h
> > @@ -176,9 +176,19 @@ struct iio_event_spec {
> > unsigned long mask_shared_by_all;
> > };
> >
> > +/*
> > + * Format values in scan type
> > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> > + */
>
> We could make this proper kernel doc format with one comment per macro.
Actually, a set of related #defines can be documented with a single
comment. I see a few examples doing that in include/linux/gfp_types.h and
include/linux/fpga/fpga-mgr.h
> > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
> > +
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-23 16:04 ` Francesco Lavra
@ 2026-03-23 16:08 ` David Lechner
2026-03-23 16:49 ` Andy Shevchenko
1 sibling, 0 replies; 19+ messages in thread
From: David Lechner @ 2026-03-23 16:08 UTC (permalink / raw)
To: Francesco Lavra, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On 3/23/26 11:04 AM, Francesco Lavra wrote:
> On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
>> On 3/17/26 10:04 AM, Francesco Lavra wrote:
>>> This field is used to differentiate between signed and unsigned
>>> integers.
>>> A following commit will extend its use in order to add support for non-
>>> integer scan elements; therefore, replace it with a union that contains
>>> a
>>> more generic 'format' field. This union will be dropped when all
>>> drivers
>>> are changed to use the format field.
>>> Opportunistically replace character literals with symbolic constants
>>> that
>>> represent the set of allowed values for the format field.
>>>
>>> Signed-off-by: Francesco Lavra <flavra@baylibre.com>
>>> ---
>>> Documentation/driver-api/iio/buffers.rst | 4 ++--
>>> include/linux/iio/iio.h | 17 +++++++++++++++--
>>> 2 files changed, 17 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/Documentation/driver-api/iio/buffers.rst
>>> b/Documentation/driver-api/iio/buffers.rst
>>> index 63f364e862d1..e16abaf826fe 100644
>>> --- a/Documentation/driver-api/iio/buffers.rst
>>> +++ b/Documentation/driver-api/iio/buffers.rst
>>> @@ -78,7 +78,7 @@ fields in iio_chan_spec definition::
>>> /* other members */
>>> int scan_index
>>> struct {
>>> - char sign;
>>> + char format;
>>> u8 realbits;
>>> u8 storagebits;
>>> u8 shift;
>>> @@ -98,7 +98,7 @@ following channel definition::
>>> /* other stuff here */
>>> .scan_index = 0,
>>> .scan_type = {
>>> - .sign = 's',
>>> + .format = IIO_SCAN_FORMAT_SIGNED_INT,
>>> .realbits = 12,
>>> .storagebits = 16,
>>> .shift = 4,
>>> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
>>> index a9ecff191bd9..d48a0ab01b8d 100644
>>> --- a/include/linux/iio/iio.h
>>> +++ b/include/linux/iio/iio.h
>>> @@ -176,9 +176,19 @@ struct iio_event_spec {
>>> unsigned long mask_shared_by_all;
>>> };
>>>
>>> +/*
>>> + * Format values in scan type
>>> + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
>>> + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
>>> + */
>>
>> We could make this proper kernel doc format with one comment per macro.
>
> Actually, a set of related #defines can be documented with a single
> comment. I see a few examples doing that in include/linux/gfp_types.h and
> include/linux/fpga/fpga-mgr.h
Fancy. Although, IDEs tend to be able to handle doc comments better
if they are not combined (i.e. getting the docs when you hold the
mouse over an identifier).
>
>
>>> +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
>>> +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
>>> +
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-23 16:04 ` Francesco Lavra
2026-03-23 16:08 ` David Lechner
@ 2026-03-23 16:49 ` Andy Shevchenko
2026-03-23 17:37 ` Francesco Lavra
1 sibling, 1 reply; 19+ messages in thread
From: Andy Shevchenko @ 2026-03-23 16:49 UTC (permalink / raw)
To: Francesco Lavra
Cc: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On Mon, Mar 23, 2026 at 05:04:10PM +0100, Francesco Lavra wrote:
> On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> > On 3/17/26 10:04 AM, Francesco Lavra wrote:
...
> > > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> > > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> > We could make this proper kernel doc format with one comment per macro.
>
> Actually, a set of related #defines can be documented with a single
> comment. I see a few examples doing that in include/linux/gfp_types.h and
> include/linux/fpga/fpga-mgr.h
>
> > > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
...or use enum
/**
* ...kernel-doc for enum...
*/
enum {
IIO_SCAN_FORMAT_SIGNED_INT = 's',
IIO_SCAN_FORMAT_UNSIGNED_INT = 'u',
};
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-23 16:49 ` Andy Shevchenko
@ 2026-03-23 17:37 ` Francesco Lavra
2026-03-24 11:04 ` Andy Shevchenko
0 siblings, 1 reply; 19+ messages in thread
From: Francesco Lavra @ 2026-03-23 17:37 UTC (permalink / raw)
To: Andy Shevchenko
Cc: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On Mon, 2026-03-23 at 18:49 +0200, Andy Shevchenko wrote:
> On Mon, Mar 23, 2026 at 05:04:10PM +0100, Francesco Lavra wrote:
> > On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> > > On 3/17/26 10:04 AM, Francesco Lavra wrote:
>
> ...
>
> > > > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> > > > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
>
> > > We could make this proper kernel doc format with one comment per
> > > macro.
> >
> > Actually, a set of related #defines can be documented with a single
> > comment. I see a few examples doing that in include/linux/gfp_types.h
> > and
> > include/linux/fpga/fpga-mgr.h
> >
> > > > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > > > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
>
> ...or use enum
>
> /**
> * ...kernel-doc for enum...
> */
> enum {
> IIO_SCAN_FORMAT_SIGNED_INT = 's',
> IIO_SCAN_FORMAT_UNSIGNED_INT = 'u',
> };
There is no standard kernel-doc format for anonymous enums.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-23 17:37 ` Francesco Lavra
@ 2026-03-24 11:04 ` Andy Shevchenko
2026-03-24 11:42 ` Francesco Lavra
0 siblings, 1 reply; 19+ messages in thread
From: Andy Shevchenko @ 2026-03-24 11:04 UTC (permalink / raw)
To: Francesco Lavra
Cc: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On Mon, Mar 23, 2026 at 06:37:38PM +0100, Francesco Lavra wrote:
> On Mon, 2026-03-23 at 18:49 +0200, Andy Shevchenko wrote:
> > On Mon, Mar 23, 2026 at 05:04:10PM +0100, Francesco Lavra wrote:
> > > On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> > > > On 3/17/26 10:04 AM, Francesco Lavra wrote:
...
> > > > > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's complement).
> > > > > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> >
> > > > We could make this proper kernel doc format with one comment per
> > > > macro.
> > >
> > > Actually, a set of related #defines can be documented with a single
> > > comment. I see a few examples doing that in include/linux/gfp_types.h
> > > and
> > > include/linux/fpga/fpga-mgr.h
> > >
> > > > > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > > > > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
> >
> > ...or use enum
> >
> > /**
> > * ...kernel-doc for enum...
> > */
> > enum {
> > IIO_SCAN_FORMAT_SIGNED_INT = 's',
> > IIO_SCAN_FORMAT_UNSIGNED_INT = 'u',
> > };
>
> There is no standard kernel-doc format for anonymous enums.
What do you mean? We have such in kernel, for example,
drivers/pinctrl/intel/pinctrl-intel.c.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-24 11:04 ` Andy Shevchenko
@ 2026-03-24 11:42 ` Francesco Lavra
2026-03-24 11:52 ` Andy Shevchenko
0 siblings, 1 reply; 19+ messages in thread
From: Francesco Lavra @ 2026-03-24 11:42 UTC (permalink / raw)
To: Andy Shevchenko
Cc: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On Tue, 2026-03-24 at 13:04 +0200, Andy Shevchenko wrote:
> On Mon, Mar 23, 2026 at 06:37:38PM +0100, Francesco Lavra wrote:
> > On Mon, 2026-03-23 at 18:49 +0200, Andy Shevchenko wrote:
> > > On Mon, Mar 23, 2026 at 05:04:10PM +0100, Francesco Lavra wrote:
> > > > On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> > > > > On 3/17/26 10:04 AM, Francesco Lavra wrote:
>
> ...
>
> > > > > > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's
> > > > > > complement).
> > > > > > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> > >
> > > > > We could make this proper kernel doc format with one comment per
> > > > > macro.
> > > >
> > > > Actually, a set of related #defines can be documented with a single
> > > > comment. I see a few examples doing that in
> > > > include/linux/gfp_types.h
> > > > and
> > > > include/linux/fpga/fpga-mgr.h
> > > >
> > > > > > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > > > > > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
> > >
> > > ...or use enum
> > >
> > > /**
> > > * ...kernel-doc for enum...
> > > */
> > > enum {
> > > IIO_SCAN_FORMAT_SIGNED_INT = 's',
> > > IIO_SCAN_FORMAT_UNSIGNED_INT = 'u',
> > > };
> >
> > There is no standard kernel-doc format for anonymous enums.
>
> What do you mean? We have such in kernel, for example,
> drivers/pinctrl/intel/pinctrl-intel.c.
The kernel-doc guidelines at Documentation/doc-guide/kernel-doc.rst, in the
section that describe structure, union, and enumeration documentation,
include the name of the struct in the example, so I thought they wouldn't
apply to anonymous types. But now I see that anonymous enum comments are
processed just fine by the kernel-doc tool.
Anyway, in v9 I switched to one comment per macro, as suggested by David.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type
2026-03-24 11:42 ` Francesco Lavra
@ 2026-03-24 11:52 ` Andy Shevchenko
0 siblings, 0 replies; 19+ messages in thread
From: Andy Shevchenko @ 2026-03-24 11:52 UTC (permalink / raw)
To: Francesco Lavra
Cc: David Lechner, Jonathan Corbet, Shuah Khan, Jonathan Cameron,
Nuno Sá, Andy Shevchenko, linux-doc, linux-kernel, linux-iio
On Tue, Mar 24, 2026 at 12:42:19PM +0100, Francesco Lavra wrote:
> On Tue, 2026-03-24 at 13:04 +0200, Andy Shevchenko wrote:
> > On Mon, Mar 23, 2026 at 06:37:38PM +0100, Francesco Lavra wrote:
> > > On Mon, 2026-03-23 at 18:49 +0200, Andy Shevchenko wrote:
> > > > On Mon, Mar 23, 2026 at 05:04:10PM +0100, Francesco Lavra wrote:
> > > > > On Sat, 2026-03-21 at 12:22 -0500, David Lechner wrote:
> > > > > > On 3/17/26 10:04 AM, Francesco Lavra wrote:
...
> > > > > > > + * @IIO_SCAN_FORMAT_SIGNED_INT: Signed integer (two's
> > > > > > > complement).
> > > > > > > + * @IIO_SCAN_FORMAT_UNSIGNED_INT: Unsigned integer.
> > > >
> > > > > > We could make this proper kernel doc format with one comment per
> > > > > > macro.
> > > > >
> > > > > Actually, a set of related #defines can be documented with a single
> > > > > comment. I see a few examples doing that in
> > > > > include/linux/gfp_types.h
> > > > > and
> > > > > include/linux/fpga/fpga-mgr.h
> > > > >
> > > > > > > +#define IIO_SCAN_FORMAT_SIGNED_INT 's'
> > > > > > > +#define IIO_SCAN_FORMAT_UNSIGNED_INT 'u'
> > > >
> > > > ...or use enum
> > > >
> > > > /**
> > > > * ...kernel-doc for enum...
> > > > */
> > > > enum {
> > > > IIO_SCAN_FORMAT_SIGNED_INT = 's',
> > > > IIO_SCAN_FORMAT_UNSIGNED_INT = 'u',
> > > > };
> > >
> > > There is no standard kernel-doc format for anonymous enums.
> >
> > What do you mean? We have such in kernel, for example,
> > drivers/pinctrl/intel/pinctrl-intel.c.
>
> The kernel-doc guidelines at Documentation/doc-guide/kernel-doc.rst, in the
> section that describe structure, union, and enumeration documentation,
> include the name of the struct in the example, so I thought they wouldn't
> apply to anonymous types. But now I see that anonymous enum comments are
> processed just fine by the kernel-doc tool.
> Anyway, in v9 I switched to one comment per macro, as suggested by David.
WFM, thanks.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-03-24 11:52 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-17 15:03 [PATCH v8 0/6] imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
2026-03-17 15:03 ` [PATCH v8 1/6] iio: imu: st_lsm6dsx: Fix check for invalid samples from FIFO Francesco Lavra
2026-03-17 15:04 ` [PATCH v8 2/6] iio: Replace 'sign' field with union in struct iio_scan_type Francesco Lavra
2026-03-21 17:22 ` David Lechner
2026-03-23 16:04 ` Francesco Lavra
2026-03-23 16:08 ` David Lechner
2026-03-23 16:49 ` Andy Shevchenko
2026-03-23 17:37 ` Francesco Lavra
2026-03-24 11:04 ` Andy Shevchenko
2026-03-24 11:42 ` Francesco Lavra
2026-03-24 11:52 ` Andy Shevchenko
2026-03-17 15:04 ` [PATCH v8 3/6] iio: tools: Add support for floating-point types in buffer scan elements Francesco Lavra
2026-03-21 17:26 ` David Lechner
2026-03-17 15:04 ` [PATCH v8 4/6] iio: ABI: Add support for floating-point numbers " Francesco Lavra
2026-03-17 15:04 ` [PATCH v8 5/6] iio: ABI: Add quaternion axis modifier Francesco Lavra
2026-03-21 17:29 ` David Lechner
2026-03-17 15:04 ` [PATCH v8 6/6] iio: imu: st_lsm6dsx: Add support for rotation sensor Francesco Lavra
2026-03-21 17:46 ` David Lechner
2026-03-21 18:51 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox