]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iio: imu: bmi270: Add triggered buffer for Bosch BMI270 IMU
authorJustin Weiss <justin@justinweiss.com>
Sun, 27 Oct 2024 17:20:22 +0000 (10:20 -0700)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Fri, 1 Nov 2024 14:54:47 +0000 (14:54 +0000)
Set up a triggered buffer for the accel and angl_vel values.

Signed-off-by: Justin Weiss <justin@justinweiss.com>
Link: https://patch.msgid.link/20241027172029.160134-2-justin@justinweiss.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/imu/bmi270/Kconfig
drivers/iio/imu/bmi270/bmi270.h
drivers/iio/imu/bmi270/bmi270_core.c

index 0ffd29794fda2f9ccda7d4d725c751d9dd86c829..6362acc706da1f5c42a4f1c8ffc4cb46f99fc641 100644 (file)
@@ -6,6 +6,7 @@
 config BMI270
        tristate
        select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
 
 config BMI270_I2C
        tristate "Bosch BMI270 I2C driver"
index 93e5f387607b75354350a6795a02c90f3591b790..6173be929bac265606757106d7a79122cfdd8ca0 100644 (file)
@@ -11,6 +11,15 @@ struct bmi270_data {
        struct device *dev;
        struct regmap *regmap;
        const struct bmi270_chip_info *chip_info;
+
+       /*
+        * Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to
+        * that to ensure a DMA safe buffer.
+        */
+       struct {
+               __le16 channels[6];
+               aligned_s64 timestamp;
+       } data __aligned(IIO_DMA_MINALIGN);
 };
 
 struct bmi270_chip_info {
index 5f08d786fa218835900f982288b83dc21df15815..bcc8a139d8845917db7762baeee0f1dd086cb2d5 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/regmap.h>
 
 #include <linux/iio/iio.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
 
 #include "bmi270.h"
 
@@ -64,6 +66,17 @@ enum bmi270_scan {
        BMI270_SCAN_GYRO_X,
        BMI270_SCAN_GYRO_Y,
        BMI270_SCAN_GYRO_Z,
+       BMI270_SCAN_TIMESTAMP,
+};
+
+static const unsigned long bmi270_avail_scan_masks[] = {
+       (BIT(BMI270_SCAN_ACCEL_X) |
+        BIT(BMI270_SCAN_ACCEL_Y) |
+        BIT(BMI270_SCAN_ACCEL_Z) |
+        BIT(BMI270_SCAN_GYRO_X) |
+        BIT(BMI270_SCAN_GYRO_Y) |
+        BIT(BMI270_SCAN_GYRO_Z)),
+       0
 };
 
 const struct bmi270_chip_info bmi270_chip_info = {
@@ -73,6 +86,27 @@ const struct bmi270_chip_info bmi270_chip_info = {
 };
 EXPORT_SYMBOL_NS_GPL(bmi270_chip_info, IIO_BMI270);
 
+static irqreturn_t bmi270_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct bmi270_data *bmi270_device = iio_priv(indio_dev);
+       int ret;
+
+       ret = regmap_bulk_read(bmi270_device->regmap, BMI270_ACCEL_X_REG,
+                              &bmi270_device->data.channels,
+                              sizeof(bmi270_device->data.channels));
+
+       if (ret)
+               goto done;
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &bmi270_device->data,
+                                          pf->timestamp);
+done:
+       iio_trigger_notify_done(indio_dev->trig);
+       return IRQ_HANDLED;
+}
+
 static int bmi270_get_data(struct bmi270_data *bmi270_device,
                           int chan_type, int axis, int *val)
 {
@@ -128,6 +162,13 @@ static const struct iio_info bmi270_info = {
        .modified = 1,                                          \
        .channel2 = IIO_MOD_##_axis,                            \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
+       .scan_index = BMI270_SCAN_ACCEL_##_axis,                \
+       .scan_type = {                                          \
+               .sign = 's',                                    \
+               .realbits = 16,                                 \
+               .storagebits = 16,                              \
+               .endianness = IIO_LE,                           \
+       },                                                      \
 }
 
 #define BMI270_ANG_VEL_CHANNEL(_axis) {                                \
@@ -135,6 +176,13 @@ static const struct iio_info bmi270_info = {
        .modified = 1,                                          \
        .channel2 = IIO_MOD_##_axis,                            \
        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
+       .scan_index = BMI270_SCAN_GYRO_##_axis,                 \
+       .scan_type = {                                          \
+               .sign = 's',                                    \
+               .realbits = 16,                                 \
+               .storagebits = 16,                              \
+               .endianness = IIO_LE,                           \
+       },                                                      \
 }
 
 static const struct iio_chan_spec bmi270_channels[] = {
@@ -144,6 +192,7 @@ static const struct iio_chan_spec bmi270_channels[] = {
        BMI270_ANG_VEL_CHANNEL(X),
        BMI270_ANG_VEL_CHANNEL(Y),
        BMI270_ANG_VEL_CHANNEL(Z),
+       IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
 };
 
 static int bmi270_validate_chip_id(struct bmi270_data *bmi270_device)
@@ -301,9 +350,16 @@ int bmi270_core_probe(struct device *dev, struct regmap *regmap,
        indio_dev->channels = bmi270_channels;
        indio_dev->num_channels = ARRAY_SIZE(bmi270_channels);
        indio_dev->name = chip_info->name;
+       indio_dev->available_scan_masks = bmi270_avail_scan_masks;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &bmi270_info;
 
+       ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+                                             iio_pollfunc_store_time,
+                                             bmi270_trigger_handler, NULL);
+       if (ret)
+               return ret;
+
        return devm_iio_device_register(dev, indio_dev);
 }
 EXPORT_SYMBOL_NS_GPL(bmi270_core_probe, IIO_BMI270);