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: smi330: Add driver

Add the iio driver for bosch imu smi330. The smi330 is a combined
three axis angular rate and three axis acceleration sensor.

Signed-off-by: Jianping Shen <Jianping.Shen@de.bosch.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Jianping Shen and committed by
Jonathan Cameron
6f3d8de8 1c9986e7

+1203
+1
drivers/iio/imu/Kconfig
··· 125 125 This driver can also be built as a module. If so, the module will be 126 126 called smi240. 127 127 128 + source "drivers/iio/imu/smi330/Kconfig" 128 129 source "drivers/iio/imu/st_lsm6dsx/Kconfig" 129 130 source "drivers/iio/imu/st_lsm9ds0/Kconfig" 130 131
+1
drivers/iio/imu/Makefile
··· 32 32 33 33 obj-$(CONFIG_SMI240) += smi240.o 34 34 35 + obj-y += smi330/ 35 36 obj-y += st_lsm6dsx/ 36 37 obj-y += st_lsm9ds0/
+33
drivers/iio/imu/smi330/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # SMI330 IMU driver 4 + # 5 + 6 + config SMI330 7 + tristate 8 + select IIO_BUFFER 9 + select IIO_TRIGGERED_BUFFER 10 + 11 + config SMI330_I2C 12 + tristate "Bosch SMI330 I2C driver" 13 + depends on I2C 14 + select SMI330 15 + select REGMAP_I2C 16 + help 17 + Enable support for the Bosch SMI330 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 smi330_i2c. 22 + 23 + config SMI330_SPI 24 + tristate "Bosch SMI330 SPI driver" 25 + depends on SPI 26 + select SMI330 27 + select REGMAP_SPI 28 + help 29 + Enable support for the Bosch SMI330 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 smi330_spi.
+7
drivers/iio/imu/smi330/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # 3 + # Makefile for Bosch SMI330 IMU 4 + # 5 + obj-$(CONFIG_SMI330) += smi330_core.o 6 + obj-$(CONFIG_SMI330_I2C) += smi330_i2c.o 7 + obj-$(CONFIG_SMI330_SPI) += smi330_spi.o
+25
drivers/iio/imu/smi330/smi330.h
··· 1 + /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */ 2 + /* 3 + * Copyright (c) 2025 Robert Bosch GmbH. 4 + */ 5 + #ifndef _SMI330_H 6 + #define _SMI330_H 7 + 8 + #include <linux/iio/iio.h> 9 + 10 + enum { 11 + SMI330_SCAN_ACCEL_X, 12 + SMI330_SCAN_ACCEL_Y, 13 + SMI330_SCAN_ACCEL_Z, 14 + SMI330_SCAN_GYRO_X, 15 + SMI330_SCAN_GYRO_Y, 16 + SMI330_SCAN_GYRO_Z, 17 + SMI330_SCAN_TIMESTAMP, 18 + SMI330_SCAN_LEN = SMI330_SCAN_TIMESTAMP, 19 + }; 20 + 21 + extern const struct regmap_config smi330_regmap_config; 22 + 23 + int smi330_core_probe(struct device *dev, struct regmap *regmap); 24 + 25 + #endif /* _SMI330_H */
+918
drivers/iio/imu/smi330/smi330_core.c
··· 1 + // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 + /* 3 + * Copyright (c) 2025 Robert Bosch GmbH. 4 + */ 5 + #include <linux/bitfield.h> 6 + #include <linux/delay.h> 7 + #include <linux/interrupt.h> 8 + #include <linux/irq.h> 9 + #include <linux/module.h> 10 + #include <linux/property.h> 11 + #include <linux/regmap.h> 12 + #include <linux/string.h> 13 + #include <linux/units.h> 14 + 15 + #include <linux/iio/buffer.h> 16 + #include <linux/iio/iio.h> 17 + #include <linux/iio/trigger.h> 18 + #include <linux/iio/trigger_consumer.h> 19 + #include <linux/iio/triggered_buffer.h> 20 + 21 + #include "smi330.h" 22 + 23 + /* Register map */ 24 + #define SMI330_CHIP_ID_REG 0x00 25 + #define SMI330_ERR_REG 0x01 26 + #define SMI330_STATUS_REG 0x02 27 + #define SMI330_ACCEL_X_REG 0x03 28 + #define SMI330_GYRO_X_REG 0x06 29 + #define SMI330_TEMP_REG 0x09 30 + #define SMI330_INT1_STATUS_REG 0x0D 31 + #define SMI330_ACCEL_CFG_REG 0x20 32 + #define SMI330_GYRO_CFG_REG 0x21 33 + #define SMI330_IO_INT_CTRL_REG 0x38 34 + #define SMI330_INT_CONF_REG 0x39 35 + #define SMI330_INT_MAP1_REG 0x3A 36 + #define SMI330_INT_MAP2_REG 0x3B 37 + #define SMI330_CMD_REG 0x7E 38 + 39 + /* Register mask */ 40 + #define SMI330_CHIP_ID_MASK GENMASK(7, 0) 41 + #define SMI330_ERR_FATAL_MASK BIT(0) 42 + #define SMI330_ERR_ACC_CONF_MASK BIT(5) 43 + #define SMI330_ERR_GYR_CONF_MASK BIT(6) 44 + #define SMI330_STATUS_POR_MASK BIT(0) 45 + #define SMI330_INT_STATUS_ACC_GYR_DRDY_MASK GENMASK(13, 12) 46 + #define SMI330_CFG_ODR_MASK GENMASK(3, 0) 47 + #define SMI330_CFG_RANGE_MASK GENMASK(6, 4) 48 + #define SMI330_CFG_BW_MASK BIT(7) 49 + #define SMI330_CFG_AVG_NUM_MASK GENMASK(10, 8) 50 + #define SMI330_CFG_MODE_MASK GENMASK(14, 12) 51 + #define SMI330_IO_INT_CTRL_INT1_MASK GENMASK(2, 0) 52 + #define SMI330_IO_INT_CTRL_INT2_MASK GENMASK(10, 8) 53 + #define SMI330_INT_CONF_LATCH_MASK BIT(0) 54 + #define SMI330_INT_MAP2_ACC_DRDY_MASK GENMASK(11, 10) 55 + #define SMI330_INT_MAP2_GYR_DRDY_MASK GENMASK(9, 8) 56 + 57 + /* Register values */ 58 + #define SMI330_IO_INT_CTRL_LVL BIT(0) 59 + #define SMI330_IO_INT_CTRL_OD BIT(1) 60 + #define SMI330_IO_INT_CTRL_EN BIT(2) 61 + #define SMI330_CMD_SOFT_RESET 0xDEAF 62 + 63 + /* T°C = (temp / 512) + 23 */ 64 + #define SMI330_TEMP_OFFSET 11776 /* 23 * 512 */ 65 + #define SMI330_TEMP_SCALE 1953125 /* (1 / 512) * 1e9 */ 66 + 67 + #define SMI330_CHIP_ID 0x42 68 + #define SMI330_SOFT_RESET_DELAY 2000 69 + 70 + /* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */ 71 + #define smi330_field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1)) 72 + #define smi330_field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask)) 73 + 74 + #define SMI330_ACCEL_CHANNEL(_axis) { \ 75 + .type = IIO_ACCEL, \ 76 + .modified = 1, \ 77 + .channel2 = IIO_MOD_##_axis, \ 78 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 79 + .info_mask_shared_by_type = \ 80 + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 81 + BIT(IIO_CHAN_INFO_SCALE) | \ 82 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | \ 83 + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 84 + .info_mask_shared_by_type_available = \ 85 + BIT(IIO_CHAN_INFO_SCALE) | \ 86 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | \ 87 + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 88 + .info_mask_shared_by_dir_available = \ 89 + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 90 + .scan_index = SMI330_SCAN_ACCEL_##_axis, \ 91 + .scan_type = { \ 92 + .sign = 's', \ 93 + .realbits = 16, \ 94 + .storagebits = 16, \ 95 + .endianness = IIO_LE, \ 96 + }, \ 97 + } 98 + 99 + #define SMI330_GYRO_CHANNEL(_axis) { \ 100 + .type = IIO_ANGL_VEL, \ 101 + .modified = 1, \ 102 + .channel2 = IIO_MOD_##_axis, \ 103 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 104 + .info_mask_shared_by_type = \ 105 + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 106 + BIT(IIO_CHAN_INFO_SCALE) | \ 107 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | \ 108 + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 109 + .info_mask_shared_by_type_available = \ 110 + BIT(IIO_CHAN_INFO_SCALE) | \ 111 + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | \ 112 + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 113 + .info_mask_shared_by_dir_available = \ 114 + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 115 + .scan_index = SMI330_SCAN_GYRO_##_axis, \ 116 + .scan_type = { \ 117 + .sign = 's', \ 118 + .realbits = 16, \ 119 + .storagebits = 16, \ 120 + .endianness = IIO_LE, \ 121 + }, \ 122 + } 123 + 124 + #define SMI330_TEMP_CHANNEL(_index) { \ 125 + .type = IIO_TEMP, \ 126 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 127 + BIT(IIO_CHAN_INFO_OFFSET) | \ 128 + BIT(IIO_CHAN_INFO_SCALE), \ 129 + .scan_index = _index, \ 130 + .scan_type = { \ 131 + .sign = 's', \ 132 + .realbits = 16, \ 133 + .storagebits = 16, \ 134 + .endianness = IIO_LE, \ 135 + }, \ 136 + } 137 + 138 + enum smi330_accel_range { 139 + SMI330_ACCEL_RANGE_2G = 0x00, 140 + SMI330_ACCEL_RANGE_4G = 0x01, 141 + SMI330_ACCEL_RANGE_8G = 0x02, 142 + SMI330_ACCEL_RANGE_16G = 0x03 143 + }; 144 + 145 + enum smi330_gyro_range { 146 + SMI330_GYRO_RANGE_125 = 0x0, 147 + SMI330_GYRO_RANGE_250 = 0x01, 148 + SMI330_GYRO_RANGE_500 = 0x02 149 + }; 150 + 151 + enum smi330_odr { 152 + SMI330_ODR_12_5_HZ = 0x05, 153 + SMI330_ODR_25_HZ = 0x06, 154 + SMI330_ODR_50_HZ = 0x07, 155 + SMI330_ODR_100_HZ = 0x08, 156 + SMI330_ODR_200_HZ = 0x09, 157 + SMI330_ODR_400_HZ = 0x0A, 158 + SMI330_ODR_800_HZ = 0x0B, 159 + SMI330_ODR_1600_HZ = 0x0C, 160 + SMI330_ODR_3200_HZ = 0x0D, 161 + SMI330_ODR_6400_HZ = 0x0E 162 + }; 163 + 164 + enum smi330_avg_num { 165 + SMI330_AVG_NUM_1 = 0x00, 166 + SMI330_AVG_NUM_2 = 0x01, 167 + SMI330_AVG_NUM_4 = 0x02, 168 + SMI330_AVG_NUM_8 = 0x03, 169 + SMI330_AVG_NUM_16 = 0x04, 170 + SMI330_AVG_NUM_32 = 0x05, 171 + SMI330_AVG_NUM_64 = 0x06 172 + }; 173 + 174 + enum smi330_mode { 175 + SMI330_MODE_SUSPEND = 0x00, 176 + SMI330_MODE_GYRO_DRIVE = 0x01, 177 + SMI330_MODE_LOW_POWER = 0x03, 178 + SMI330_MODE_NORMAL = 0x04, 179 + SMI330_MODE_HIGH_PERF = 0x07 180 + }; 181 + 182 + enum smi330_bw { 183 + SMI330_BW_2 = 0x00, /* ODR/2 */ 184 + SMI330_BW_4 = 0x01 /* ODR/4 */ 185 + }; 186 + 187 + enum smi330_operation_mode { 188 + SMI330_POLLING, 189 + SMI330_DATA_READY, 190 + }; 191 + 192 + enum smi330_sensor { 193 + SMI330_ACCEL, 194 + SMI330_GYRO, 195 + }; 196 + 197 + enum smi330_sensor_conf_select { 198 + SMI330_ODR, 199 + SMI330_RANGE, 200 + SMI330_BW, 201 + SMI330_AVG_NUM, 202 + }; 203 + 204 + enum smi330_int_out { 205 + SMI330_INT_DISABLED, 206 + SMI330_INT_1, 207 + SMI330_INT_2, 208 + }; 209 + 210 + struct smi330_attributes { 211 + int *reg_vals; 212 + int *vals; 213 + int len; 214 + int type; 215 + int mask; 216 + }; 217 + 218 + struct smi330_cfg { 219 + enum smi330_operation_mode op_mode; 220 + enum smi330_int_out data_irq; 221 + }; 222 + 223 + struct smi330_data { 224 + struct regmap *regmap; 225 + struct smi330_cfg cfg; 226 + struct iio_trigger *trig; 227 + IIO_DECLARE_BUFFER_WITH_TS(__le16, buf, SMI330_SCAN_LEN); 228 + }; 229 + 230 + const struct regmap_config smi330_regmap_config = { 231 + .reg_bits = 8, 232 + .val_bits = 16, 233 + .val_format_endian = REGMAP_ENDIAN_LITTLE, 234 + }; 235 + EXPORT_SYMBOL_NS_GPL(smi330_regmap_config, "IIO_SMI330"); 236 + 237 + static const struct iio_chan_spec smi330_channels[] = { 238 + SMI330_ACCEL_CHANNEL(X), 239 + SMI330_ACCEL_CHANNEL(Y), 240 + SMI330_ACCEL_CHANNEL(Z), 241 + SMI330_GYRO_CHANNEL(X), 242 + SMI330_GYRO_CHANNEL(Y), 243 + SMI330_GYRO_CHANNEL(Z), 244 + SMI330_TEMP_CHANNEL(-1), /* No buffer support */ 245 + IIO_CHAN_SOFT_TIMESTAMP(SMI330_SCAN_TIMESTAMP), 246 + }; 247 + 248 + static const unsigned long smi330_avail_scan_masks[] = { 249 + (BIT(SMI330_SCAN_ACCEL_X) | BIT(SMI330_SCAN_ACCEL_Y) | 250 + BIT(SMI330_SCAN_ACCEL_Z) | BIT(SMI330_SCAN_GYRO_X) | 251 + BIT(SMI330_SCAN_GYRO_Y) | BIT(SMI330_SCAN_GYRO_Z)), 252 + 0 253 + }; 254 + 255 + static const struct smi330_attributes smi330_accel_scale_attr = { 256 + .reg_vals = (int[]){ SMI330_ACCEL_RANGE_2G, SMI330_ACCEL_RANGE_4G, 257 + SMI330_ACCEL_RANGE_8G, SMI330_ACCEL_RANGE_16G }, 258 + .vals = (int[]){ 0, 61035, 0, 122070, 0, 244140, 0, 488281 }, 259 + .len = 8, 260 + .type = IIO_VAL_INT_PLUS_NANO, 261 + .mask = SMI330_CFG_RANGE_MASK 262 + }; 263 + 264 + static const struct smi330_attributes smi330_gyro_scale_attr = { 265 + .reg_vals = (int[]){ SMI330_GYRO_RANGE_125, SMI330_GYRO_RANGE_250, 266 + SMI330_GYRO_RANGE_500 }, 267 + .vals = (int[]){ 0, 3814697, 0, 7629395, 0, 15258789 }, 268 + .len = 6, 269 + .type = IIO_VAL_INT_PLUS_NANO, 270 + .mask = SMI330_CFG_RANGE_MASK 271 + }; 272 + 273 + static const struct smi330_attributes smi330_average_attr = { 274 + .reg_vals = (int[]){ SMI330_AVG_NUM_1, SMI330_AVG_NUM_2, 275 + SMI330_AVG_NUM_4, SMI330_AVG_NUM_8, 276 + SMI330_AVG_NUM_16, SMI330_AVG_NUM_32, 277 + SMI330_AVG_NUM_64 }, 278 + .vals = (int[]){ 1, 2, 4, 8, 16, 32, 64 }, 279 + .len = 7, 280 + .type = IIO_VAL_INT, 281 + .mask = SMI330_CFG_AVG_NUM_MASK 282 + }; 283 + 284 + static const struct smi330_attributes smi330_bandwidth_attr = { 285 + .reg_vals = (int[]){ SMI330_BW_2, SMI330_BW_4 }, 286 + .vals = (int[]){ 2, 4 }, 287 + .len = 2, 288 + .type = IIO_VAL_INT, 289 + .mask = SMI330_CFG_BW_MASK 290 + }; 291 + 292 + static const struct smi330_attributes smi330_odr_attr = { 293 + .reg_vals = (int[]){ SMI330_ODR_12_5_HZ, SMI330_ODR_25_HZ, 294 + SMI330_ODR_50_HZ, SMI330_ODR_100_HZ, 295 + SMI330_ODR_200_HZ, SMI330_ODR_400_HZ, 296 + SMI330_ODR_800_HZ, SMI330_ODR_1600_HZ, 297 + SMI330_ODR_3200_HZ, SMI330_ODR_6400_HZ }, 298 + .vals = (int[]){ 12, 25, 50, 100, 200, 400, 800, 1600, 3200, 6400 }, 299 + .len = 10, 300 + .type = IIO_VAL_INT, 301 + .mask = SMI330_CFG_ODR_MASK 302 + }; 303 + 304 + static int smi330_get_attributes(enum smi330_sensor_conf_select config, 305 + enum smi330_sensor sensor, 306 + const struct smi330_attributes **attr) 307 + { 308 + switch (config) { 309 + case SMI330_ODR: 310 + *attr = &smi330_odr_attr; 311 + return 0; 312 + case SMI330_RANGE: 313 + if (sensor == SMI330_ACCEL) 314 + *attr = &smi330_accel_scale_attr; 315 + else 316 + *attr = &smi330_gyro_scale_attr; 317 + return 0; 318 + case SMI330_BW: 319 + *attr = &smi330_bandwidth_attr; 320 + return 0; 321 + case SMI330_AVG_NUM: 322 + *attr = &smi330_average_attr; 323 + return 0; 324 + default: 325 + return -EINVAL; 326 + } 327 + } 328 + 329 + static int smi330_get_config_reg(enum smi330_sensor sensor, int *reg) 330 + { 331 + switch (sensor) { 332 + case SMI330_ACCEL: 333 + *reg = SMI330_ACCEL_CFG_REG; 334 + return 0; 335 + case SMI330_GYRO: 336 + *reg = SMI330_GYRO_CFG_REG; 337 + return 0; 338 + default: 339 + return -EINVAL; 340 + } 341 + } 342 + 343 + static int smi330_get_sensor_config(struct smi330_data *data, 344 + enum smi330_sensor sensor, 345 + enum smi330_sensor_conf_select config, 346 + int *value) 347 + 348 + { 349 + int ret, reg, reg_val, i; 350 + const struct smi330_attributes *attr; 351 + 352 + ret = smi330_get_config_reg(sensor, &reg); 353 + if (ret) 354 + return ret; 355 + 356 + ret = regmap_read(data->regmap, reg, &reg_val); 357 + if (ret) 358 + return ret; 359 + 360 + ret = smi330_get_attributes(config, sensor, &attr); 361 + if (ret) 362 + return ret; 363 + 364 + reg_val = smi330_field_get(attr->mask, reg_val); 365 + 366 + if (attr->type == IIO_VAL_INT) { 367 + for (i = 0; i < attr->len; i++) { 368 + if (attr->reg_vals[i] == reg_val) { 369 + *value = attr->vals[i]; 370 + return 0; 371 + } 372 + } 373 + } else { 374 + for (i = 0; i < attr->len / 2; i++) { 375 + if (attr->reg_vals[i] == reg_val) { 376 + *value = attr->vals[2 * i + 1]; 377 + return 0; 378 + } 379 + } 380 + } 381 + 382 + return -EINVAL; 383 + } 384 + 385 + static int smi330_set_sensor_config(struct smi330_data *data, 386 + enum smi330_sensor sensor, 387 + enum smi330_sensor_conf_select config, 388 + int value) 389 + { 390 + int ret, i, reg, reg_val, error; 391 + const struct smi330_attributes *attr; 392 + 393 + ret = smi330_get_attributes(config, sensor, &attr); 394 + if (ret) 395 + return ret; 396 + 397 + for (i = 0; i < attr->len; i++) { 398 + if (attr->vals[i] == value) { 399 + if (attr->type == IIO_VAL_INT) 400 + reg_val = attr->reg_vals[i]; 401 + else 402 + reg_val = attr->reg_vals[i / 2]; 403 + break; 404 + } 405 + } 406 + if (i == attr->len) 407 + return -EINVAL; 408 + 409 + ret = smi330_get_config_reg(sensor, &reg); 410 + if (ret) 411 + return ret; 412 + 413 + reg_val = smi330_field_prep(attr->mask, reg_val); 414 + ret = regmap_update_bits(data->regmap, reg, attr->mask, reg_val); 415 + if (ret) 416 + return ret; 417 + 418 + ret = regmap_read(data->regmap, SMI330_ERR_REG, &error); 419 + if (ret) 420 + return ret; 421 + 422 + if (FIELD_GET(SMI330_ERR_ACC_CONF_MASK, error) || 423 + FIELD_GET(SMI330_ERR_GYR_CONF_MASK, error)) 424 + return -EIO; 425 + 426 + return 0; 427 + } 428 + 429 + static int smi330_get_data(struct smi330_data *data, int chan_type, int axis, 430 + int *val) 431 + { 432 + u8 reg; 433 + int ret, sample; 434 + 435 + switch (chan_type) { 436 + case IIO_ACCEL: 437 + reg = SMI330_ACCEL_X_REG + (axis - IIO_MOD_X); 438 + break; 439 + case IIO_ANGL_VEL: 440 + reg = SMI330_GYRO_X_REG + (axis - IIO_MOD_X); 441 + break; 442 + case IIO_TEMP: 443 + reg = SMI330_TEMP_REG; 444 + break; 445 + default: 446 + return -EINVAL; 447 + } 448 + 449 + ret = regmap_read(data->regmap, reg, &sample); 450 + if (ret) 451 + return ret; 452 + 453 + *val = sign_extend32(sample, 15); 454 + 455 + return 0; 456 + } 457 + 458 + static int smi330_read_avail(struct iio_dev *indio_dev, 459 + struct iio_chan_spec const *chan, const int **vals, 460 + int *type, int *length, long mask) 461 + { 462 + switch (mask) { 463 + case IIO_CHAN_INFO_SCALE: 464 + if (chan->type == IIO_ACCEL) { 465 + *vals = smi330_accel_scale_attr.vals; 466 + *length = smi330_accel_scale_attr.len; 467 + *type = smi330_accel_scale_attr.type; 468 + } else { 469 + *vals = smi330_gyro_scale_attr.vals; 470 + *length = smi330_gyro_scale_attr.len; 471 + *type = smi330_gyro_scale_attr.type; 472 + } 473 + return IIO_AVAIL_LIST; 474 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 475 + *vals = smi330_average_attr.vals; 476 + *length = smi330_average_attr.len; 477 + *type = smi330_average_attr.type; 478 + *type = IIO_VAL_INT; 479 + return IIO_AVAIL_LIST; 480 + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 481 + *vals = smi330_bandwidth_attr.vals; 482 + *length = smi330_bandwidth_attr.len; 483 + *type = smi330_bandwidth_attr.type; 484 + return IIO_AVAIL_LIST; 485 + case IIO_CHAN_INFO_SAMP_FREQ: 486 + *vals = smi330_odr_attr.vals; 487 + *length = smi330_odr_attr.len; 488 + *type = smi330_odr_attr.type; 489 + return IIO_AVAIL_LIST; 490 + default: 491 + return -EINVAL; 492 + } 493 + } 494 + 495 + static int smi330_read_raw(struct iio_dev *indio_dev, 496 + struct iio_chan_spec const *chan, int *val, 497 + int *val2, long mask) 498 + { 499 + int ret; 500 + struct smi330_data *data = iio_priv(indio_dev); 501 + enum smi330_sensor sensor; 502 + 503 + /* valid for all channel types */ 504 + switch (mask) { 505 + case IIO_CHAN_INFO_RAW: 506 + if (!iio_device_claim_direct(indio_dev)) 507 + return -EBUSY; 508 + ret = smi330_get_data(data, chan->type, chan->channel2, val); 509 + iio_device_release_direct(indio_dev); 510 + return ret ? ret : IIO_VAL_INT; 511 + default: 512 + break; 513 + } 514 + 515 + switch (chan->type) { 516 + case IIO_ACCEL: 517 + sensor = SMI330_ACCEL; 518 + break; 519 + case IIO_ANGL_VEL: 520 + sensor = SMI330_GYRO; 521 + break; 522 + case IIO_TEMP: 523 + switch (mask) { 524 + case IIO_CHAN_INFO_SCALE: 525 + *val = SMI330_TEMP_SCALE / GIGA; 526 + *val2 = SMI330_TEMP_SCALE % GIGA; 527 + return IIO_VAL_INT_PLUS_NANO; 528 + case IIO_CHAN_INFO_OFFSET: 529 + *val = SMI330_TEMP_OFFSET; 530 + return IIO_VAL_INT; 531 + default: 532 + return -EINVAL; 533 + } 534 + default: 535 + return -EINVAL; 536 + } 537 + 538 + /* valid for acc and gyro channels */ 539 + switch (mask) { 540 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 541 + ret = smi330_get_sensor_config(data, sensor, SMI330_AVG_NUM, 542 + val); 543 + return ret ? ret : IIO_VAL_INT; 544 + 545 + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 546 + ret = smi330_get_sensor_config(data, sensor, SMI330_BW, val); 547 + return ret ? ret : IIO_VAL_INT; 548 + 549 + case IIO_CHAN_INFO_SAMP_FREQ: 550 + ret = smi330_get_sensor_config(data, sensor, SMI330_ODR, val); 551 + return ret ? ret : IIO_VAL_INT; 552 + 553 + case IIO_CHAN_INFO_SCALE: 554 + *val = 0; 555 + ret = smi330_get_sensor_config(data, sensor, SMI330_RANGE, 556 + val2); 557 + return ret ? ret : IIO_VAL_INT_PLUS_NANO; 558 + 559 + default: 560 + return -EINVAL; 561 + } 562 + } 563 + 564 + static int smi330_write_raw(struct iio_dev *indio_dev, 565 + struct iio_chan_spec const *chan, int val, int val2, 566 + long mask) 567 + { 568 + struct smi330_data *data = iio_priv(indio_dev); 569 + enum smi330_sensor sensor; 570 + 571 + switch (chan->type) { 572 + case IIO_ACCEL: 573 + sensor = SMI330_ACCEL; 574 + break; 575 + case IIO_ANGL_VEL: 576 + sensor = SMI330_GYRO; 577 + break; 578 + default: 579 + return -EINVAL; 580 + } 581 + 582 + switch (mask) { 583 + case IIO_CHAN_INFO_SCALE: 584 + return smi330_set_sensor_config(data, sensor, SMI330_RANGE, 585 + val2); 586 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 587 + return smi330_set_sensor_config(data, sensor, SMI330_AVG_NUM, 588 + val); 589 + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 590 + return smi330_set_sensor_config(data, sensor, SMI330_BW, val); 591 + case IIO_CHAN_INFO_SAMP_FREQ: 592 + return smi330_set_sensor_config(data, sensor, SMI330_ODR, val); 593 + default: 594 + return -EINVAL; 595 + } 596 + } 597 + 598 + static int smi330_write_raw_get_fmt(struct iio_dev *indio_dev, 599 + struct iio_chan_spec const *chan, long info) 600 + { 601 + switch (info) { 602 + case IIO_CHAN_INFO_SCALE: 603 + return IIO_VAL_INT_PLUS_NANO; 604 + default: 605 + return IIO_VAL_INT_PLUS_MICRO; 606 + } 607 + } 608 + 609 + static int smi330_soft_reset(struct smi330_data *data) 610 + { 611 + int ret, dummy_byte; 612 + 613 + ret = regmap_write(data->regmap, SMI330_CMD_REG, SMI330_CMD_SOFT_RESET); 614 + if (ret) 615 + return ret; 616 + fsleep(SMI330_SOFT_RESET_DELAY); 617 + 618 + /* Performing a dummy read after a soft-reset */ 619 + regmap_read(data->regmap, SMI330_CHIP_ID_REG, &dummy_byte); 620 + 621 + return 0; 622 + } 623 + 624 + static irqreturn_t smi330_trigger_handler(int irq, void *p) 625 + { 626 + int ret; 627 + struct iio_poll_func *pf = p; 628 + struct iio_dev *indio_dev = pf->indio_dev; 629 + struct smi330_data *data = iio_priv(indio_dev); 630 + 631 + ret = regmap_bulk_read(data->regmap, SMI330_ACCEL_X_REG, data->buf, 632 + SMI330_SCAN_LEN); 633 + if (ret) 634 + goto out; 635 + 636 + iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp); 637 + 638 + out: 639 + iio_trigger_notify_done(indio_dev->trig); 640 + 641 + return IRQ_HANDLED; 642 + } 643 + 644 + static irqreturn_t smi330_irq_thread_handler(int irq, void *indio_dev_) 645 + { 646 + int ret, int_stat; 647 + s16 int_status[2] = { 0 }; 648 + struct iio_dev *indio_dev = indio_dev_; 649 + struct smi330_data *data = iio_priv(indio_dev); 650 + 651 + ret = regmap_bulk_read(data->regmap, SMI330_INT1_STATUS_REG, int_status, 2); 652 + if (ret) 653 + return IRQ_NONE; 654 + 655 + int_stat = int_status[0] | int_status[1]; 656 + 657 + if (FIELD_GET(SMI330_INT_STATUS_ACC_GYR_DRDY_MASK, int_stat)) { 658 + indio_dev->pollfunc->timestamp = iio_get_time_ns(indio_dev); 659 + iio_trigger_poll_nested(data->trig); 660 + } 661 + 662 + return IRQ_HANDLED; 663 + } 664 + 665 + static int smi330_set_int_pin_config(struct smi330_data *data, 666 + enum smi330_int_out irq_num, 667 + bool active_high, bool open_drain, 668 + bool latch) 669 + { 670 + int ret, val; 671 + 672 + val = active_high ? SMI330_IO_INT_CTRL_LVL : 0; 673 + val |= open_drain ? SMI330_IO_INT_CTRL_OD : 0; 674 + val |= SMI330_IO_INT_CTRL_EN; 675 + 676 + switch (irq_num) { 677 + case SMI330_INT_1: 678 + val = FIELD_PREP(SMI330_IO_INT_CTRL_INT1_MASK, val); 679 + ret = regmap_update_bits(data->regmap, SMI330_IO_INT_CTRL_REG, 680 + SMI330_IO_INT_CTRL_INT1_MASK, val); 681 + if (ret) 682 + return ret; 683 + break; 684 + case SMI330_INT_2: 685 + val = FIELD_PREP(SMI330_IO_INT_CTRL_INT2_MASK, val); 686 + ret = regmap_update_bits(data->regmap, SMI330_IO_INT_CTRL_REG, 687 + SMI330_IO_INT_CTRL_INT2_MASK, val); 688 + if (ret) 689 + return ret; 690 + break; 691 + default: 692 + return -EINVAL; 693 + } 694 + 695 + return regmap_update_bits(data->regmap, SMI330_INT_CONF_REG, 696 + SMI330_INT_CONF_LATCH_MASK, 697 + FIELD_PREP(SMI330_INT_CONF_LATCH_MASK, 698 + latch)); 699 + } 700 + 701 + static int smi330_setup_irq(struct device *dev, struct iio_dev *indio_dev, 702 + int irq, enum smi330_int_out irq_num) 703 + { 704 + int ret, irq_type; 705 + bool open_drain, active_high, latch; 706 + struct smi330_data *data = iio_priv(indio_dev); 707 + struct irq_data *desc; 708 + 709 + desc = irq_get_irq_data(irq); 710 + if (!desc) 711 + return -EINVAL; 712 + 713 + irq_type = irqd_get_trigger_type(desc); 714 + switch (irq_type) { 715 + case IRQF_TRIGGER_RISING: 716 + latch = false; 717 + active_high = true; 718 + break; 719 + case IRQF_TRIGGER_HIGH: 720 + latch = true; 721 + active_high = true; 722 + break; 723 + case IRQF_TRIGGER_FALLING: 724 + latch = false; 725 + active_high = false; 726 + break; 727 + case IRQF_TRIGGER_LOW: 728 + latch = true; 729 + active_high = false; 730 + break; 731 + default: 732 + return -EINVAL; 733 + } 734 + 735 + open_drain = device_property_read_bool(dev, "drive-open-drain"); 736 + 737 + ret = smi330_set_int_pin_config(data, irq_num, active_high, open_drain, 738 + latch); 739 + if (ret) 740 + return ret; 741 + 742 + return devm_request_threaded_irq(dev, irq, NULL, 743 + smi330_irq_thread_handler, 744 + irq_type | IRQF_ONESHOT, 745 + indio_dev->name, indio_dev); 746 + } 747 + 748 + static int smi330_register_irq(struct device *dev, struct iio_dev *indio_dev) 749 + { 750 + int ret, irq; 751 + struct smi330_data *data = iio_priv(indio_dev); 752 + struct fwnode_handle *fwnode; 753 + 754 + fwnode = dev_fwnode(dev); 755 + if (!fwnode) 756 + return -ENODEV; 757 + 758 + data->cfg.data_irq = SMI330_INT_DISABLED; 759 + 760 + irq = fwnode_irq_get_byname(fwnode, "INT1"); 761 + if (irq > 0) { 762 + ret = smi330_setup_irq(dev, indio_dev, irq, SMI330_INT_1); 763 + if (ret) 764 + return ret; 765 + data->cfg.data_irq = SMI330_INT_1; 766 + } else { 767 + irq = fwnode_irq_get_byname(fwnode, "INT2"); 768 + if (irq > 0) { 769 + ret = smi330_setup_irq(dev, indio_dev, irq, 770 + SMI330_INT_2); 771 + if (ret) 772 + return ret; 773 + data->cfg.data_irq = SMI330_INT_2; 774 + } 775 + } 776 + 777 + return 0; 778 + } 779 + 780 + static int smi330_set_drdy_trigger_state(struct iio_trigger *trig, bool enable) 781 + { 782 + int val; 783 + struct smi330_data *data = iio_trigger_get_drvdata(trig); 784 + 785 + if (enable) 786 + data->cfg.op_mode = SMI330_DATA_READY; 787 + else 788 + data->cfg.op_mode = SMI330_POLLING; 789 + 790 + val = FIELD_PREP(SMI330_INT_MAP2_ACC_DRDY_MASK, 791 + enable ? data->cfg.data_irq : 0); 792 + val |= FIELD_PREP(SMI330_INT_MAP2_GYR_DRDY_MASK, 793 + enable ? data->cfg.data_irq : 0); 794 + return regmap_update_bits(data->regmap, SMI330_INT_MAP2_REG, 795 + SMI330_INT_MAP2_ACC_DRDY_MASK | 796 + SMI330_INT_MAP2_GYR_DRDY_MASK, 797 + val); 798 + } 799 + 800 + static const struct iio_trigger_ops smi330_trigger_ops = { 801 + .set_trigger_state = &smi330_set_drdy_trigger_state, 802 + }; 803 + 804 + static struct iio_info smi330_info = { 805 + .read_avail = smi330_read_avail, 806 + .read_raw = smi330_read_raw, 807 + .write_raw = smi330_write_raw, 808 + .write_raw_get_fmt = smi330_write_raw_get_fmt, 809 + }; 810 + 811 + static int smi330_dev_init(struct smi330_data *data) 812 + { 813 + int ret, chip_id, val, mode; 814 + struct device *dev = regmap_get_device(data->regmap); 815 + 816 + ret = regmap_read(data->regmap, SMI330_CHIP_ID_REG, &chip_id); 817 + if (ret) 818 + return ret; 819 + 820 + chip_id = FIELD_GET(SMI330_CHIP_ID_MASK, chip_id); 821 + if (chip_id != SMI330_CHIP_ID) 822 + dev_info(dev, "Unknown chip id: 0x%04x\n", chip_id); 823 + 824 + ret = regmap_read(data->regmap, SMI330_ERR_REG, &val); 825 + if (ret) 826 + return ret; 827 + if (FIELD_GET(SMI330_ERR_FATAL_MASK, val)) 828 + return -ENODEV; 829 + 830 + ret = regmap_read(data->regmap, SMI330_STATUS_REG, &val); 831 + if (ret) 832 + return ret; 833 + if (FIELD_GET(SMI330_STATUS_POR_MASK, val) == 0) 834 + return -ENODEV; 835 + 836 + mode = FIELD_PREP(SMI330_CFG_MODE_MASK, SMI330_MODE_NORMAL); 837 + 838 + ret = regmap_update_bits(data->regmap, SMI330_ACCEL_CFG_REG, 839 + SMI330_CFG_MODE_MASK, mode); 840 + if (ret) 841 + return ret; 842 + 843 + return regmap_update_bits(data->regmap, SMI330_GYRO_CFG_REG, 844 + SMI330_CFG_MODE_MASK, mode); 845 + } 846 + 847 + int smi330_core_probe(struct device *dev, struct regmap *regmap) 848 + { 849 + int ret; 850 + struct iio_dev *indio_dev; 851 + struct smi330_data *data; 852 + 853 + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 854 + if (!indio_dev) 855 + return -ENOMEM; 856 + 857 + data = iio_priv(indio_dev); 858 + data->regmap = regmap; 859 + 860 + ret = smi330_soft_reset(data); 861 + if (ret) 862 + return dev_err_probe(dev, ret, "Soft reset failed\n"); 863 + 864 + indio_dev->channels = smi330_channels; 865 + indio_dev->num_channels = ARRAY_SIZE(smi330_channels); 866 + indio_dev->available_scan_masks = smi330_avail_scan_masks; 867 + indio_dev->name = "smi330"; 868 + indio_dev->modes = INDIO_DIRECT_MODE; 869 + indio_dev->info = &smi330_info; 870 + 871 + data->cfg.op_mode = SMI330_POLLING; 872 + 873 + ret = smi330_dev_init(data); 874 + if (ret) 875 + return dev_err_probe(dev, ret, "Init failed\n"); 876 + 877 + ret = smi330_register_irq(dev, indio_dev); 878 + if (ret) 879 + return dev_err_probe(dev, ret, "Register IRQ failed\n"); 880 + 881 + if (data->cfg.data_irq != SMI330_INT_DISABLED) { 882 + data->trig = devm_iio_trigger_alloc(dev, "%s-drdy-trigger", 883 + indio_dev->name); 884 + if (!data->trig) 885 + return -ENOMEM; 886 + 887 + data->trig->ops = &smi330_trigger_ops; 888 + iio_trigger_set_drvdata(data->trig, data); 889 + 890 + ret = devm_iio_trigger_register(dev, data->trig); 891 + if (ret) 892 + return dev_err_probe(dev, ret, 893 + "IIO register trigger failed\n"); 894 + 895 + /* Set default operation mode to data ready. */ 896 + indio_dev->trig = iio_trigger_get(data->trig); 897 + } 898 + 899 + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, 900 + iio_pollfunc_store_time, 901 + smi330_trigger_handler, NULL); 902 + if (ret) 903 + return dev_err_probe(dev, ret, "IIO buffer setup failed\n"); 904 + 905 + ret = devm_iio_device_register(dev, indio_dev); 906 + if (ret) 907 + return dev_err_probe(dev, ret, "Register IIO device failed\n"); 908 + 909 + return 0; 910 + } 911 + EXPORT_SYMBOL_NS_GPL(smi330_core_probe, "IIO_SMI330"); 912 + 913 + MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>"); 914 + MODULE_AUTHOR("Roman Huber <roman.huber@de.bosch.com>"); 915 + MODULE_AUTHOR("Filip Andrei <Andrei.Filip@ro.bosch.com>"); 916 + MODULE_AUTHOR("Drimbarean Avram Andrei <Avram-Andrei.Drimbarean@ro.bosch.com>"); 917 + MODULE_DESCRIPTION("Bosch SMI330 IMU driver"); 918 + MODULE_LICENSE("Dual BSD/GPL");
+133
drivers/iio/imu/smi330/smi330_i2c.c
··· 1 + // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 + /* 3 + * Copyright (c) 2025 Robert Bosch GmbH. 4 + */ 5 + #include <linux/i2c.h> 6 + #include <linux/mod_devicetable.h> 7 + #include <linux/module.h> 8 + #include <linux/regmap.h> 9 + 10 + #include "smi330.h" 11 + 12 + #define SMI330_NUM_DUMMY_BYTES 2 13 + #define SMI330_I2C_MAX_RX_BUFFER_SIZE \ 14 + (SMI330_NUM_DUMMY_BYTES + SMI330_SCAN_LEN * sizeof(s16)) 15 + 16 + struct smi330_i2c_priv { 17 + struct i2c_client *i2c; 18 + u8 rx_buffer[SMI330_I2C_MAX_RX_BUFFER_SIZE]; 19 + }; 20 + 21 + static int smi330_regmap_i2c_read(void *context, const void *reg_buf, 22 + size_t reg_size, void *val_buf, 23 + size_t val_size) 24 + { 25 + struct smi330_i2c_priv *priv = context; 26 + int ret; 27 + 28 + if (SMI330_NUM_DUMMY_BYTES + val_size > SMI330_I2C_MAX_RX_BUFFER_SIZE) 29 + return -EINVAL; 30 + 31 + /* 32 + * SMI330 I2C read frame: 33 + * <Slave address[6:0], RnW> <x, Register address[6:0]> 34 + * <Slave address[6:0], RnW> <Dummy[7:0]> <Dummy[7:0]> <Data_0[7:0]> <Data_1[15:8]>... 35 + * <Data_N[7:0]> <Data_N[15:8]> 36 + * Remark: Slave address is not considered part of the frame in the following definitions 37 + */ 38 + struct i2c_msg msgs[] = { 39 + { 40 + .addr = priv->i2c->addr, 41 + .flags = priv->i2c->flags, 42 + .len = reg_size, 43 + .buf = (u8 *)reg_buf, 44 + }, 45 + { 46 + .addr = priv->i2c->addr, 47 + .flags = priv->i2c->flags | I2C_M_RD, 48 + .len = SMI330_NUM_DUMMY_BYTES + val_size, 49 + .buf = priv->rx_buffer, 50 + }, 51 + }; 52 + 53 + ret = i2c_transfer(priv->i2c->adapter, msgs, ARRAY_SIZE(msgs)); 54 + if (ret < 0) 55 + return ret; 56 + 57 + memcpy(val_buf, priv->rx_buffer + SMI330_NUM_DUMMY_BYTES, val_size); 58 + 59 + return 0; 60 + } 61 + 62 + static int smi330_regmap_i2c_write(void *context, const void *data, 63 + size_t count) 64 + { 65 + struct smi330_i2c_priv *priv = context; 66 + u8 reg; 67 + 68 + /* 69 + * SMI330 I2C write frame: 70 + * <Slave address[6:0], RnW> <x, Register address[6:0]> <Data_0[7:0]> <Data_1[15:8]>... 71 + * <Data_N[7:0]> <Data_N[15:8]> 72 + * Remark: Slave address is not considered part of the frame in the following definitions 73 + */ 74 + reg = *(u8 *)data; 75 + return i2c_smbus_write_i2c_block_data(priv->i2c, reg, 76 + count - sizeof(u8), 77 + data + sizeof(u8)); 78 + } 79 + 80 + static const struct regmap_bus smi330_regmap_bus = { 81 + .read = smi330_regmap_i2c_read, 82 + .write = smi330_regmap_i2c_write, 83 + }; 84 + 85 + static int smi330_i2c_probe(struct i2c_client *i2c) 86 + { 87 + struct device *dev = &i2c->dev; 88 + struct smi330_i2c_priv *priv; 89 + struct regmap *regmap; 90 + 91 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 92 + if (!priv) 93 + return -ENOMEM; 94 + 95 + priv->i2c = i2c; 96 + regmap = devm_regmap_init(dev, &smi330_regmap_bus, priv, 97 + &smi330_regmap_config); 98 + if (IS_ERR(regmap)) 99 + return dev_err_probe(dev, PTR_ERR(regmap), 100 + "Failed to initialize I2C Regmap\n"); 101 + 102 + return smi330_core_probe(dev, regmap); 103 + } 104 + 105 + static const struct i2c_device_id smi330_i2c_device_id[] = { 106 + { .name = "smi330" }, 107 + { } 108 + }; 109 + MODULE_DEVICE_TABLE(i2c, smi330_i2c_device_id); 110 + 111 + static const struct of_device_id smi330_of_match[] = { 112 + { .compatible = "bosch,smi330" }, 113 + { } 114 + }; 115 + MODULE_DEVICE_TABLE(of, smi330_of_match); 116 + 117 + static struct i2c_driver smi330_i2c_driver = { 118 + .probe = smi330_i2c_probe, 119 + .id_table = smi330_i2c_device_id, 120 + .driver = { 121 + .of_match_table = smi330_of_match, 122 + .name = "smi330_i2c", 123 + }, 124 + }; 125 + module_i2c_driver(smi330_i2c_driver); 126 + 127 + MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>"); 128 + MODULE_AUTHOR("Roman Huber <roman.huber@de.bosch.com>"); 129 + MODULE_AUTHOR("Filip Andrei <Andrei.Filip@ro.bosch.com>"); 130 + MODULE_AUTHOR("Drimbarean Avram Andrei <Avram-Andrei.Drimbarean@ro.bosch.com>"); 131 + MODULE_DESCRIPTION("Bosch SMI330 I2C driver"); 132 + MODULE_LICENSE("Dual BSD/GPL"); 133 + MODULE_IMPORT_NS("IIO_SMI330");
+85
drivers/iio/imu/smi330/smi330_spi.c
··· 1 + // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 + /* 3 + * Copyright (c) 2025 Robert Bosch GmbH. 4 + */ 5 + #include <linux/mod_devicetable.h> 6 + #include <linux/module.h> 7 + #include <linux/regmap.h> 8 + #include <linux/spi/spi.h> 9 + 10 + #include "smi330.h" 11 + 12 + static int smi330_regmap_spi_read(void *context, const void *reg_buf, 13 + size_t reg_size, void *val_buf, 14 + size_t val_size) 15 + { 16 + struct spi_device *spi = context; 17 + 18 + /* Insert pad byte for reading */ 19 + u8 reg[] = { *(u8 *)reg_buf, 0 }; 20 + 21 + if (reg_size + 1 != ARRAY_SIZE(reg)) { 22 + dev_err(&spi->dev, "Invalid register size %zu\n", reg_size); 23 + return -EINVAL; 24 + } 25 + 26 + return spi_write_then_read(spi, reg, ARRAY_SIZE(reg), val_buf, 27 + val_size); 28 + } 29 + 30 + static int smi330_regmap_spi_write(void *context, const void *data, 31 + size_t count) 32 + { 33 + struct spi_device *spi = context; 34 + 35 + return spi_write(spi, data, count); 36 + } 37 + 38 + static const struct regmap_bus smi330_regmap_bus = { 39 + .read = smi330_regmap_spi_read, 40 + .write = smi330_regmap_spi_write, 41 + .read_flag_mask = 0x80, 42 + }; 43 + 44 + static int smi330_spi_probe(struct spi_device *spi) 45 + { 46 + struct regmap *regmap; 47 + 48 + regmap = devm_regmap_init(&spi->dev, &smi330_regmap_bus, &spi->dev, 49 + &smi330_regmap_config); 50 + if (IS_ERR(regmap)) 51 + return dev_err_probe(&spi->dev, PTR_ERR(regmap), 52 + "Failed to initialize SPI Regmap\n"); 53 + 54 + return smi330_core_probe(&spi->dev, regmap); 55 + } 56 + 57 + static const struct spi_device_id smi330_spi_device_id[] = { 58 + { .name = "smi330" }, 59 + { } 60 + }; 61 + MODULE_DEVICE_TABLE(spi, smi330_spi_device_id); 62 + 63 + static const struct of_device_id smi330_of_match[] = { 64 + { .compatible = "bosch,smi330" }, 65 + { } 66 + }; 67 + MODULE_DEVICE_TABLE(of, smi330_of_match); 68 + 69 + static struct spi_driver smi330_spi_driver = { 70 + .probe = smi330_spi_probe, 71 + .id_table = smi330_spi_device_id, 72 + .driver = { 73 + .of_match_table = smi330_of_match, 74 + .name = "smi330_spi", 75 + }, 76 + }; 77 + module_spi_driver(smi330_spi_driver); 78 + 79 + MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>"); 80 + MODULE_AUTHOR("Roman Huber <roman.huber@de.bosch.com>"); 81 + MODULE_AUTHOR("Filip Andrei <Andrei.Filip@ro.bosch.com>"); 82 + MODULE_AUTHOR("Drimbarean Avram Andrei <Avram-Andrei.Drimbarean@ro.bosch.com>"); 83 + MODULE_DESCRIPTION("Bosch SMI330 SPI driver"); 84 + MODULE_LICENSE("Dual BSD/GPL"); 85 + MODULE_IMPORT_NS("IIO_SMI330");