Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: imu: Add driver for BMI323 IMU

The Bosch BMI323 is a 6-axis low-power IMU that provide measurements for
acceleration, angular rate, and temperature. This sensor includes
motion-triggered interrupt features, such as a step counter, tap detection,
and activity/inactivity interrupt capabilities.

The driver supports various functionalities, including data ready, FIFO
data handling, and events such as tap detection, step counting, and
activity interrupts.

Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
Link: https://lore.kernel.org/r/20231013034808.8948-3-jagathjog1996@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Jagath Jog J and committed by
Jonathan Cameron
8a636db3 a0357c08

+2628
+18
Documentation/ABI/testing/sysfs-bus-iio
··· 2254 2254 If a label is defined for this event add that to the event 2255 2255 specific attributes. This is useful for userspace to be able to 2256 2256 better identify an individual event. 2257 + 2258 + What: /sys/.../events/in_accel_gesture_tap_wait_timeout 2259 + KernelVersion: 6.7 2260 + Contact: linux-iio@vger.kernel.org 2261 + Description: 2262 + Enable tap gesture confirmation with timeout. 2263 + 2264 + What: /sys/.../events/in_accel_gesture_tap_wait_dur 2265 + KernelVersion: 6.7 2266 + Contact: linux-iio@vger.kernel.org 2267 + Description: 2268 + Timeout value in seconds for tap gesture confirmation. 2269 + 2270 + What: /sys/.../events/in_accel_gesture_tap_wait_dur_available 2271 + KernelVersion: 6.7 2272 + Contact: linux-iio@vger.kernel.org 2273 + Description: 2274 + List of available timeout value for tap gesture confirmation.
+7
MAINTAINERS
··· 3647 3647 F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml 3648 3648 F: drivers/iio/accel/bma400* 3649 3649 3650 + BOSCH SENSORTEC BMI323 IMU IIO DRIVER 3651 + M: Jagath Jog J <jagathjog1996@gmail.com> 3652 + L: linux-iio@vger.kernel.org 3653 + S: Maintained 3654 + F: Documentation/devicetree/bindings/iio/imu/bosch,bma400.yaml 3655 + F: drivers/iio/imu/bmi323/ 3656 + 3650 3657 BPF JIT for ARM 3651 3658 M: Russell King <linux@armlinux.org.uk> 3652 3659 M: Puranjay Mohan <puranjay12@gmail.com>
+1
drivers/iio/imu/Kconfig
··· 53 53 ADIS16485, ADIS16488 inertial sensors. 54 54 55 55 source "drivers/iio/imu/bmi160/Kconfig" 56 + source "drivers/iio/imu/bmi323/Kconfig" 56 57 source "drivers/iio/imu/bno055/Kconfig" 57 58 58 59 config FXOS8700
+1
drivers/iio/imu/Makefile
··· 15 15 obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o 16 16 17 17 obj-y += bmi160/ 18 + obj-y += bmi323/ 18 19 obj-y += bno055/ 19 20 20 21 obj-$(CONFIG_FXOS8700) += fxos8700_core.o
+33
drivers/iio/imu/bmi323/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # BMI323 IMU driver 4 + # 5 + 6 + config BMI323 7 + tristate 8 + select IIO_BUFFER 9 + select IIO_TRIGGERED_BUFFER 10 + 11 + config BMI323_I2C 12 + tristate "Bosch BMI323 I2C driver" 13 + depends on I2C 14 + select BMI323 15 + select REGMAP_I2C 16 + help 17 + Enable support for the Bosch BMI323 6-Axis IMU connected to I2C 18 + interface. 19 + 20 + This driver can also be built as a module. If so, the module will be 21 + called bmi323_i2c. 22 + 23 + config BMI323_SPI 24 + tristate "Bosch BMI323 SPI driver" 25 + depends on SPI 26 + select BMI323 27 + select REGMAP_SPI 28 + help 29 + Enable support for the Bosch BMI323 6-Axis IMU connected to SPI 30 + interface. 31 + 32 + This driver can also be built as a module. If so, the module will be 33 + called bmi323_spi.
+7
drivers/iio/imu/bmi323/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # Makefile for Bosch BMI323 IMU 4 + # 5 + obj-$(CONFIG_BMI323) += bmi323_core.o 6 + obj-$(CONFIG_BMI323_I2C) += bmi323_i2c.o 7 + obj-$(CONFIG_BMI323_SPI) += bmi323_spi.o
+209
drivers/iio/imu/bmi323/bmi323.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * IIO driver for Bosch BMI323 6-Axis IMU 4 + * 5 + * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com> 6 + */ 7 + 8 + #ifndef _BMI323_H_ 9 + #define _BMI323_H_ 10 + 11 + #include <linux/bits.h> 12 + #include <linux/regmap.h> 13 + #include <linux/units.h> 14 + 15 + #define BMI323_I2C_DUMMY 2 16 + #define BMI323_SPI_DUMMY 1 17 + 18 + /* Register map */ 19 + 20 + #define BMI323_CHIP_ID_REG 0x00 21 + #define BMI323_CHIP_ID_VAL 0x0043 22 + #define BMI323_CHIP_ID_MSK GENMASK(7, 0) 23 + #define BMI323_ERR_REG 0x01 24 + #define BMI323_STATUS_REG 0x02 25 + #define BMI323_STATUS_POR_MSK BIT(0) 26 + 27 + /* Accelero/Gyro/Temp data registers */ 28 + #define BMI323_ACCEL_X_REG 0x03 29 + #define BMI323_GYRO_X_REG 0x06 30 + #define BMI323_TEMP_REG 0x09 31 + #define BMI323_ALL_CHAN_MSK GENMASK(5, 0) 32 + 33 + /* Status registers */ 34 + #define BMI323_STATUS_INT1_REG 0x0D 35 + #define BMI323_STATUS_INT2_REG 0x0E 36 + #define BMI323_STATUS_NOMOTION_MSK BIT(0) 37 + #define BMI323_STATUS_MOTION_MSK BIT(1) 38 + #define BMI323_STATUS_STP_WTR_MSK BIT(5) 39 + #define BMI323_STATUS_TAP_MSK BIT(8) 40 + #define BMI323_STATUS_ERROR_MSK BIT(10) 41 + #define BMI323_STATUS_TMP_DRDY_MSK BIT(11) 42 + #define BMI323_STATUS_GYR_DRDY_MSK BIT(12) 43 + #define BMI323_STATUS_ACC_DRDY_MSK BIT(13) 44 + #define BMI323_STATUS_ACC_GYR_DRDY_MSK GENMASK(13, 12) 45 + #define BMI323_STATUS_FIFO_WTRMRK_MSK BIT(14) 46 + #define BMI323_STATUS_FIFO_FULL_MSK BIT(15) 47 + 48 + /* Feature registers */ 49 + #define BMI323_FEAT_IO0_REG 0x10 50 + #define BMI323_FEAT_IO0_XYZ_NOMOTION_MSK GENMASK(2, 0) 51 + #define BMI323_FEAT_IO0_XYZ_MOTION_MSK GENMASK(5, 3) 52 + #define BMI323_FEAT_XYZ_MSK GENMASK(2, 0) 53 + #define BMI323_FEAT_IO0_STP_CNT_MSK BIT(9) 54 + #define BMI323_FEAT_IO0_S_TAP_MSK BIT(12) 55 + #define BMI323_FEAT_IO0_D_TAP_MSK BIT(13) 56 + #define BMI323_FEAT_IO1_REG 0x11 57 + #define BMI323_FEAT_IO1_ERR_MSK GENMASK(3, 0) 58 + #define BMI323_FEAT_IO2_REG 0x12 59 + #define BMI323_FEAT_IO_STATUS_REG 0x14 60 + #define BMI323_FEAT_IO_STATUS_MSK BIT(0) 61 + #define BMI323_FEAT_ENG_POLL 2000 62 + #define BMI323_FEAT_ENG_TIMEOUT 10000 63 + 64 + /* FIFO registers */ 65 + #define BMI323_FIFO_FILL_LEVEL_REG 0x15 66 + #define BMI323_FIFO_DATA_REG 0x16 67 + 68 + /* Accelero/Gyro config registers */ 69 + #define BMI323_ACC_CONF_REG 0x20 70 + #define BMI323_GYRO_CONF_REG 0x21 71 + #define BMI323_ACC_GYRO_CONF_MODE_MSK GENMASK(14, 12) 72 + #define BMI323_ACC_GYRO_CONF_ODR_MSK GENMASK(3, 0) 73 + #define BMI323_ACC_GYRO_CONF_SCL_MSK GENMASK(6, 4) 74 + #define BMI323_ACC_GYRO_CONF_BW_MSK BIT(7) 75 + #define BMI323_ACC_GYRO_CONF_AVG_MSK GENMASK(10, 8) 76 + 77 + /* FIFO registers */ 78 + #define BMI323_FIFO_WTRMRK_REG 0x35 79 + #define BMI323_FIFO_CONF_REG 0x36 80 + #define BMI323_FIFO_CONF_STP_FUL_MSK BIT(0) 81 + #define BMI323_FIFO_CONF_ACC_GYR_EN_MSK GENMASK(10, 9) 82 + #define BMI323_FIFO_ACC_GYR_MSK GENMASK(1, 0) 83 + #define BMI323_FIFO_CTRL_REG 0x37 84 + #define BMI323_FIFO_FLUSH_MSK BIT(0) 85 + 86 + /* Interrupt pin config registers */ 87 + #define BMI323_IO_INT_CTR_REG 0x38 88 + #define BMI323_IO_INT1_LVL_MSK BIT(0) 89 + #define BMI323_IO_INT1_OD_MSK BIT(1) 90 + #define BMI323_IO_INT1_OP_EN_MSK BIT(2) 91 + #define BMI323_IO_INT1_LVL_OD_OP_MSK GENMASK(2, 0) 92 + #define BMI323_IO_INT2_LVL_MSK BIT(8) 93 + #define BMI323_IO_INT2_OD_MSK BIT(9) 94 + #define BMI323_IO_INT2_OP_EN_MSK BIT(10) 95 + #define BMI323_IO_INT2_LVL_OD_OP_MSK GENMASK(10, 8) 96 + #define BMI323_IO_INT_CONF_REG 0x39 97 + #define BMI323_IO_INT_LTCH_MSK BIT(0) 98 + #define BMI323_INT_MAP1_REG 0x3A 99 + #define BMI323_INT_MAP2_REG 0x3B 100 + #define BMI323_NOMOTION_MSK GENMASK(1, 0) 101 + #define BMI323_MOTION_MSK GENMASK(3, 2) 102 + #define BMI323_STEP_CNT_MSK GENMASK(11, 10) 103 + #define BMI323_TAP_MSK GENMASK(1, 0) 104 + #define BMI323_TMP_DRDY_MSK GENMASK(7, 6) 105 + #define BMI323_GYR_DRDY_MSK GENMASK(9, 8) 106 + #define BMI323_ACC_DRDY_MSK GENMASK(11, 10) 107 + #define BMI323_FIFO_WTRMRK_MSK GENMASK(13, 12) 108 + #define BMI323_FIFO_FULL_MSK GENMASK(15, 14) 109 + 110 + /* Feature registers */ 111 + #define BMI323_FEAT_CTRL_REG 0x40 112 + #define BMI323_FEAT_ENG_EN_MSK BIT(0) 113 + #define BMI323_FEAT_DATA_ADDR 0x41 114 + #define BMI323_FEAT_DATA_TX 0x42 115 + #define BMI323_FEAT_DATA_STATUS 0x43 116 + #define BMI323_FEAT_DATA_TX_RDY_MSK BIT(1) 117 + #define BMI323_FEAT_EVNT_EXT_REG 0x47 118 + #define BMI323_FEAT_EVNT_EXT_S_MSK BIT(3) 119 + #define BMI323_FEAT_EVNT_EXT_D_MSK BIT(4) 120 + 121 + #define BMI323_CMD_REG 0x7E 122 + #define BMI323_RST_VAL 0xDEAF 123 + #define BMI323_CFG_RES_REG 0x7F 124 + 125 + /* Extended registers */ 126 + #define BMI323_GEN_SET1_REG 0x02 127 + #define BMI323_GEN_SET1_MODE_MSK BIT(0) 128 + #define BMI323_GEN_HOLD_DUR_MSK GENMASK(4, 1) 129 + 130 + /* Any Motion/No Motion config registers */ 131 + #define BMI323_ANYMO1_REG 0x05 132 + #define BMI323_NOMO1_REG 0x08 133 + #define BMI323_MO2_OFFSET 0x01 134 + #define BMI323_MO3_OFFSET 0x02 135 + #define BMI323_MO1_REF_UP_MSK BIT(12) 136 + #define BMI323_MO1_SLOPE_TH_MSK GENMASK(11, 0) 137 + #define BMI323_MO2_HYSTR_MSK GENMASK(9, 0) 138 + #define BMI323_MO3_DURA_MSK GENMASK(12, 0) 139 + 140 + /* Step counter config registers */ 141 + #define BMI323_STEP_SC1_REG 0x10 142 + #define BMI323_STEP_SC1_WTRMRK_MSK GENMASK(9, 0) 143 + #define BMI323_STEP_SC1_RST_CNT_MSK BIT(10) 144 + #define BMI323_STEP_SC1_REG 0x10 145 + #define BMI323_STEP_LEN 2 146 + 147 + /* Tap gesture config registers */ 148 + #define BMI323_TAP1_REG 0x1E 149 + #define BMI323_TAP1_AXIS_SEL_MSK GENMASK(1, 0) 150 + #define BMI323_AXIS_XYZ_MSK GENMASK(1, 0) 151 + #define BMI323_TAP1_TIMOUT_MSK BIT(2) 152 + #define BMI323_TAP1_MAX_PEAKS_MSK GENMASK(5, 3) 153 + #define BMI323_TAP1_MODE_MSK GENMASK(7, 6) 154 + #define BMI323_TAP2_REG 0x1F 155 + #define BMI323_TAP2_THRES_MSK GENMASK(9, 0) 156 + #define BMI323_TAP2_MAX_DUR_MSK GENMASK(15, 10) 157 + #define BMI323_TAP3_REG 0x20 158 + #define BMI323_TAP3_QUIET_TIM_MSK GENMASK(15, 12) 159 + #define BMI323_TAP3_QT_BW_TAP_MSK GENMASK(11, 8) 160 + #define BMI323_TAP3_QT_AFT_GES_MSK GENMASK(15, 12) 161 + 162 + #define BMI323_MOTION_THRES_SCALE 512 163 + #define BMI323_MOTION_HYSTR_SCALE 512 164 + #define BMI323_MOTION_DURAT_SCALE 50 165 + #define BMI323_TAP_THRES_SCALE 512 166 + #define BMI323_DUR_BW_TAP_SCALE 200 167 + #define BMI323_QUITE_TIM_GES_SCALE 25 168 + #define BMI323_MAX_GES_DUR_SCALE 25 169 + 170 + /* 171 + * The formula to calculate temperature in C. 172 + * See datasheet section 6.1.1, Register Map Overview 173 + * 174 + * T_C = (temp_raw / 512) + 23 175 + */ 176 + #define BMI323_TEMP_OFFSET 11776 177 + #define BMI323_TEMP_SCALE 1953125 178 + 179 + /* 180 + * The BMI323 features a FIFO with a capacity of 2048 bytes. Each frame 181 + * consists of accelerometer (X, Y, Z) data and gyroscope (X, Y, Z) data, 182 + * totaling 6 words or 12 bytes. The FIFO buffer can hold a total of 183 + * 170 frames. 184 + * 185 + * If a watermark interrupt is configured for 170 frames, the interrupt will 186 + * trigger when the FIFO reaches 169 frames, so limit the maximum watermark 187 + * level to 169 frames. In terms of data, 169 frames would equal 1014 bytes, 188 + * which is approximately 2 frames before the FIFO reaches its full capacity. 189 + * See datasheet section 5.7.3 FIFO Buffer Interrupts 190 + */ 191 + #define BMI323_BYTES_PER_SAMPLE 2 192 + #define BMI323_FIFO_LENGTH_IN_BYTES 2048 193 + #define BMI323_FIFO_FRAME_LENGTH 6 194 + #define BMI323_FIFO_FULL_IN_FRAMES \ 195 + ((BMI323_FIFO_LENGTH_IN_BYTES / \ 196 + (BMI323_BYTES_PER_SAMPLE * BMI323_FIFO_FRAME_LENGTH)) - 1) 197 + #define BMI323_FIFO_FULL_IN_WORDS \ 198 + (BMI323_FIFO_FULL_IN_FRAMES * BMI323_FIFO_FRAME_LENGTH) 199 + 200 + #define BMI323_INT_MICRO_TO_RAW(val, val2, scale) ((val) * (scale) + \ 201 + ((val2) * (scale)) / MEGA) 202 + 203 + #define BMI323_RAW_TO_MICRO(raw, scale) ((((raw) % (scale)) * MEGA) / scale) 204 + 205 + struct device; 206 + int bmi323_core_probe(struct device *dev); 207 + extern const struct regmap_config bmi323_regmap_config; 208 + 209 + #endif
+2139
drivers/iio/imu/bmi323/bmi323_core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * IIO core driver for Bosch BMI323 6-Axis IMU. 4 + * 5 + * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com> 6 + * 7 + * Datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi323-ds000.pdf 8 + */ 9 + 10 + #include <linux/bitfield.h> 11 + #include <linux/cleanup.h> 12 + #include <linux/device.h> 13 + #include <linux/interrupt.h> 14 + #include <linux/minmax.h> 15 + #include <linux/module.h> 16 + #include <linux/mutex.h> 17 + #include <linux/property.h> 18 + #include <linux/regmap.h> 19 + #include <linux/regulator/consumer.h> 20 + #include <linux/units.h> 21 + 22 + #include <asm/unaligned.h> 23 + 24 + #include <linux/iio/buffer.h> 25 + #include <linux/iio/events.h> 26 + #include <linux/iio/iio.h> 27 + #include <linux/iio/sysfs.h> 28 + #include <linux/iio/trigger.h> 29 + #include <linux/iio/trigger_consumer.h> 30 + #include <linux/iio/triggered_buffer.h> 31 + 32 + #include "bmi323.h" 33 + 34 + enum bmi323_sensor_type { 35 + BMI323_ACCEL, 36 + BMI323_GYRO, 37 + BMI323_SENSORS_CNT, 38 + }; 39 + 40 + enum bmi323_opr_mode { 41 + ACC_GYRO_MODE_DISABLE = 0x00, 42 + GYRO_DRIVE_MODE_ENABLED = 0x01, 43 + ACC_GYRO_MODE_DUTYCYCLE = 0x03, 44 + ACC_GYRO_MODE_CONTINOUS = 0x04, 45 + ACC_GYRO_MODE_HIGH_PERF = 0x07, 46 + }; 47 + 48 + enum bmi323_state { 49 + BMI323_IDLE, 50 + BMI323_BUFFER_DRDY_TRIGGERED, 51 + BMI323_BUFFER_FIFO, 52 + }; 53 + 54 + enum bmi323_irq_pin { 55 + BMI323_IRQ_DISABLED, 56 + BMI323_IRQ_INT1, 57 + BMI323_IRQ_INT2, 58 + }; 59 + 60 + enum bmi323_3db_bw { 61 + BMI323_BW_ODR_BY_2, 62 + BMI323_BW_ODR_BY_4, 63 + }; 64 + 65 + enum bmi323_scan { 66 + BMI323_ACCEL_X, 67 + BMI323_ACCEL_Y, 68 + BMI323_ACCEL_Z, 69 + BMI323_GYRO_X, 70 + BMI323_GYRO_Y, 71 + BMI323_GYRO_Z, 72 + BMI323_CHAN_MAX 73 + }; 74 + 75 + struct bmi323_hw { 76 + u8 data; 77 + u8 config; 78 + const int (*scale_table)[2]; 79 + int scale_table_len; 80 + }; 81 + 82 + /* 83 + * The accelerometer supports +-2G/4G/8G/16G ranges, and the resolution of 84 + * each sample is 16 bits, signed. 85 + * At +-8G the scale can calculated by 86 + * ((8 + 8) * 9.80665 / (2^16 - 1)) * 10^6 = 2394.23819 scale in micro 87 + * 88 + */ 89 + static const int bmi323_accel_scale[][2] = { 90 + { 0, 598 }, 91 + { 0, 1197 }, 92 + { 0, 2394 }, 93 + { 0, 4788 }, 94 + }; 95 + 96 + static const int bmi323_gyro_scale[][2] = { 97 + { 0, 66 }, 98 + { 0, 133 }, 99 + { 0, 266 }, 100 + { 0, 532 }, 101 + { 0, 1065 }, 102 + }; 103 + 104 + static const int bmi323_accel_gyro_avrg[] = {0, 2, 4, 8, 16, 32, 64}; 105 + 106 + static const struct bmi323_hw bmi323_hw[2] = { 107 + [BMI323_ACCEL] = { 108 + .data = BMI323_ACCEL_X_REG, 109 + .config = BMI323_ACC_CONF_REG, 110 + .scale_table = bmi323_accel_scale, 111 + .scale_table_len = ARRAY_SIZE(bmi323_accel_scale), 112 + }, 113 + [BMI323_GYRO] = { 114 + .data = BMI323_GYRO_X_REG, 115 + .config = BMI323_GYRO_CONF_REG, 116 + .scale_table = bmi323_gyro_scale, 117 + .scale_table_len = ARRAY_SIZE(bmi323_gyro_scale), 118 + }, 119 + }; 120 + 121 + struct bmi323_data { 122 + struct device *dev; 123 + struct regmap *regmap; 124 + struct iio_mount_matrix orientation; 125 + enum bmi323_irq_pin irq_pin; 126 + struct iio_trigger *trig; 127 + bool drdy_trigger_enabled; 128 + enum bmi323_state state; 129 + s64 fifo_tstamp, old_fifo_tstamp; 130 + u32 odrns[BMI323_SENSORS_CNT]; 131 + u32 odrhz[BMI323_SENSORS_CNT]; 132 + unsigned int feature_events; 133 + 134 + /* 135 + * Lock to protect the members of device's private data from concurrent 136 + * access and also to serialize the access of extended registers. 137 + * See bmi323_write_ext_reg(..) for more info. 138 + */ 139 + struct mutex mutex; 140 + int watermark; 141 + __le16 fifo_buff[BMI323_FIFO_FULL_IN_WORDS] __aligned(IIO_DMA_MINALIGN); 142 + struct { 143 + __le16 channels[BMI323_CHAN_MAX]; 144 + s64 ts __aligned(8); 145 + } buffer; 146 + __le16 steps_count[BMI323_STEP_LEN]; 147 + }; 148 + 149 + static const struct iio_mount_matrix * 150 + bmi323_get_mount_matrix(const struct iio_dev *idev, 151 + const struct iio_chan_spec *chan) 152 + { 153 + struct bmi323_data *data = iio_priv(idev); 154 + 155 + return &data->orientation; 156 + } 157 + 158 + static const struct iio_chan_spec_ext_info bmi323_ext_info[] = { 159 + IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, bmi323_get_mount_matrix), 160 + { } 161 + }; 162 + 163 + static const struct iio_event_spec bmi323_step_wtrmrk_event = { 164 + .type = IIO_EV_TYPE_CHANGE, 165 + .dir = IIO_EV_DIR_NONE, 166 + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | 167 + BIT(IIO_EV_INFO_VALUE), 168 + }; 169 + 170 + static const struct iio_event_spec bmi323_accel_event[] = { 171 + { 172 + .type = IIO_EV_TYPE_MAG, 173 + .dir = IIO_EV_DIR_FALLING, 174 + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | 175 + BIT(IIO_EV_INFO_PERIOD) | 176 + BIT(IIO_EV_INFO_HYSTERESIS) | 177 + BIT(IIO_EV_INFO_ENABLE), 178 + }, 179 + { 180 + .type = IIO_EV_TYPE_MAG, 181 + .dir = IIO_EV_DIR_RISING, 182 + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | 183 + BIT(IIO_EV_INFO_PERIOD) | 184 + BIT(IIO_EV_INFO_HYSTERESIS) | 185 + BIT(IIO_EV_INFO_ENABLE), 186 + }, 187 + { 188 + .type = IIO_EV_TYPE_GESTURE, 189 + .dir = IIO_EV_DIR_SINGLETAP, 190 + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | 191 + BIT(IIO_EV_INFO_VALUE) | 192 + BIT(IIO_EV_INFO_RESET_TIMEOUT), 193 + }, 194 + { 195 + .type = IIO_EV_TYPE_GESTURE, 196 + .dir = IIO_EV_DIR_DOUBLETAP, 197 + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | 198 + BIT(IIO_EV_INFO_VALUE) | 199 + BIT(IIO_EV_INFO_RESET_TIMEOUT) | 200 + BIT(IIO_EV_INFO_TAP2_MIN_DELAY), 201 + }, 202 + }; 203 + 204 + #define BMI323_ACCEL_CHANNEL(_type, _axis, _index) { \ 205 + .type = _type, \ 206 + .modified = 1, \ 207 + .channel2 = IIO_MOD_##_axis, \ 208 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 209 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 210 + BIT(IIO_CHAN_INFO_SCALE) | \ 211 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 212 + .info_mask_shared_by_type_available = \ 213 + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 214 + BIT(IIO_CHAN_INFO_SCALE) | \ 215 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 216 + .scan_index = _index, \ 217 + .scan_type = { \ 218 + .sign = 's', \ 219 + .realbits = 16, \ 220 + .storagebits = 16, \ 221 + .endianness = IIO_LE, \ 222 + }, \ 223 + .ext_info = bmi323_ext_info, \ 224 + .event_spec = bmi323_accel_event, \ 225 + .num_event_specs = ARRAY_SIZE(bmi323_accel_event), \ 226 + } 227 + 228 + #define BMI323_GYRO_CHANNEL(_type, _axis, _index) { \ 229 + .type = _type, \ 230 + .modified = 1, \ 231 + .channel2 = IIO_MOD_##_axis, \ 232 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 233 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 234 + BIT(IIO_CHAN_INFO_SCALE) | \ 235 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 236 + .info_mask_shared_by_type_available = \ 237 + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 238 + BIT(IIO_CHAN_INFO_SCALE) | \ 239 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 240 + .scan_index = _index, \ 241 + .scan_type = { \ 242 + .sign = 's', \ 243 + .realbits = 16, \ 244 + .storagebits = 16, \ 245 + .endianness = IIO_LE, \ 246 + }, \ 247 + .ext_info = bmi323_ext_info, \ 248 + } 249 + 250 + static const struct iio_chan_spec bmi323_channels[] = { 251 + BMI323_ACCEL_CHANNEL(IIO_ACCEL, X, BMI323_ACCEL_X), 252 + BMI323_ACCEL_CHANNEL(IIO_ACCEL, Y, BMI323_ACCEL_Y), 253 + BMI323_ACCEL_CHANNEL(IIO_ACCEL, Z, BMI323_ACCEL_Z), 254 + BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, X, BMI323_GYRO_X), 255 + BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, Y, BMI323_GYRO_Y), 256 + BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, Z, BMI323_GYRO_Z), 257 + { 258 + .type = IIO_TEMP, 259 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 260 + BIT(IIO_CHAN_INFO_OFFSET) | 261 + BIT(IIO_CHAN_INFO_SCALE), 262 + .scan_index = -1, 263 + }, 264 + { 265 + .type = IIO_STEPS, 266 + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | 267 + BIT(IIO_CHAN_INFO_ENABLE), 268 + .scan_index = -1, 269 + .event_spec = &bmi323_step_wtrmrk_event, 270 + .num_event_specs = 1, 271 + 272 + }, 273 + IIO_CHAN_SOFT_TIMESTAMP(BMI323_CHAN_MAX), 274 + }; 275 + 276 + static const int bmi323_acc_gyro_odr[][2] = { 277 + { 0, 781250 }, 278 + { 1, 562500 }, 279 + { 3, 125000 }, 280 + { 6, 250000 }, 281 + { 12, 500000 }, 282 + { 25, 0 }, 283 + { 50, 0 }, 284 + { 100, 0 }, 285 + { 200, 0 }, 286 + { 400, 0 }, 287 + { 800, 0 }, 288 + }; 289 + 290 + static const int bmi323_acc_gyro_odrns[] = { 291 + 1280 * MEGA, 292 + 640 * MEGA, 293 + 320 * MEGA, 294 + 160 * MEGA, 295 + 80 * MEGA, 296 + 40 * MEGA, 297 + 20 * MEGA, 298 + 10 * MEGA, 299 + 5 * MEGA, 300 + 2500 * KILO, 301 + 1250 * KILO, 302 + }; 303 + 304 + static enum bmi323_sensor_type bmi323_iio_to_sensor(enum iio_chan_type iio_type) 305 + { 306 + switch (iio_type) { 307 + case IIO_ACCEL: 308 + return BMI323_ACCEL; 309 + case IIO_ANGL_VEL: 310 + return BMI323_GYRO; 311 + default: 312 + return -EINVAL; 313 + } 314 + } 315 + 316 + static int bmi323_set_mode(struct bmi323_data *data, 317 + enum bmi323_sensor_type sensor, 318 + enum bmi323_opr_mode mode) 319 + { 320 + guard(mutex)(&data->mutex); 321 + return regmap_update_bits(data->regmap, bmi323_hw[sensor].config, 322 + BMI323_ACC_GYRO_CONF_MODE_MSK, 323 + FIELD_PREP(BMI323_ACC_GYRO_CONF_MODE_MSK, 324 + mode)); 325 + } 326 + 327 + /* 328 + * When writing data to extended register there must be no communication to 329 + * any other register before write transaction is complete. 330 + * See datasheet section 6.2 Extended Register Map Description. 331 + */ 332 + static int bmi323_write_ext_reg(struct bmi323_data *data, unsigned int ext_addr, 333 + unsigned int ext_data) 334 + { 335 + int ret, feature_status; 336 + 337 + ret = regmap_read(data->regmap, BMI323_FEAT_DATA_STATUS, 338 + &feature_status); 339 + if (ret) 340 + return ret; 341 + 342 + if (!FIELD_GET(BMI323_FEAT_DATA_TX_RDY_MSK, feature_status)) 343 + return -EBUSY; 344 + 345 + ret = regmap_write(data->regmap, BMI323_FEAT_DATA_ADDR, ext_addr); 346 + if (ret) 347 + return ret; 348 + 349 + return regmap_write(data->regmap, BMI323_FEAT_DATA_TX, ext_data); 350 + } 351 + 352 + /* 353 + * When reading data from extended register there must be no communication to 354 + * any other register before read transaction is complete. 355 + * See datasheet section 6.2 Extended Register Map Description. 356 + */ 357 + static int bmi323_read_ext_reg(struct bmi323_data *data, unsigned int ext_addr, 358 + unsigned int *ext_data) 359 + { 360 + int ret, feature_status; 361 + 362 + ret = regmap_read(data->regmap, BMI323_FEAT_DATA_STATUS, 363 + &feature_status); 364 + if (ret) 365 + return ret; 366 + 367 + if (!FIELD_GET(BMI323_FEAT_DATA_TX_RDY_MSK, feature_status)) 368 + return -EBUSY; 369 + 370 + ret = regmap_write(data->regmap, BMI323_FEAT_DATA_ADDR, ext_addr); 371 + if (ret) 372 + return ret; 373 + 374 + return regmap_read(data->regmap, BMI323_FEAT_DATA_TX, ext_data); 375 + } 376 + 377 + static int bmi323_update_ext_reg(struct bmi323_data *data, 378 + unsigned int ext_addr, 379 + unsigned int mask, unsigned int ext_data) 380 + { 381 + unsigned int value; 382 + int ret; 383 + 384 + ret = bmi323_read_ext_reg(data, ext_addr, &value); 385 + if (ret) 386 + return ret; 387 + 388 + set_mask_bits(&value, mask, ext_data); 389 + 390 + return bmi323_write_ext_reg(data, ext_addr, value); 391 + } 392 + 393 + static int bmi323_get_error_status(struct bmi323_data *data) 394 + { 395 + int error, ret; 396 + 397 + guard(mutex)(&data->mutex); 398 + ret = regmap_read(data->regmap, BMI323_ERR_REG, &error); 399 + if (ret) 400 + return ret; 401 + 402 + if (error) 403 + dev_err(data->dev, "Sensor error 0x%x\n", error); 404 + 405 + return error; 406 + } 407 + 408 + static int bmi323_feature_engine_events(struct bmi323_data *data, 409 + const unsigned int event_mask, 410 + bool state) 411 + { 412 + unsigned int value; 413 + int ret; 414 + 415 + ret = regmap_read(data->regmap, BMI323_FEAT_IO0_REG, &value); 416 + if (ret) 417 + return ret; 418 + 419 + /* Register must be cleared before changing an active config */ 420 + ret = regmap_write(data->regmap, BMI323_FEAT_IO0_REG, 0); 421 + if (ret) 422 + return ret; 423 + 424 + if (state) 425 + value |= event_mask; 426 + else 427 + value &= ~event_mask; 428 + 429 + ret = regmap_write(data->regmap, BMI323_FEAT_IO0_REG, value); 430 + if (ret) 431 + return ret; 432 + 433 + return regmap_write(data->regmap, BMI323_FEAT_IO_STATUS_REG, 434 + BMI323_FEAT_IO_STATUS_MSK); 435 + } 436 + 437 + static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state) 438 + { 439 + enum bmi323_irq_pin step_irq; 440 + int ret; 441 + 442 + guard(mutex)(&data->mutex); 443 + if (!FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, data->feature_events)) 444 + return -EINVAL; 445 + 446 + if (state) 447 + step_irq = data->irq_pin; 448 + else 449 + step_irq = BMI323_IRQ_DISABLED; 450 + 451 + ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG, 452 + BMI323_STEP_SC1_WTRMRK_MSK, 453 + FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK, 454 + state ? 1 : 0)); 455 + if (ret) 456 + return ret; 457 + 458 + return regmap_update_bits(data->regmap, BMI323_INT_MAP1_REG, 459 + BMI323_STEP_CNT_MSK, 460 + FIELD_PREP(BMI323_STEP_CNT_MSK, step_irq)); 461 + } 462 + 463 + static int bmi323_motion_config_reg(enum iio_event_direction dir) 464 + { 465 + switch (dir) { 466 + case IIO_EV_DIR_RISING: 467 + return BMI323_ANYMO1_REG; 468 + case IIO_EV_DIR_FALLING: 469 + return BMI323_NOMO1_REG; 470 + default: 471 + return -EINVAL; 472 + } 473 + } 474 + 475 + static int bmi323_motion_event_en(struct bmi323_data *data, 476 + enum iio_event_direction dir, int state) 477 + { 478 + unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0; 479 + int config, ret, msk, raw, field_value; 480 + enum bmi323_irq_pin motion_irq; 481 + int irq_msk, irq_field_val; 482 + 483 + if (state) 484 + motion_irq = data->irq_pin; 485 + else 486 + motion_irq = BMI323_IRQ_DISABLED; 487 + 488 + switch (dir) { 489 + case IIO_EV_DIR_RISING: 490 + msk = BMI323_FEAT_IO0_XYZ_MOTION_MSK; 491 + raw = 512; 492 + config = BMI323_ANYMO1_REG; 493 + irq_msk = BMI323_MOTION_MSK; 494 + irq_field_val = FIELD_PREP(BMI323_MOTION_MSK, motion_irq); 495 + field_value = FIELD_PREP(BMI323_FEAT_IO0_XYZ_MOTION_MSK, 496 + state_value); 497 + break; 498 + case IIO_EV_DIR_FALLING: 499 + msk = BMI323_FEAT_IO0_XYZ_NOMOTION_MSK; 500 + raw = 0; 501 + config = BMI323_NOMO1_REG; 502 + irq_msk = BMI323_NOMOTION_MSK; 503 + irq_field_val = FIELD_PREP(BMI323_NOMOTION_MSK, motion_irq); 504 + field_value = FIELD_PREP(BMI323_FEAT_IO0_XYZ_NOMOTION_MSK, 505 + state_value); 506 + break; 507 + default: 508 + return -EINVAL; 509 + } 510 + 511 + guard(mutex)(&data->mutex); 512 + ret = bmi323_feature_engine_events(data, msk, state); 513 + if (ret) 514 + return ret; 515 + 516 + ret = bmi323_update_ext_reg(data, config, 517 + BMI323_MO1_REF_UP_MSK, 518 + FIELD_PREP(BMI323_MO1_REF_UP_MSK, 0)); 519 + if (ret) 520 + return ret; 521 + 522 + /* Set initial value to avoid interrupts while enabling*/ 523 + ret = bmi323_update_ext_reg(data, config, 524 + BMI323_MO1_SLOPE_TH_MSK, 525 + FIELD_PREP(BMI323_MO1_SLOPE_TH_MSK, raw)); 526 + if (ret) 527 + return ret; 528 + 529 + ret = regmap_update_bits(data->regmap, BMI323_INT_MAP1_REG, irq_msk, 530 + irq_field_val); 531 + if (ret) 532 + return ret; 533 + 534 + set_mask_bits(&data->feature_events, msk, field_value); 535 + 536 + return 0; 537 + } 538 + 539 + static int bmi323_tap_event_en(struct bmi323_data *data, 540 + enum iio_event_direction dir, int state) 541 + { 542 + enum bmi323_irq_pin tap_irq; 543 + int ret, tap_enabled; 544 + 545 + guard(mutex)(&data->mutex); 546 + 547 + if (data->odrhz[BMI323_ACCEL] < 200) { 548 + dev_err(data->dev, "Invalid accelrometer parameter\n"); 549 + return -EINVAL; 550 + } 551 + 552 + switch (dir) { 553 + case IIO_EV_DIR_SINGLETAP: 554 + ret = bmi323_feature_engine_events(data, 555 + BMI323_FEAT_IO0_S_TAP_MSK, 556 + state); 557 + if (ret) 558 + return ret; 559 + 560 + set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_S_TAP_MSK, 561 + FIELD_PREP(BMI323_FEAT_IO0_S_TAP_MSK, state)); 562 + break; 563 + case IIO_EV_DIR_DOUBLETAP: 564 + ret = bmi323_feature_engine_events(data, 565 + BMI323_FEAT_IO0_D_TAP_MSK, 566 + state); 567 + if (ret) 568 + return ret; 569 + 570 + set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_D_TAP_MSK, 571 + FIELD_PREP(BMI323_FEAT_IO0_D_TAP_MSK, state)); 572 + break; 573 + default: 574 + return -EINVAL; 575 + } 576 + 577 + tap_enabled = FIELD_GET(BMI323_FEAT_IO0_S_TAP_MSK | 578 + BMI323_FEAT_IO0_D_TAP_MSK, 579 + data->feature_events); 580 + 581 + if (tap_enabled) 582 + tap_irq = data->irq_pin; 583 + else 584 + tap_irq = BMI323_IRQ_DISABLED; 585 + 586 + ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG, 587 + BMI323_TAP_MSK, 588 + FIELD_PREP(BMI323_TAP_MSK, tap_irq)); 589 + if (ret) 590 + return ret; 591 + 592 + if (!state) 593 + return 0; 594 + 595 + ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG, 596 + BMI323_TAP1_MAX_PEAKS_MSK, 597 + FIELD_PREP(BMI323_TAP1_MAX_PEAKS_MSK, 598 + 0x04)); 599 + if (ret) 600 + return ret; 601 + 602 + ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG, 603 + BMI323_TAP1_AXIS_SEL_MSK, 604 + FIELD_PREP(BMI323_TAP1_AXIS_SEL_MSK, 605 + BMI323_AXIS_XYZ_MSK)); 606 + if (ret) 607 + return ret; 608 + 609 + return bmi323_update_ext_reg(data, BMI323_TAP1_REG, 610 + BMI323_TAP1_TIMOUT_MSK, 611 + FIELD_PREP(BMI323_TAP1_TIMOUT_MSK, 612 + 0)); 613 + } 614 + 615 + static ssize_t in_accel_gesture_tap_wait_dur_show(struct device *dev, 616 + struct device_attribute *attr, 617 + char *buf) 618 + { 619 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 620 + struct bmi323_data *data = iio_priv(indio_dev); 621 + unsigned int reg_value, raw; 622 + int ret, val[2]; 623 + 624 + scoped_guard(mutex, &data->mutex) { 625 + ret = bmi323_read_ext_reg(data, BMI323_TAP2_REG, &reg_value); 626 + if (ret) 627 + return ret; 628 + } 629 + 630 + raw = FIELD_GET(BMI323_TAP2_MAX_DUR_MSK, reg_value); 631 + val[0] = raw / BMI323_MAX_GES_DUR_SCALE; 632 + val[1] = BMI323_RAW_TO_MICRO(raw, BMI323_MAX_GES_DUR_SCALE); 633 + 634 + return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, ARRAY_SIZE(val), 635 + val); 636 + } 637 + 638 + static ssize_t in_accel_gesture_tap_wait_dur_store(struct device *dev, 639 + struct device_attribute *attr, 640 + const char *buf, size_t len) 641 + { 642 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 643 + struct bmi323_data *data = iio_priv(indio_dev); 644 + int ret, val_int, val_fract, raw; 645 + 646 + ret = iio_str_to_fixpoint(buf, 100000, &val_int, &val_fract); 647 + if (ret) 648 + return ret; 649 + 650 + raw = BMI323_INT_MICRO_TO_RAW(val_int, val_fract, 651 + BMI323_MAX_GES_DUR_SCALE); 652 + if (!in_range(raw, 0, 64)) 653 + return -EINVAL; 654 + 655 + guard(mutex)(&data->mutex); 656 + ret = bmi323_update_ext_reg(data, BMI323_TAP2_REG, 657 + BMI323_TAP2_MAX_DUR_MSK, 658 + FIELD_PREP(BMI323_TAP2_MAX_DUR_MSK, raw)); 659 + if (ret) 660 + return ret; 661 + 662 + return len; 663 + } 664 + 665 + /* 666 + * Maximum duration from first tap within the second tap is expected to happen. 667 + * This timeout is applicable only if gesture_tap_wait_timeout is enabled. 668 + */ 669 + static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_wait_dur, 0); 670 + 671 + static ssize_t in_accel_gesture_tap_wait_timeout_show(struct device *dev, 672 + struct device_attribute *attr, 673 + char *buf) 674 + { 675 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 676 + struct bmi323_data *data = iio_priv(indio_dev); 677 + unsigned int reg_value, raw; 678 + int ret; 679 + 680 + scoped_guard(mutex, &data->mutex) { 681 + ret = bmi323_read_ext_reg(data, BMI323_TAP1_REG, &reg_value); 682 + if (ret) 683 + return ret; 684 + } 685 + 686 + raw = FIELD_GET(BMI323_TAP1_TIMOUT_MSK, reg_value); 687 + 688 + return iio_format_value(buf, IIO_VAL_INT, 1, &raw); 689 + } 690 + 691 + static ssize_t in_accel_gesture_tap_wait_timeout_store(struct device *dev, 692 + struct device_attribute *attr, 693 + const char *buf, 694 + size_t len) 695 + { 696 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 697 + struct bmi323_data *data = iio_priv(indio_dev); 698 + bool val; 699 + int ret; 700 + 701 + ret = kstrtobool(buf, &val); 702 + if (ret) 703 + return ret; 704 + 705 + guard(mutex)(&data->mutex); 706 + ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG, 707 + BMI323_TAP1_TIMOUT_MSK, 708 + FIELD_PREP(BMI323_TAP1_TIMOUT_MSK, val)); 709 + if (ret) 710 + return ret; 711 + 712 + return len; 713 + } 714 + 715 + /* Enable/disable gesture confirmation with wait time */ 716 + static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_wait_timeout, 0); 717 + 718 + static IIO_CONST_ATTR(in_accel_gesture_tap_wait_dur_available, 719 + "[0.0 0.04 2.52]"); 720 + 721 + static IIO_CONST_ATTR(in_accel_gesture_doubletap_tap2_min_delay_available, 722 + "[0.005 0.005 0.075]"); 723 + 724 + static IIO_CONST_ATTR(in_accel_gesture_tap_reset_timeout_available, 725 + "[0.04 0.04 0.6]"); 726 + 727 + static IIO_CONST_ATTR(in_accel_gesture_tap_value_available, "[0.0 0.002 1.99]"); 728 + 729 + static IIO_CONST_ATTR(in_accel_mag_value_available, "[0.0 0.002 7.99]"); 730 + 731 + static IIO_CONST_ATTR(in_accel_mag_period_available, "[0.0 0.02 162.0]"); 732 + 733 + static IIO_CONST_ATTR(in_accel_mag_hysteresis_available, "[0.0 0.002 1.99]"); 734 + 735 + static struct attribute *bmi323_event_attributes[] = { 736 + &iio_const_attr_in_accel_gesture_tap_value_available.dev_attr.attr, 737 + &iio_const_attr_in_accel_gesture_tap_reset_timeout_available.dev_attr.attr, 738 + &iio_const_attr_in_accel_gesture_doubletap_tap2_min_delay_available.dev_attr.attr, 739 + &iio_const_attr_in_accel_gesture_tap_wait_dur_available.dev_attr.attr, 740 + &iio_dev_attr_in_accel_gesture_tap_wait_timeout.dev_attr.attr, 741 + &iio_dev_attr_in_accel_gesture_tap_wait_dur.dev_attr.attr, 742 + &iio_const_attr_in_accel_mag_value_available.dev_attr.attr, 743 + &iio_const_attr_in_accel_mag_period_available.dev_attr.attr, 744 + &iio_const_attr_in_accel_mag_hysteresis_available.dev_attr.attr, 745 + NULL 746 + }; 747 + 748 + static const struct attribute_group bmi323_event_attribute_group = { 749 + .attrs = bmi323_event_attributes, 750 + }; 751 + 752 + static int bmi323_write_event_config(struct iio_dev *indio_dev, 753 + const struct iio_chan_spec *chan, 754 + enum iio_event_type type, 755 + enum iio_event_direction dir, int state) 756 + { 757 + struct bmi323_data *data = iio_priv(indio_dev); 758 + 759 + switch (type) { 760 + case IIO_EV_TYPE_MAG: 761 + return bmi323_motion_event_en(data, dir, state); 762 + case IIO_EV_TYPE_GESTURE: 763 + return bmi323_tap_event_en(data, dir, state); 764 + case IIO_EV_TYPE_CHANGE: 765 + return bmi323_step_wtrmrk_en(data, state); 766 + default: 767 + return -EINVAL; 768 + } 769 + } 770 + 771 + static int bmi323_read_event_config(struct iio_dev *indio_dev, 772 + const struct iio_chan_spec *chan, 773 + enum iio_event_type type, 774 + enum iio_event_direction dir) 775 + { 776 + struct bmi323_data *data = iio_priv(indio_dev); 777 + int ret, value, reg_val; 778 + 779 + guard(mutex)(&data->mutex); 780 + 781 + switch (chan->type) { 782 + case IIO_ACCEL: 783 + switch (dir) { 784 + case IIO_EV_DIR_SINGLETAP: 785 + ret = FIELD_GET(BMI323_FEAT_IO0_S_TAP_MSK, 786 + data->feature_events); 787 + break; 788 + case IIO_EV_DIR_DOUBLETAP: 789 + ret = FIELD_GET(BMI323_FEAT_IO0_D_TAP_MSK, 790 + data->feature_events); 791 + break; 792 + case IIO_EV_DIR_RISING: 793 + value = FIELD_GET(BMI323_FEAT_IO0_XYZ_MOTION_MSK, 794 + data->feature_events); 795 + ret = value ? 1 : 0; 796 + break; 797 + case IIO_EV_DIR_FALLING: 798 + value = FIELD_GET(BMI323_FEAT_IO0_XYZ_NOMOTION_MSK, 799 + data->feature_events); 800 + ret = value ? 1 : 0; 801 + break; 802 + default: 803 + ret = -EINVAL; 804 + break; 805 + } 806 + return ret; 807 + case IIO_STEPS: 808 + ret = regmap_read(data->regmap, BMI323_INT_MAP1_REG, &reg_val); 809 + if (ret) 810 + return ret; 811 + 812 + return FIELD_GET(BMI323_STEP_CNT_MSK, reg_val) ? 1 : 0; 813 + default: 814 + return -EINVAL; 815 + } 816 + } 817 + 818 + static int bmi323_write_event_value(struct iio_dev *indio_dev, 819 + const struct iio_chan_spec *chan, 820 + enum iio_event_type type, 821 + enum iio_event_direction dir, 822 + enum iio_event_info info, 823 + int val, int val2) 824 + { 825 + struct bmi323_data *data = iio_priv(indio_dev); 826 + unsigned int raw; 827 + int reg; 828 + 829 + guard(mutex)(&data->mutex); 830 + 831 + switch (type) { 832 + case IIO_EV_TYPE_GESTURE: 833 + switch (info) { 834 + case IIO_EV_INFO_VALUE: 835 + if (!in_range(val, 0, 2)) 836 + return -EINVAL; 837 + 838 + raw = BMI323_INT_MICRO_TO_RAW(val, val2, 839 + BMI323_TAP_THRES_SCALE); 840 + 841 + return bmi323_update_ext_reg(data, BMI323_TAP2_REG, 842 + BMI323_TAP2_THRES_MSK, 843 + FIELD_PREP(BMI323_TAP2_THRES_MSK, 844 + raw)); 845 + case IIO_EV_INFO_RESET_TIMEOUT: 846 + if (val || !in_range(val2, 40000, 560001)) 847 + return -EINVAL; 848 + 849 + raw = BMI323_INT_MICRO_TO_RAW(val, val2, 850 + BMI323_QUITE_TIM_GES_SCALE); 851 + 852 + return bmi323_update_ext_reg(data, BMI323_TAP3_REG, 853 + BMI323_TAP3_QT_AFT_GES_MSK, 854 + FIELD_PREP(BMI323_TAP3_QT_AFT_GES_MSK, 855 + raw)); 856 + case IIO_EV_INFO_TAP2_MIN_DELAY: 857 + if (val || !in_range(val2, 5000, 70001)) 858 + return -EINVAL; 859 + 860 + raw = BMI323_INT_MICRO_TO_RAW(val, val2, 861 + BMI323_DUR_BW_TAP_SCALE); 862 + 863 + return bmi323_update_ext_reg(data, BMI323_TAP3_REG, 864 + BMI323_TAP3_QT_BW_TAP_MSK, 865 + FIELD_PREP(BMI323_TAP3_QT_BW_TAP_MSK, 866 + raw)); 867 + default: 868 + return -EINVAL; 869 + } 870 + case IIO_EV_TYPE_MAG: 871 + reg = bmi323_motion_config_reg(dir); 872 + if (reg < 0) 873 + return -EINVAL; 874 + 875 + switch (info) { 876 + case IIO_EV_INFO_VALUE: 877 + if (!in_range(val, 0, 8)) 878 + return -EINVAL; 879 + 880 + raw = BMI323_INT_MICRO_TO_RAW(val, val2, 881 + BMI323_MOTION_THRES_SCALE); 882 + 883 + return bmi323_update_ext_reg(data, reg, 884 + BMI323_MO1_SLOPE_TH_MSK, 885 + FIELD_PREP(BMI323_MO1_SLOPE_TH_MSK, 886 + raw)); 887 + case IIO_EV_INFO_PERIOD: 888 + if (!in_range(val, 0, 163)) 889 + return -EINVAL; 890 + 891 + raw = BMI323_INT_MICRO_TO_RAW(val, val2, 892 + BMI323_MOTION_DURAT_SCALE); 893 + 894 + return bmi323_update_ext_reg(data, 895 + reg + BMI323_MO3_OFFSET, 896 + BMI323_MO3_DURA_MSK, 897 + FIELD_PREP(BMI323_MO3_DURA_MSK, 898 + raw)); 899 + case IIO_EV_INFO_HYSTERESIS: 900 + if (!in_range(val, 0, 2)) 901 + return -EINVAL; 902 + 903 + raw = BMI323_INT_MICRO_TO_RAW(val, val2, 904 + BMI323_MOTION_HYSTR_SCALE); 905 + 906 + return bmi323_update_ext_reg(data, 907 + reg + BMI323_MO2_OFFSET, 908 + BMI323_MO2_HYSTR_MSK, 909 + FIELD_PREP(BMI323_MO2_HYSTR_MSK, 910 + raw)); 911 + default: 912 + return -EINVAL; 913 + } 914 + case IIO_EV_TYPE_CHANGE: 915 + if (!in_range(val, 0, 20461)) 916 + return -EINVAL; 917 + 918 + raw = val / 20; 919 + return bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG, 920 + BMI323_STEP_SC1_WTRMRK_MSK, 921 + FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK, 922 + raw)); 923 + default: 924 + return -EINVAL; 925 + } 926 + } 927 + 928 + static int bmi323_read_event_value(struct iio_dev *indio_dev, 929 + const struct iio_chan_spec *chan, 930 + enum iio_event_type type, 931 + enum iio_event_direction dir, 932 + enum iio_event_info info, 933 + int *val, int *val2) 934 + { 935 + struct bmi323_data *data = iio_priv(indio_dev); 936 + unsigned int raw, reg_value; 937 + int ret, reg; 938 + 939 + guard(mutex)(&data->mutex); 940 + 941 + switch (type) { 942 + case IIO_EV_TYPE_GESTURE: 943 + switch (info) { 944 + case IIO_EV_INFO_VALUE: 945 + ret = bmi323_read_ext_reg(data, BMI323_TAP2_REG, 946 + &reg_value); 947 + if (ret) 948 + return ret; 949 + 950 + raw = FIELD_GET(BMI323_TAP2_THRES_MSK, reg_value); 951 + *val = raw / BMI323_TAP_THRES_SCALE; 952 + *val2 = BMI323_RAW_TO_MICRO(raw, BMI323_TAP_THRES_SCALE); 953 + return IIO_VAL_INT_PLUS_MICRO; 954 + case IIO_EV_INFO_RESET_TIMEOUT: 955 + ret = bmi323_read_ext_reg(data, BMI323_TAP3_REG, 956 + &reg_value); 957 + if (ret) 958 + return ret; 959 + 960 + raw = FIELD_GET(BMI323_TAP3_QT_AFT_GES_MSK, reg_value); 961 + *val = 0; 962 + *val2 = BMI323_RAW_TO_MICRO(raw, 963 + BMI323_QUITE_TIM_GES_SCALE); 964 + return IIO_VAL_INT_PLUS_MICRO; 965 + case IIO_EV_INFO_TAP2_MIN_DELAY: 966 + ret = bmi323_read_ext_reg(data, BMI323_TAP3_REG, 967 + &reg_value); 968 + if (ret) 969 + return ret; 970 + 971 + raw = FIELD_GET(BMI323_TAP3_QT_BW_TAP_MSK, reg_value); 972 + *val = 0; 973 + *val2 = BMI323_RAW_TO_MICRO(raw, 974 + BMI323_DUR_BW_TAP_SCALE); 975 + return IIO_VAL_INT_PLUS_MICRO; 976 + default: 977 + return -EINVAL; 978 + } 979 + case IIO_EV_TYPE_MAG: 980 + reg = bmi323_motion_config_reg(dir); 981 + if (reg < 0) 982 + return -EINVAL; 983 + 984 + switch (info) { 985 + case IIO_EV_INFO_VALUE: 986 + ret = bmi323_read_ext_reg(data, reg, &reg_value); 987 + if (ret) 988 + return ret; 989 + 990 + raw = FIELD_GET(BMI323_MO1_SLOPE_TH_MSK, reg_value); 991 + *val = raw / BMI323_MOTION_THRES_SCALE; 992 + *val2 = BMI323_RAW_TO_MICRO(raw, 993 + BMI323_MOTION_THRES_SCALE); 994 + return IIO_VAL_INT_PLUS_MICRO; 995 + case IIO_EV_INFO_PERIOD: 996 + ret = bmi323_read_ext_reg(data, 997 + reg + BMI323_MO3_OFFSET, 998 + &reg_value); 999 + if (ret) 1000 + return ret; 1001 + 1002 + raw = FIELD_GET(BMI323_MO3_DURA_MSK, reg_value); 1003 + *val = raw / BMI323_MOTION_DURAT_SCALE; 1004 + *val2 = BMI323_RAW_TO_MICRO(raw, 1005 + BMI323_MOTION_DURAT_SCALE); 1006 + return IIO_VAL_INT_PLUS_MICRO; 1007 + case IIO_EV_INFO_HYSTERESIS: 1008 + ret = bmi323_read_ext_reg(data, 1009 + reg + BMI323_MO2_OFFSET, 1010 + &reg_value); 1011 + if (ret) 1012 + return ret; 1013 + 1014 + raw = FIELD_GET(BMI323_MO2_HYSTR_MSK, reg_value); 1015 + *val = raw / BMI323_MOTION_HYSTR_SCALE; 1016 + *val2 = BMI323_RAW_TO_MICRO(raw, 1017 + BMI323_MOTION_HYSTR_SCALE); 1018 + return IIO_VAL_INT_PLUS_MICRO; 1019 + default: 1020 + return -EINVAL; 1021 + } 1022 + case IIO_EV_TYPE_CHANGE: 1023 + ret = bmi323_read_ext_reg(data, BMI323_STEP_SC1_REG, 1024 + &reg_value); 1025 + if (ret) 1026 + return ret; 1027 + 1028 + raw = FIELD_GET(BMI323_STEP_SC1_WTRMRK_MSK, reg_value); 1029 + *val = raw * 20; 1030 + return IIO_VAL_INT; 1031 + default: 1032 + return -EINVAL; 1033 + } 1034 + } 1035 + 1036 + static int __bmi323_fifo_flush(struct iio_dev *indio_dev) 1037 + { 1038 + struct bmi323_data *data = iio_priv(indio_dev); 1039 + int i, ret, fifo_lvl, frame_count, bit, index; 1040 + __le16 *frame, *pchannels; 1041 + u64 sample_period; 1042 + s64 tstamp; 1043 + 1044 + guard(mutex)(&data->mutex); 1045 + ret = regmap_read(data->regmap, BMI323_FIFO_FILL_LEVEL_REG, &fifo_lvl); 1046 + if (ret) 1047 + return ret; 1048 + 1049 + fifo_lvl = min(fifo_lvl, BMI323_FIFO_FULL_IN_WORDS); 1050 + 1051 + frame_count = fifo_lvl / BMI323_FIFO_FRAME_LENGTH; 1052 + if (!frame_count) 1053 + return -EINVAL; 1054 + 1055 + if (fifo_lvl % BMI323_FIFO_FRAME_LENGTH) 1056 + dev_warn(data->dev, "Bad FIFO alignment\n"); 1057 + 1058 + /* 1059 + * Approximate timestamps for each of the sample based on the sampling 1060 + * frequency, timestamp for last sample and number of samples. 1061 + */ 1062 + if (data->old_fifo_tstamp) { 1063 + sample_period = data->fifo_tstamp - data->old_fifo_tstamp; 1064 + do_div(sample_period, frame_count); 1065 + } else { 1066 + sample_period = data->odrns[BMI323_ACCEL]; 1067 + } 1068 + 1069 + tstamp = data->fifo_tstamp - (frame_count - 1) * sample_period; 1070 + 1071 + ret = regmap_noinc_read(data->regmap, BMI323_FIFO_DATA_REG, 1072 + &data->fifo_buff[0], 1073 + fifo_lvl * BMI323_BYTES_PER_SAMPLE); 1074 + if (ret) 1075 + return ret; 1076 + 1077 + for (i = 0; i < frame_count; i++) { 1078 + frame = &data->fifo_buff[i * BMI323_FIFO_FRAME_LENGTH]; 1079 + pchannels = &data->buffer.channels[0]; 1080 + 1081 + index = 0; 1082 + for_each_set_bit(bit, indio_dev->active_scan_mask, 1083 + BMI323_CHAN_MAX) 1084 + pchannels[index++] = frame[bit]; 1085 + 1086 + iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, 1087 + tstamp); 1088 + 1089 + tstamp += sample_period; 1090 + } 1091 + 1092 + return frame_count; 1093 + } 1094 + 1095 + static int bmi323_set_watermark(struct iio_dev *indio_dev, unsigned int val) 1096 + { 1097 + struct bmi323_data *data = iio_priv(indio_dev); 1098 + 1099 + val = min(val, (u32)BMI323_FIFO_FULL_IN_FRAMES); 1100 + 1101 + guard(mutex)(&data->mutex); 1102 + data->watermark = val; 1103 + 1104 + return 0; 1105 + } 1106 + 1107 + static int bmi323_fifo_disable(struct bmi323_data *data) 1108 + { 1109 + int ret; 1110 + 1111 + guard(mutex)(&data->mutex); 1112 + ret = regmap_write(data->regmap, BMI323_FIFO_CONF_REG, 0); 1113 + if (ret) 1114 + return ret; 1115 + 1116 + ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG, 1117 + BMI323_FIFO_WTRMRK_MSK, 1118 + FIELD_PREP(BMI323_FIFO_WTRMRK_MSK, 0)); 1119 + if (ret) 1120 + return ret; 1121 + 1122 + data->fifo_tstamp = 0; 1123 + data->state = BMI323_IDLE; 1124 + 1125 + return 0; 1126 + } 1127 + 1128 + static int bmi323_buffer_predisable(struct iio_dev *indio_dev) 1129 + { 1130 + struct bmi323_data *data = iio_priv(indio_dev); 1131 + 1132 + if (iio_device_get_current_mode(indio_dev) == INDIO_BUFFER_TRIGGERED) 1133 + return 0; 1134 + 1135 + return bmi323_fifo_disable(data); 1136 + } 1137 + 1138 + static int bmi323_update_watermark(struct bmi323_data *data) 1139 + { 1140 + int wtrmrk; 1141 + 1142 + wtrmrk = data->watermark * BMI323_FIFO_FRAME_LENGTH; 1143 + 1144 + return regmap_write(data->regmap, BMI323_FIFO_WTRMRK_REG, wtrmrk); 1145 + } 1146 + 1147 + static int bmi323_fifo_enable(struct bmi323_data *data) 1148 + { 1149 + int ret; 1150 + 1151 + guard(mutex)(&data->mutex); 1152 + ret = regmap_update_bits(data->regmap, BMI323_FIFO_CONF_REG, 1153 + BMI323_FIFO_CONF_ACC_GYR_EN_MSK, 1154 + FIELD_PREP(BMI323_FIFO_CONF_ACC_GYR_EN_MSK, 1155 + BMI323_FIFO_ACC_GYR_MSK)); 1156 + if (ret) 1157 + return ret; 1158 + 1159 + ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG, 1160 + BMI323_FIFO_WTRMRK_MSK, 1161 + FIELD_PREP(BMI323_FIFO_WTRMRK_MSK, 1162 + data->irq_pin)); 1163 + if (ret) 1164 + return ret; 1165 + 1166 + ret = bmi323_update_watermark(data); 1167 + if (ret) 1168 + return ret; 1169 + 1170 + ret = regmap_write(data->regmap, BMI323_FIFO_CTRL_REG, 1171 + BMI323_FIFO_FLUSH_MSK); 1172 + if (ret) 1173 + return ret; 1174 + 1175 + data->state = BMI323_BUFFER_FIFO; 1176 + 1177 + return 0; 1178 + } 1179 + 1180 + static int bmi323_buffer_preenable(struct iio_dev *indio_dev) 1181 + { 1182 + struct bmi323_data *data = iio_priv(indio_dev); 1183 + 1184 + guard(mutex)(&data->mutex); 1185 + /* 1186 + * When the ODR of the accelerometer and gyroscope do not match, the 1187 + * maximum ODR value between the accelerometer and gyroscope is used 1188 + * for FIFO and the signal with lower ODR will insert dummy frame. 1189 + * So allow buffer read only when ODR's of accelero and gyro are equal. 1190 + * See datasheet section 5.7 "FIFO Data Buffering". 1191 + */ 1192 + if (data->odrns[BMI323_ACCEL] != data->odrns[BMI323_GYRO]) { 1193 + dev_err(data->dev, "Accelero and Gyro ODR doesn't match\n"); 1194 + return -EINVAL; 1195 + } 1196 + 1197 + return 0; 1198 + } 1199 + 1200 + static int bmi323_buffer_postenable(struct iio_dev *indio_dev) 1201 + { 1202 + struct bmi323_data *data = iio_priv(indio_dev); 1203 + 1204 + if (iio_device_get_current_mode(indio_dev) == INDIO_BUFFER_TRIGGERED) 1205 + return 0; 1206 + 1207 + return bmi323_fifo_enable(data); 1208 + } 1209 + 1210 + static ssize_t hwfifo_watermark_show(struct device *dev, 1211 + struct device_attribute *attr, char *buf) 1212 + { 1213 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 1214 + struct bmi323_data *data = iio_priv(indio_dev); 1215 + int wm; 1216 + 1217 + scoped_guard(mutex, &data->mutex) 1218 + wm = data->watermark; 1219 + 1220 + return sysfs_emit(buf, "%d\n", wm); 1221 + } 1222 + static IIO_DEVICE_ATTR_RO(hwfifo_watermark, 0); 1223 + 1224 + static ssize_t hwfifo_enabled_show(struct device *dev, 1225 + struct device_attribute *attr, 1226 + char *buf) 1227 + { 1228 + struct iio_dev *indio_dev = dev_to_iio_dev(dev); 1229 + struct bmi323_data *data = iio_priv(indio_dev); 1230 + bool state; 1231 + 1232 + scoped_guard(mutex, &data->mutex) 1233 + state = data->state == BMI323_BUFFER_FIFO; 1234 + 1235 + return sysfs_emit(buf, "%d\n", state); 1236 + } 1237 + static IIO_DEVICE_ATTR_RO(hwfifo_enabled, 0); 1238 + 1239 + static const struct iio_dev_attr *bmi323_fifo_attributes[] = { 1240 + &iio_dev_attr_hwfifo_watermark, 1241 + &iio_dev_attr_hwfifo_enabled, 1242 + NULL 1243 + }; 1244 + 1245 + static const struct iio_buffer_setup_ops bmi323_buffer_ops = { 1246 + .preenable = bmi323_buffer_preenable, 1247 + .postenable = bmi323_buffer_postenable, 1248 + .predisable = bmi323_buffer_predisable, 1249 + }; 1250 + 1251 + static irqreturn_t bmi323_irq_thread_handler(int irq, void *private) 1252 + { 1253 + struct iio_dev *indio_dev = private; 1254 + struct bmi323_data *data = iio_priv(indio_dev); 1255 + unsigned int status_addr, status, feature_event; 1256 + s64 timestamp = iio_get_time_ns(indio_dev); 1257 + int ret; 1258 + 1259 + if (data->irq_pin == BMI323_IRQ_INT1) 1260 + status_addr = BMI323_STATUS_INT1_REG; 1261 + else 1262 + status_addr = BMI323_STATUS_INT2_REG; 1263 + 1264 + scoped_guard(mutex, &data->mutex) { 1265 + ret = regmap_read(data->regmap, status_addr, &status); 1266 + if (ret) 1267 + return IRQ_NONE; 1268 + } 1269 + 1270 + if (!status || FIELD_GET(BMI323_STATUS_ERROR_MSK, status)) 1271 + return IRQ_NONE; 1272 + 1273 + if (FIELD_GET(BMI323_STATUS_FIFO_WTRMRK_MSK, status)) { 1274 + data->old_fifo_tstamp = data->fifo_tstamp; 1275 + data->fifo_tstamp = iio_get_time_ns(indio_dev); 1276 + ret = __bmi323_fifo_flush(indio_dev); 1277 + if (ret < 0) 1278 + return IRQ_NONE; 1279 + } 1280 + 1281 + if (FIELD_GET(BMI323_STATUS_ACC_GYR_DRDY_MSK, status)) 1282 + iio_trigger_poll_nested(data->trig); 1283 + 1284 + if (FIELD_GET(BMI323_STATUS_MOTION_MSK, status)) 1285 + iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, 1286 + IIO_MOD_X_OR_Y_OR_Z, 1287 + IIO_EV_TYPE_MAG, 1288 + IIO_EV_DIR_RISING), 1289 + timestamp); 1290 + 1291 + if (FIELD_GET(BMI323_STATUS_NOMOTION_MSK, status)) 1292 + iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, 1293 + IIO_MOD_X_OR_Y_OR_Z, 1294 + IIO_EV_TYPE_MAG, 1295 + IIO_EV_DIR_FALLING), 1296 + timestamp); 1297 + 1298 + if (FIELD_GET(BMI323_STATUS_STP_WTR_MSK, status)) 1299 + iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_STEPS, 0, 1300 + IIO_NO_MOD, 1301 + IIO_EV_TYPE_CHANGE, 1302 + IIO_EV_DIR_NONE), 1303 + timestamp); 1304 + 1305 + if (FIELD_GET(BMI323_STATUS_TAP_MSK, status)) { 1306 + scoped_guard(mutex, &data->mutex) { 1307 + ret = regmap_read(data->regmap, 1308 + BMI323_FEAT_EVNT_EXT_REG, 1309 + &feature_event); 1310 + if (ret) 1311 + return IRQ_NONE; 1312 + } 1313 + 1314 + if (FIELD_GET(BMI323_FEAT_EVNT_EXT_S_MSK, feature_event)) { 1315 + iio_push_event(indio_dev, 1316 + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, 1317 + IIO_MOD_X_OR_Y_OR_Z, 1318 + IIO_EV_TYPE_GESTURE, 1319 + IIO_EV_DIR_SINGLETAP), 1320 + timestamp); 1321 + } 1322 + 1323 + if (FIELD_GET(BMI323_FEAT_EVNT_EXT_D_MSK, feature_event)) 1324 + iio_push_event(indio_dev, 1325 + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, 1326 + IIO_MOD_X_OR_Y_OR_Z, 1327 + IIO_EV_TYPE_GESTURE, 1328 + IIO_EV_DIR_DOUBLETAP), 1329 + timestamp); 1330 + } 1331 + 1332 + return IRQ_HANDLED; 1333 + } 1334 + 1335 + static int bmi323_set_drdy_irq(struct bmi323_data *data, 1336 + enum bmi323_irq_pin irq_pin) 1337 + { 1338 + int ret; 1339 + 1340 + ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG, 1341 + BMI323_GYR_DRDY_MSK, 1342 + FIELD_PREP(BMI323_GYR_DRDY_MSK, irq_pin)); 1343 + if (ret) 1344 + return ret; 1345 + 1346 + return regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG, 1347 + BMI323_ACC_DRDY_MSK, 1348 + FIELD_PREP(BMI323_ACC_DRDY_MSK, irq_pin)); 1349 + } 1350 + 1351 + static int bmi323_data_rdy_trigger_set_state(struct iio_trigger *trig, 1352 + bool state) 1353 + { 1354 + struct bmi323_data *data = iio_trigger_get_drvdata(trig); 1355 + enum bmi323_irq_pin irq_pin; 1356 + 1357 + guard(mutex)(&data->mutex); 1358 + 1359 + if (data->state == BMI323_BUFFER_FIFO) { 1360 + dev_warn(data->dev, "Can't set trigger when FIFO enabled\n"); 1361 + return -EBUSY; 1362 + } 1363 + 1364 + if (state) { 1365 + data->state = BMI323_BUFFER_DRDY_TRIGGERED; 1366 + irq_pin = data->irq_pin; 1367 + } else { 1368 + data->state = BMI323_IDLE; 1369 + irq_pin = BMI323_IRQ_DISABLED; 1370 + } 1371 + 1372 + return bmi323_set_drdy_irq(data, irq_pin); 1373 + } 1374 + 1375 + static const struct iio_trigger_ops bmi323_trigger_ops = { 1376 + .set_trigger_state = &bmi323_data_rdy_trigger_set_state, 1377 + }; 1378 + 1379 + static irqreturn_t bmi323_trigger_handler(int irq, void *p) 1380 + { 1381 + struct iio_poll_func *pf = p; 1382 + struct iio_dev *indio_dev = pf->indio_dev; 1383 + struct bmi323_data *data = iio_priv(indio_dev); 1384 + int ret, bit, index = 0; 1385 + 1386 + /* Lock to protect the data->buffer */ 1387 + guard(mutex)(&data->mutex); 1388 + 1389 + if (*indio_dev->active_scan_mask == BMI323_ALL_CHAN_MSK) { 1390 + ret = regmap_bulk_read(data->regmap, BMI323_ACCEL_X_REG, 1391 + &data->buffer.channels, 1392 + ARRAY_SIZE(data->buffer.channels)); 1393 + if (ret) 1394 + return IRQ_NONE; 1395 + } else { 1396 + for_each_set_bit(bit, indio_dev->active_scan_mask, 1397 + BMI323_CHAN_MAX) { 1398 + ret = regmap_raw_read(data->regmap, 1399 + BMI323_ACCEL_X_REG + bit, 1400 + &data->buffer.channels[index++], 1401 + BMI323_BYTES_PER_SAMPLE); 1402 + if (ret) 1403 + return IRQ_NONE; 1404 + } 1405 + } 1406 + 1407 + iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, 1408 + iio_get_time_ns(indio_dev)); 1409 + 1410 + iio_trigger_notify_done(indio_dev->trig); 1411 + 1412 + return IRQ_HANDLED; 1413 + } 1414 + 1415 + static int bmi323_set_average(struct bmi323_data *data, 1416 + enum bmi323_sensor_type sensor, int avg) 1417 + { 1418 + int raw = ARRAY_SIZE(bmi323_accel_gyro_avrg); 1419 + 1420 + while (raw--) 1421 + if (avg == bmi323_accel_gyro_avrg[raw]) 1422 + break; 1423 + if (raw < 0) 1424 + return -EINVAL; 1425 + 1426 + guard(mutex)(&data->mutex); 1427 + return regmap_update_bits(data->regmap, bmi323_hw[sensor].config, 1428 + BMI323_ACC_GYRO_CONF_AVG_MSK, 1429 + FIELD_PREP(BMI323_ACC_GYRO_CONF_AVG_MSK, 1430 + raw)); 1431 + } 1432 + 1433 + static int bmi323_get_average(struct bmi323_data *data, 1434 + enum bmi323_sensor_type sensor, int *avg) 1435 + { 1436 + int ret, value, raw; 1437 + 1438 + scoped_guard(mutex, &data->mutex) { 1439 + ret = regmap_read(data->regmap, bmi323_hw[sensor].config, &value); 1440 + if (ret) 1441 + return ret; 1442 + } 1443 + 1444 + raw = FIELD_GET(BMI323_ACC_GYRO_CONF_AVG_MSK, value); 1445 + *avg = bmi323_accel_gyro_avrg[raw]; 1446 + 1447 + return IIO_VAL_INT; 1448 + } 1449 + 1450 + static int bmi323_enable_steps(struct bmi323_data *data, int val) 1451 + { 1452 + int ret; 1453 + 1454 + guard(mutex)(&data->mutex); 1455 + if (data->odrhz[BMI323_ACCEL] < 200) { 1456 + dev_err(data->dev, "Invalid accelrometer parameter\n"); 1457 + return -EINVAL; 1458 + } 1459 + 1460 + ret = bmi323_feature_engine_events(data, BMI323_FEAT_IO0_STP_CNT_MSK, 1461 + val ? 1 : 0); 1462 + if (ret) 1463 + return ret; 1464 + 1465 + set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_STP_CNT_MSK, 1466 + FIELD_PREP(BMI323_FEAT_IO0_STP_CNT_MSK, val ? 1 : 0)); 1467 + 1468 + return 0; 1469 + } 1470 + 1471 + static int bmi323_read_steps(struct bmi323_data *data, int *val) 1472 + { 1473 + int ret; 1474 + 1475 + guard(mutex)(&data->mutex); 1476 + if (!FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, data->feature_events)) 1477 + return -EINVAL; 1478 + 1479 + ret = regmap_bulk_read(data->regmap, BMI323_FEAT_IO2_REG, 1480 + data->steps_count, 1481 + ARRAY_SIZE(data->steps_count)); 1482 + if (ret) 1483 + return ret; 1484 + 1485 + *val = get_unaligned_le32(data->steps_count); 1486 + 1487 + return IIO_VAL_INT; 1488 + } 1489 + 1490 + static int bmi323_read_axis(struct bmi323_data *data, 1491 + struct iio_chan_spec const *chan, int *val) 1492 + { 1493 + enum bmi323_sensor_type sensor; 1494 + unsigned int value; 1495 + u8 addr; 1496 + int ret; 1497 + 1498 + ret = bmi323_get_error_status(data); 1499 + if (ret) 1500 + return -EINVAL; 1501 + 1502 + sensor = bmi323_iio_to_sensor(chan->type); 1503 + addr = bmi323_hw[sensor].data + (chan->channel2 - IIO_MOD_X); 1504 + 1505 + scoped_guard(mutex, &data->mutex) { 1506 + ret = regmap_read(data->regmap, addr, &value); 1507 + if (ret) 1508 + return ret; 1509 + } 1510 + 1511 + *val = sign_extend32(value, chan->scan_type.realbits - 1); 1512 + 1513 + return IIO_VAL_INT; 1514 + } 1515 + 1516 + static int bmi323_get_temp_data(struct bmi323_data *data, int *val) 1517 + { 1518 + unsigned int value; 1519 + int ret; 1520 + 1521 + ret = bmi323_get_error_status(data); 1522 + if (ret) 1523 + return -EINVAL; 1524 + 1525 + scoped_guard(mutex, &data->mutex) { 1526 + ret = regmap_read(data->regmap, BMI323_TEMP_REG, &value); 1527 + if (ret) 1528 + return ret; 1529 + } 1530 + 1531 + *val = sign_extend32(value, 15); 1532 + 1533 + return IIO_VAL_INT; 1534 + } 1535 + 1536 + static int bmi323_get_odr(struct bmi323_data *data, 1537 + enum bmi323_sensor_type sensor, int *odr, int *uodr) 1538 + { 1539 + int ret, value, odr_raw; 1540 + 1541 + scoped_guard(mutex, &data->mutex) { 1542 + ret = regmap_read(data->regmap, bmi323_hw[sensor].config, &value); 1543 + if (ret) 1544 + return ret; 1545 + } 1546 + 1547 + odr_raw = FIELD_GET(BMI323_ACC_GYRO_CONF_ODR_MSK, value); 1548 + *odr = bmi323_acc_gyro_odr[odr_raw - 1][0]; 1549 + *uodr = bmi323_acc_gyro_odr[odr_raw - 1][1]; 1550 + 1551 + return IIO_VAL_INT_PLUS_MICRO; 1552 + } 1553 + 1554 + static int bmi323_configure_power_mode(struct bmi323_data *data, 1555 + enum bmi323_sensor_type sensor, 1556 + int odr_index) 1557 + { 1558 + enum bmi323_opr_mode mode; 1559 + 1560 + if (bmi323_acc_gyro_odr[odr_index][0] > 25) 1561 + mode = ACC_GYRO_MODE_CONTINOUS; 1562 + else 1563 + mode = ACC_GYRO_MODE_DUTYCYCLE; 1564 + 1565 + return bmi323_set_mode(data, sensor, mode); 1566 + } 1567 + 1568 + static int bmi323_set_odr(struct bmi323_data *data, 1569 + enum bmi323_sensor_type sensor, int odr, int uodr) 1570 + { 1571 + int odr_raw, ret; 1572 + 1573 + odr_raw = ARRAY_SIZE(bmi323_acc_gyro_odr); 1574 + 1575 + while (odr_raw--) 1576 + if (odr == bmi323_acc_gyro_odr[odr_raw][0] && 1577 + uodr == bmi323_acc_gyro_odr[odr_raw][1]) 1578 + break; 1579 + if (odr_raw < 0) 1580 + return -EINVAL; 1581 + 1582 + ret = bmi323_configure_power_mode(data, sensor, odr_raw); 1583 + if (ret) 1584 + return -EINVAL; 1585 + 1586 + guard(mutex)(&data->mutex); 1587 + data->odrhz[sensor] = bmi323_acc_gyro_odr[odr_raw][0]; 1588 + data->odrns[sensor] = bmi323_acc_gyro_odrns[odr_raw]; 1589 + 1590 + odr_raw++; 1591 + 1592 + return regmap_update_bits(data->regmap, bmi323_hw[sensor].config, 1593 + BMI323_ACC_GYRO_CONF_ODR_MSK, 1594 + FIELD_PREP(BMI323_ACC_GYRO_CONF_ODR_MSK, 1595 + odr_raw)); 1596 + } 1597 + 1598 + static int bmi323_get_scale(struct bmi323_data *data, 1599 + enum bmi323_sensor_type sensor, int *val2) 1600 + { 1601 + int ret, value, scale_raw; 1602 + 1603 + scoped_guard(mutex, &data->mutex) { 1604 + ret = regmap_read(data->regmap, bmi323_hw[sensor].config, 1605 + &value); 1606 + if (ret) 1607 + return ret; 1608 + } 1609 + 1610 + scale_raw = FIELD_GET(BMI323_ACC_GYRO_CONF_SCL_MSK, value); 1611 + *val2 = bmi323_hw[sensor].scale_table[scale_raw][1]; 1612 + 1613 + return IIO_VAL_INT_PLUS_MICRO; 1614 + } 1615 + 1616 + static int bmi323_set_scale(struct bmi323_data *data, 1617 + enum bmi323_sensor_type sensor, int val, int val2) 1618 + { 1619 + int scale_raw; 1620 + 1621 + scale_raw = bmi323_hw[sensor].scale_table_len; 1622 + 1623 + while (scale_raw--) 1624 + if (val == bmi323_hw[sensor].scale_table[scale_raw][0] && 1625 + val2 == bmi323_hw[sensor].scale_table[scale_raw][1]) 1626 + break; 1627 + if (scale_raw < 0) 1628 + return -EINVAL; 1629 + 1630 + guard(mutex)(&data->mutex); 1631 + return regmap_update_bits(data->regmap, bmi323_hw[sensor].config, 1632 + BMI323_ACC_GYRO_CONF_SCL_MSK, 1633 + FIELD_PREP(BMI323_ACC_GYRO_CONF_SCL_MSK, 1634 + scale_raw)); 1635 + } 1636 + 1637 + static int bmi323_read_avail(struct iio_dev *indio_dev, 1638 + struct iio_chan_spec const *chan, 1639 + const int **vals, int *type, int *length, 1640 + long mask) 1641 + { 1642 + enum bmi323_sensor_type sensor; 1643 + 1644 + switch (mask) { 1645 + case IIO_CHAN_INFO_SAMP_FREQ: 1646 + *type = IIO_VAL_INT_PLUS_MICRO; 1647 + *vals = (const int *)bmi323_acc_gyro_odr; 1648 + *length = ARRAY_SIZE(bmi323_acc_gyro_odr) * 2; 1649 + return IIO_AVAIL_LIST; 1650 + case IIO_CHAN_INFO_SCALE: 1651 + sensor = bmi323_iio_to_sensor(chan->type); 1652 + *type = IIO_VAL_INT_PLUS_MICRO; 1653 + *vals = (const int *)bmi323_hw[sensor].scale_table; 1654 + *length = bmi323_hw[sensor].scale_table_len * 2; 1655 + return IIO_AVAIL_LIST; 1656 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 1657 + *type = IIO_VAL_INT; 1658 + *vals = (const int *)bmi323_accel_gyro_avrg; 1659 + *length = ARRAY_SIZE(bmi323_accel_gyro_avrg); 1660 + return IIO_AVAIL_LIST; 1661 + default: 1662 + return -EINVAL; 1663 + } 1664 + } 1665 + 1666 + static int bmi323_write_raw(struct iio_dev *indio_dev, 1667 + struct iio_chan_spec const *chan, int val, 1668 + int val2, long mask) 1669 + { 1670 + struct bmi323_data *data = iio_priv(indio_dev); 1671 + int ret; 1672 + 1673 + switch (mask) { 1674 + case IIO_CHAN_INFO_SAMP_FREQ: 1675 + ret = iio_device_claim_direct_mode(indio_dev); 1676 + if (ret) 1677 + return ret; 1678 + 1679 + ret = bmi323_set_odr(data, bmi323_iio_to_sensor(chan->type), 1680 + val, val2); 1681 + iio_device_release_direct_mode(indio_dev); 1682 + return ret; 1683 + case IIO_CHAN_INFO_SCALE: 1684 + ret = iio_device_claim_direct_mode(indio_dev); 1685 + if (ret) 1686 + return ret; 1687 + 1688 + ret = bmi323_set_scale(data, bmi323_iio_to_sensor(chan->type), 1689 + val, val2); 1690 + iio_device_release_direct_mode(indio_dev); 1691 + return ret; 1692 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 1693 + ret = iio_device_claim_direct_mode(indio_dev); 1694 + if (ret) 1695 + return ret; 1696 + 1697 + ret = bmi323_set_average(data, bmi323_iio_to_sensor(chan->type), 1698 + val); 1699 + 1700 + iio_device_release_direct_mode(indio_dev); 1701 + return ret; 1702 + case IIO_CHAN_INFO_ENABLE: 1703 + return bmi323_enable_steps(data, val); 1704 + case IIO_CHAN_INFO_PROCESSED: 1705 + scoped_guard(mutex, &data->mutex) { 1706 + if (val || !FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, 1707 + data->feature_events)) 1708 + return -EINVAL; 1709 + 1710 + /* Clear step counter value */ 1711 + ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG, 1712 + BMI323_STEP_SC1_RST_CNT_MSK, 1713 + FIELD_PREP(BMI323_STEP_SC1_RST_CNT_MSK, 1714 + 1)); 1715 + } 1716 + return ret; 1717 + default: 1718 + return -EINVAL; 1719 + } 1720 + } 1721 + 1722 + static int bmi323_read_raw(struct iio_dev *indio_dev, 1723 + struct iio_chan_spec const *chan, int *val, 1724 + int *val2, long mask) 1725 + { 1726 + struct bmi323_data *data = iio_priv(indio_dev); 1727 + int ret; 1728 + 1729 + switch (mask) { 1730 + case IIO_CHAN_INFO_PROCESSED: 1731 + return bmi323_read_steps(data, val); 1732 + case IIO_CHAN_INFO_RAW: 1733 + switch (chan->type) { 1734 + case IIO_ACCEL: 1735 + case IIO_ANGL_VEL: 1736 + ret = iio_device_claim_direct_mode(indio_dev); 1737 + if (ret) 1738 + return ret; 1739 + 1740 + ret = bmi323_read_axis(data, chan, val); 1741 + 1742 + iio_device_release_direct_mode(indio_dev); 1743 + return ret; 1744 + case IIO_TEMP: 1745 + return bmi323_get_temp_data(data, val); 1746 + default: 1747 + return -EINVAL; 1748 + } 1749 + case IIO_CHAN_INFO_SAMP_FREQ: 1750 + return bmi323_get_odr(data, bmi323_iio_to_sensor(chan->type), 1751 + val, val2); 1752 + case IIO_CHAN_INFO_SCALE: 1753 + switch (chan->type) { 1754 + case IIO_ACCEL: 1755 + case IIO_ANGL_VEL: 1756 + *val = 0; 1757 + return bmi323_get_scale(data, 1758 + bmi323_iio_to_sensor(chan->type), 1759 + val2); 1760 + case IIO_TEMP: 1761 + *val = BMI323_TEMP_SCALE / MEGA; 1762 + *val2 = BMI323_TEMP_SCALE % MEGA; 1763 + return IIO_VAL_INT_PLUS_MICRO; 1764 + default: 1765 + return -EINVAL; 1766 + } 1767 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 1768 + return bmi323_get_average(data, 1769 + bmi323_iio_to_sensor(chan->type), 1770 + val); 1771 + case IIO_CHAN_INFO_OFFSET: 1772 + switch (chan->type) { 1773 + case IIO_TEMP: 1774 + *val = BMI323_TEMP_OFFSET; 1775 + return IIO_VAL_INT; 1776 + default: 1777 + return -EINVAL; 1778 + } 1779 + case IIO_CHAN_INFO_ENABLE: 1780 + scoped_guard(mutex, &data->mutex) 1781 + *val = FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, 1782 + data->feature_events); 1783 + return IIO_VAL_INT; 1784 + default: 1785 + return -EINVAL; 1786 + } 1787 + } 1788 + 1789 + static const struct iio_info bmi323_info = { 1790 + .read_raw = bmi323_read_raw, 1791 + .write_raw = bmi323_write_raw, 1792 + .read_avail = bmi323_read_avail, 1793 + .hwfifo_set_watermark = bmi323_set_watermark, 1794 + .write_event_config = bmi323_write_event_config, 1795 + .read_event_config = bmi323_read_event_config, 1796 + .write_event_value = bmi323_write_event_value, 1797 + .read_event_value = bmi323_read_event_value, 1798 + .event_attrs = &bmi323_event_attribute_group, 1799 + }; 1800 + 1801 + #define BMI323_SCAN_MASK_ACCEL_3AXIS \ 1802 + (BIT(BMI323_ACCEL_X) | BIT(BMI323_ACCEL_Y) | BIT(BMI323_ACCEL_Z)) 1803 + 1804 + #define BMI323_SCAN_MASK_GYRO_3AXIS \ 1805 + (BIT(BMI323_GYRO_X) | BIT(BMI323_GYRO_Y) | BIT(BMI323_GYRO_Z)) 1806 + 1807 + static const unsigned long bmi323_avail_scan_masks[] = { 1808 + /* 3-axis accel */ 1809 + BMI323_SCAN_MASK_ACCEL_3AXIS, 1810 + /* 3-axis gyro */ 1811 + BMI323_SCAN_MASK_GYRO_3AXIS, 1812 + /* 3-axis accel + 3-axis gyro */ 1813 + BMI323_SCAN_MASK_ACCEL_3AXIS | BMI323_SCAN_MASK_GYRO_3AXIS, 1814 + 0 1815 + }; 1816 + 1817 + static int bmi323_int_pin_config(struct bmi323_data *data, 1818 + enum bmi323_irq_pin irq_pin, 1819 + bool active_high, bool open_drain, bool latch) 1820 + { 1821 + unsigned int mask, field_value; 1822 + int ret; 1823 + 1824 + ret = regmap_update_bits(data->regmap, BMI323_IO_INT_CONF_REG, 1825 + BMI323_IO_INT_LTCH_MSK, 1826 + FIELD_PREP(BMI323_IO_INT_LTCH_MSK, latch)); 1827 + if (ret) 1828 + return ret; 1829 + 1830 + ret = bmi323_update_ext_reg(data, BMI323_GEN_SET1_REG, 1831 + BMI323_GEN_HOLD_DUR_MSK, 1832 + FIELD_PREP(BMI323_GEN_HOLD_DUR_MSK, 0)); 1833 + if (ret) 1834 + return ret; 1835 + 1836 + switch (irq_pin) { 1837 + case BMI323_IRQ_INT1: 1838 + mask = BMI323_IO_INT1_LVL_OD_OP_MSK; 1839 + 1840 + field_value = FIELD_PREP(BMI323_IO_INT1_LVL_MSK, active_high) | 1841 + FIELD_PREP(BMI323_IO_INT1_OD_MSK, open_drain) | 1842 + FIELD_PREP(BMI323_IO_INT1_OP_EN_MSK, 1); 1843 + break; 1844 + case BMI323_IRQ_INT2: 1845 + mask = BMI323_IO_INT2_LVL_OD_OP_MSK; 1846 + 1847 + field_value = FIELD_PREP(BMI323_IO_INT2_LVL_MSK, active_high) | 1848 + FIELD_PREP(BMI323_IO_INT2_OD_MSK, open_drain) | 1849 + FIELD_PREP(BMI323_IO_INT2_OP_EN_MSK, 1); 1850 + break; 1851 + default: 1852 + return -EINVAL; 1853 + } 1854 + 1855 + return regmap_update_bits(data->regmap, BMI323_IO_INT_CTR_REG, mask, 1856 + field_value); 1857 + } 1858 + 1859 + static int bmi323_trigger_probe(struct bmi323_data *data, 1860 + struct iio_dev *indio_dev) 1861 + { 1862 + bool open_drain, active_high, latch; 1863 + struct fwnode_handle *fwnode; 1864 + enum bmi323_irq_pin irq_pin; 1865 + int ret, irq, irq_type; 1866 + struct irq_data *desc; 1867 + 1868 + fwnode = dev_fwnode(data->dev); 1869 + if (!fwnode) 1870 + return -ENODEV; 1871 + 1872 + irq = fwnode_irq_get_byname(fwnode, "INT1"); 1873 + if (irq > 0) { 1874 + irq_pin = BMI323_IRQ_INT1; 1875 + } else { 1876 + irq = fwnode_irq_get_byname(fwnode, "INT2"); 1877 + if (irq < 0) 1878 + return 0; 1879 + 1880 + irq_pin = BMI323_IRQ_INT2; 1881 + } 1882 + 1883 + desc = irq_get_irq_data(irq); 1884 + if (!desc) 1885 + return dev_err_probe(data->dev, -EINVAL, 1886 + "Could not find IRQ %d\n", irq); 1887 + 1888 + irq_type = irqd_get_trigger_type(desc); 1889 + switch (irq_type) { 1890 + case IRQF_TRIGGER_RISING: 1891 + latch = false; 1892 + active_high = true; 1893 + break; 1894 + case IRQF_TRIGGER_HIGH: 1895 + latch = true; 1896 + active_high = true; 1897 + break; 1898 + case IRQF_TRIGGER_FALLING: 1899 + latch = false; 1900 + active_high = false; 1901 + break; 1902 + case IRQF_TRIGGER_LOW: 1903 + latch = true; 1904 + active_high = false; 1905 + break; 1906 + default: 1907 + return dev_err_probe(data->dev, -EINVAL, 1908 + "Invalid interrupt type 0x%x specified\n", 1909 + irq_type); 1910 + } 1911 + 1912 + open_drain = fwnode_property_read_bool(fwnode, "drive-open-drain"); 1913 + 1914 + ret = bmi323_int_pin_config(data, irq_pin, active_high, open_drain, 1915 + latch); 1916 + if (ret) 1917 + return dev_err_probe(data->dev, ret, 1918 + "Failed to configure irq line\n"); 1919 + 1920 + data->trig = devm_iio_trigger_alloc(data->dev, "%s-trig-%d", 1921 + indio_dev->name, irq_pin); 1922 + if (!data->trig) 1923 + return -ENOMEM; 1924 + 1925 + data->trig->ops = &bmi323_trigger_ops; 1926 + iio_trigger_set_drvdata(data->trig, data); 1927 + 1928 + ret = devm_request_threaded_irq(data->dev, irq, NULL, 1929 + bmi323_irq_thread_handler, 1930 + IRQF_ONESHOT, "bmi323-int", indio_dev); 1931 + if (ret) 1932 + return dev_err_probe(data->dev, ret, "Failed to request IRQ\n"); 1933 + 1934 + ret = devm_iio_trigger_register(data->dev, data->trig); 1935 + if (ret) 1936 + return dev_err_probe(data->dev, ret, 1937 + "Trigger registration failed\n"); 1938 + 1939 + data->irq_pin = irq_pin; 1940 + 1941 + return 0; 1942 + } 1943 + 1944 + static int bmi323_feature_engine_enable(struct bmi323_data *data, bool en) 1945 + { 1946 + unsigned int feature_status; 1947 + int ret; 1948 + 1949 + if (!en) 1950 + return regmap_write(data->regmap, BMI323_FEAT_CTRL_REG, 0); 1951 + 1952 + ret = regmap_write(data->regmap, BMI323_FEAT_IO2_REG, 0x012c); 1953 + if (ret) 1954 + return ret; 1955 + 1956 + ret = regmap_write(data->regmap, BMI323_FEAT_IO_STATUS_REG, 1957 + BMI323_FEAT_IO_STATUS_MSK); 1958 + if (ret) 1959 + return ret; 1960 + 1961 + ret = regmap_write(data->regmap, BMI323_FEAT_CTRL_REG, 1962 + BMI323_FEAT_ENG_EN_MSK); 1963 + if (ret) 1964 + return ret; 1965 + 1966 + /* 1967 + * It takes around 4 msec to enable the Feature engine, so check 1968 + * the status of the feature engine every 2 msec for a maximum 1969 + * of 5 trials. 1970 + */ 1971 + ret = regmap_read_poll_timeout(data->regmap, BMI323_FEAT_IO1_REG, 1972 + feature_status, 1973 + FIELD_GET(BMI323_FEAT_IO1_ERR_MSK, 1974 + feature_status) == 1, 1975 + BMI323_FEAT_ENG_POLL, 1976 + BMI323_FEAT_ENG_TIMEOUT); 1977 + if (ret) 1978 + return dev_err_probe(data->dev, -EINVAL, 1979 + "Failed to enable feature engine\n"); 1980 + 1981 + return 0; 1982 + } 1983 + 1984 + static void bmi323_disable(void *data_ptr) 1985 + { 1986 + struct bmi323_data *data = data_ptr; 1987 + 1988 + bmi323_set_mode(data, BMI323_ACCEL, ACC_GYRO_MODE_DISABLE); 1989 + bmi323_set_mode(data, BMI323_GYRO, ACC_GYRO_MODE_DISABLE); 1990 + } 1991 + 1992 + static int bmi323_set_bw(struct bmi323_data *data, 1993 + enum bmi323_sensor_type sensor, enum bmi323_3db_bw bw) 1994 + { 1995 + return regmap_update_bits(data->regmap, bmi323_hw[sensor].config, 1996 + BMI323_ACC_GYRO_CONF_BW_MSK, 1997 + FIELD_PREP(BMI323_ACC_GYRO_CONF_BW_MSK, bw)); 1998 + } 1999 + 2000 + static int bmi323_init(struct bmi323_data *data) 2001 + { 2002 + int ret, val; 2003 + 2004 + /* 2005 + * Perform soft reset to make sure the device is in a known state after 2006 + * start up. A delay of 1.5 ms is required after reset. 2007 + * See datasheet section 5.17 "Soft Reset". 2008 + */ 2009 + ret = regmap_write(data->regmap, BMI323_CMD_REG, BMI323_RST_VAL); 2010 + if (ret) 2011 + return ret; 2012 + 2013 + usleep_range(1500, 2000); 2014 + 2015 + /* 2016 + * Dummy read is required to enable SPI interface after reset. 2017 + * See datasheet section 7.2.1 "Protocol Selection". 2018 + */ 2019 + regmap_read(data->regmap, BMI323_CHIP_ID_REG, &val); 2020 + 2021 + ret = regmap_read(data->regmap, BMI323_STATUS_REG, &val); 2022 + if (ret) 2023 + return ret; 2024 + 2025 + if (!FIELD_GET(BMI323_STATUS_POR_MSK, val)) 2026 + return dev_err_probe(data->dev, -EINVAL, 2027 + "Sensor initialization error\n"); 2028 + 2029 + ret = regmap_read(data->regmap, BMI323_CHIP_ID_REG, &val); 2030 + if (ret) 2031 + return ret; 2032 + 2033 + if (FIELD_GET(BMI323_CHIP_ID_MSK, val) != BMI323_CHIP_ID_VAL) 2034 + return dev_err_probe(data->dev, -EINVAL, "Chip ID mismatch\n"); 2035 + 2036 + ret = bmi323_feature_engine_enable(data, true); 2037 + if (ret) 2038 + return ret; 2039 + 2040 + ret = regmap_read(data->regmap, BMI323_ERR_REG, &val); 2041 + if (ret) 2042 + return ret; 2043 + 2044 + if (val) 2045 + return dev_err_probe(data->dev, -EINVAL, 2046 + "Sensor power error = 0x%x\n", val); 2047 + 2048 + /* 2049 + * Set the Bandwidth coefficient which defines the 3 dB cutoff 2050 + * frequency in relation to the ODR. 2051 + */ 2052 + ret = bmi323_set_bw(data, BMI323_ACCEL, BMI323_BW_ODR_BY_2); 2053 + if (ret) 2054 + return ret; 2055 + 2056 + ret = bmi323_set_bw(data, BMI323_GYRO, BMI323_BW_ODR_BY_2); 2057 + if (ret) 2058 + return ret; 2059 + 2060 + ret = bmi323_set_odr(data, BMI323_ACCEL, 25, 0); 2061 + if (ret) 2062 + return ret; 2063 + 2064 + ret = bmi323_set_odr(data, BMI323_GYRO, 25, 0); 2065 + if (ret) 2066 + return ret; 2067 + 2068 + return devm_add_action_or_reset(data->dev, bmi323_disable, data); 2069 + } 2070 + 2071 + int bmi323_core_probe(struct device *dev) 2072 + { 2073 + static const char * const regulator_names[] = { "vdd", "vddio" }; 2074 + struct iio_dev *indio_dev; 2075 + struct bmi323_data *data; 2076 + struct regmap *regmap; 2077 + int ret; 2078 + 2079 + regmap = dev_get_regmap(dev, NULL); 2080 + if (!regmap) 2081 + return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n"); 2082 + 2083 + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 2084 + if (!indio_dev) 2085 + return dev_err_probe(dev, -ENOMEM, 2086 + "Failed to allocate device\n"); 2087 + 2088 + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names), 2089 + regulator_names); 2090 + if (ret) 2091 + return dev_err_probe(dev, ret, "Failed to enable regulators\n"); 2092 + 2093 + data = iio_priv(indio_dev); 2094 + data->dev = dev; 2095 + data->regmap = regmap; 2096 + mutex_init(&data->mutex); 2097 + 2098 + ret = bmi323_init(data); 2099 + if (ret) 2100 + return -EINVAL; 2101 + 2102 + ret = iio_read_mount_matrix(dev, &data->orientation); 2103 + if (ret) 2104 + return ret; 2105 + 2106 + indio_dev->name = "bmi323-imu"; 2107 + indio_dev->info = &bmi323_info; 2108 + indio_dev->channels = bmi323_channels; 2109 + indio_dev->num_channels = ARRAY_SIZE(bmi323_channels); 2110 + indio_dev->available_scan_masks = bmi323_avail_scan_masks; 2111 + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; 2112 + dev_set_drvdata(data->dev, indio_dev); 2113 + 2114 + ret = bmi323_trigger_probe(data, indio_dev); 2115 + if (ret) 2116 + return -EINVAL; 2117 + 2118 + ret = devm_iio_triggered_buffer_setup_ext(data->dev, indio_dev, 2119 + &iio_pollfunc_store_time, 2120 + bmi323_trigger_handler, 2121 + IIO_BUFFER_DIRECTION_IN, 2122 + &bmi323_buffer_ops, 2123 + bmi323_fifo_attributes); 2124 + if (ret) 2125 + return dev_err_probe(data->dev, ret, 2126 + "Failed to setup trigger buffer\n"); 2127 + 2128 + ret = devm_iio_device_register(data->dev, indio_dev); 2129 + if (ret) 2130 + return dev_err_probe(data->dev, ret, 2131 + "Unable to register iio device\n"); 2132 + 2133 + return 0; 2134 + } 2135 + EXPORT_SYMBOL_NS_GPL(bmi323_core_probe, IIO_BMI323); 2136 + 2137 + MODULE_DESCRIPTION("Bosch BMI323 IMU driver"); 2138 + MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>"); 2139 + MODULE_LICENSE("GPL");
+121
drivers/iio/imu/bmi323/bmi323_i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * I2C driver for Bosch BMI323 6-Axis IMU. 4 + * 5 + * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com> 6 + */ 7 + 8 + #include <linux/i2c.h> 9 + #include <linux/mod_devicetable.h> 10 + #include <linux/module.h> 11 + #include <linux/regmap.h> 12 + 13 + #include "bmi323.h" 14 + 15 + struct bmi323_i2c_priv { 16 + struct i2c_client *i2c; 17 + u8 i2c_rx_buffer[BMI323_FIFO_LENGTH_IN_BYTES + BMI323_I2C_DUMMY]; 18 + }; 19 + 20 + /* 21 + * From BMI323 datasheet section 4: Notes on the Serial Interface Support. 22 + * Each I2C register read operation requires to read two dummy bytes before 23 + * the actual payload. 24 + */ 25 + static int bmi323_regmap_i2c_read(void *context, const void *reg_buf, 26 + size_t reg_size, void *val_buf, 27 + size_t val_size) 28 + { 29 + struct bmi323_i2c_priv *priv = context; 30 + struct i2c_msg msgs[2]; 31 + int ret; 32 + 33 + msgs[0].addr = priv->i2c->addr; 34 + msgs[0].flags = priv->i2c->flags; 35 + msgs[0].len = reg_size; 36 + msgs[0].buf = (u8 *)reg_buf; 37 + 38 + msgs[1].addr = priv->i2c->addr; 39 + msgs[1].len = val_size + BMI323_I2C_DUMMY; 40 + msgs[1].buf = priv->i2c_rx_buffer; 41 + msgs[1].flags = priv->i2c->flags | I2C_M_RD; 42 + 43 + ret = i2c_transfer(priv->i2c->adapter, msgs, ARRAY_SIZE(msgs)); 44 + if (ret < 0) 45 + return -EIO; 46 + 47 + memcpy(val_buf, priv->i2c_rx_buffer + BMI323_I2C_DUMMY, val_size); 48 + 49 + return 0; 50 + } 51 + 52 + static int bmi323_regmap_i2c_write(void *context, const void *data, 53 + size_t count) 54 + { 55 + struct bmi323_i2c_priv *priv = context; 56 + u8 reg; 57 + 58 + reg = *(u8 *)data; 59 + return i2c_smbus_write_i2c_block_data(priv->i2c, reg, 60 + count - sizeof(u8), 61 + data + sizeof(u8)); 62 + } 63 + 64 + static struct regmap_bus bmi323_regmap_bus = { 65 + .read = bmi323_regmap_i2c_read, 66 + .write = bmi323_regmap_i2c_write, 67 + }; 68 + 69 + const struct regmap_config bmi323_i2c_regmap_config = { 70 + .reg_bits = 8, 71 + .val_bits = 16, 72 + .max_register = BMI323_CFG_RES_REG, 73 + .val_format_endian = REGMAP_ENDIAN_LITTLE, 74 + }; 75 + 76 + static int bmi323_i2c_probe(struct i2c_client *i2c) 77 + { 78 + struct device *dev = &i2c->dev; 79 + struct bmi323_i2c_priv *priv; 80 + struct regmap *regmap; 81 + 82 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 83 + if (!priv) 84 + return -ENOMEM; 85 + 86 + priv->i2c = i2c; 87 + regmap = devm_regmap_init(dev, &bmi323_regmap_bus, priv, 88 + &bmi323_i2c_regmap_config); 89 + if (IS_ERR(regmap)) 90 + return dev_err_probe(dev, PTR_ERR(regmap), 91 + "Failed to initialize I2C Regmap\n"); 92 + 93 + return bmi323_core_probe(dev); 94 + } 95 + 96 + static const struct i2c_device_id bmi323_i2c_ids[] = { 97 + { "bmi323" }, 98 + { } 99 + }; 100 + MODULE_DEVICE_TABLE(i2c, bmi323_i2c_ids); 101 + 102 + static const struct of_device_id bmi323_of_i2c_match[] = { 103 + { .compatible = "bosch,bmi323" }, 104 + { } 105 + }; 106 + MODULE_DEVICE_TABLE(of, bmi323_of_i2c_match); 107 + 108 + static struct i2c_driver bmi323_i2c_driver = { 109 + .driver = { 110 + .name = "bmi323", 111 + .of_match_table = bmi323_of_i2c_match, 112 + }, 113 + .probe = bmi323_i2c_probe, 114 + .id_table = bmi323_i2c_ids, 115 + }; 116 + module_i2c_driver(bmi323_i2c_driver); 117 + 118 + MODULE_DESCRIPTION("Bosch BMI323 IMU driver"); 119 + MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>"); 120 + MODULE_LICENSE("GPL"); 121 + MODULE_IMPORT_NS(IIO_BMI323);
+92
drivers/iio/imu/bmi323/bmi323_spi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * SPI driver for Bosch BMI323 6-Axis IMU. 4 + * 5 + * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com> 6 + */ 7 + 8 + #include <linux/mod_devicetable.h> 9 + #include <linux/module.h> 10 + #include <linux/regmap.h> 11 + #include <linux/spi/spi.h> 12 + 13 + #include "bmi323.h" 14 + 15 + /* 16 + * From BMI323 datasheet section 4: Notes on the Serial Interface Support. 17 + * Each SPI register read operation requires to read one dummy byte before 18 + * the actual payload. 19 + */ 20 + static int bmi323_regmap_spi_read(void *context, const void *reg_buf, 21 + size_t reg_size, void *val_buf, 22 + size_t val_size) 23 + { 24 + struct spi_device *spi = context; 25 + 26 + return spi_write_then_read(spi, reg_buf, reg_size, val_buf, val_size); 27 + } 28 + 29 + static int bmi323_regmap_spi_write(void *context, const void *data, 30 + size_t count) 31 + { 32 + struct spi_device *spi = context; 33 + u8 *data_buff = (u8 *)data; 34 + 35 + data_buff[1] = data_buff[0]; 36 + return spi_write(spi, data_buff + 1, count - 1); 37 + } 38 + 39 + static struct regmap_bus bmi323_regmap_bus = { 40 + .read = bmi323_regmap_spi_read, 41 + .write = bmi323_regmap_spi_write, 42 + }; 43 + 44 + const struct regmap_config bmi323_spi_regmap_config = { 45 + .reg_bits = 8, 46 + .val_bits = 16, 47 + .pad_bits = 8, 48 + .read_flag_mask = BIT(7), 49 + .max_register = BMI323_CFG_RES_REG, 50 + .val_format_endian = REGMAP_ENDIAN_LITTLE, 51 + }; 52 + 53 + static int bmi323_spi_probe(struct spi_device *spi) 54 + { 55 + struct device *dev = &spi->dev; 56 + struct regmap *regmap; 57 + 58 + regmap = devm_regmap_init(dev, &bmi323_regmap_bus, dev, 59 + &bmi323_spi_regmap_config); 60 + if (IS_ERR(regmap)) 61 + return dev_err_probe(dev, PTR_ERR(regmap), 62 + "Failed to initialize SPI Regmap\n"); 63 + 64 + return bmi323_core_probe(dev); 65 + } 66 + 67 + static const struct spi_device_id bmi323_spi_ids[] = { 68 + { "bmi323" }, 69 + { } 70 + }; 71 + MODULE_DEVICE_TABLE(spi, bmi323_spi_ids); 72 + 73 + static const struct of_device_id bmi323_of_spi_match[] = { 74 + { .compatible = "bosch,bmi323" }, 75 + { } 76 + }; 77 + MODULE_DEVICE_TABLE(of, bmi323_of_spi_match); 78 + 79 + static struct spi_driver bmi323_spi_driver = { 80 + .driver = { 81 + .name = "bmi323", 82 + .of_match_table = bmi323_of_spi_match, 83 + }, 84 + .probe = bmi323_spi_probe, 85 + .id_table = bmi323_spi_ids, 86 + }; 87 + module_spi_driver(bmi323_spi_driver); 88 + 89 + MODULE_DESCRIPTION("Bosch BMI323 IMU driver"); 90 + MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>"); 91 + MODULE_LICENSE("GPL"); 92 + MODULE_IMPORT_NS(IIO_BMI323);