1*99918e78SShen Jianping // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2*99918e78SShen Jianping /* 3*99918e78SShen Jianping * Copyright (c) 2024 Robert Bosch GmbH. 4*99918e78SShen Jianping */ 5*99918e78SShen Jianping #include <linux/bitfield.h> 6*99918e78SShen Jianping #include <linux/bits.h> 7*99918e78SShen Jianping #include <linux/delay.h> 8*99918e78SShen Jianping #include <linux/device.h> 9*99918e78SShen Jianping #include <linux/module.h> 10*99918e78SShen Jianping #include <linux/regmap.h> 11*99918e78SShen Jianping #include <linux/spi/spi.h> 12*99918e78SShen Jianping #include <linux/unaligned.h> 13*99918e78SShen Jianping #include <linux/units.h> 14*99918e78SShen Jianping 15*99918e78SShen Jianping #include <linux/iio/buffer.h> 16*99918e78SShen Jianping #include <linux/iio/iio.h> 17*99918e78SShen Jianping #include <linux/iio/trigger.h> 18*99918e78SShen Jianping #include <linux/iio/trigger_consumer.h> 19*99918e78SShen Jianping #include <linux/iio/triggered_buffer.h> 20*99918e78SShen Jianping 21*99918e78SShen Jianping #define SMI240_CHIP_ID 0x0024 22*99918e78SShen Jianping 23*99918e78SShen Jianping #define SMI240_SOFT_CONFIG_EOC_MASK BIT(0) 24*99918e78SShen Jianping #define SMI240_SOFT_CONFIG_GYR_BW_MASK BIT(1) 25*99918e78SShen Jianping #define SMI240_SOFT_CONFIG_ACC_BW_MASK BIT(2) 26*99918e78SShen Jianping #define SMI240_SOFT_CONFIG_BITE_AUTO_MASK BIT(3) 27*99918e78SShen Jianping #define SMI240_SOFT_CONFIG_BITE_REP_MASK GENMASK(6, 4) 28*99918e78SShen Jianping 29*99918e78SShen Jianping #define SMI240_CHIP_ID_REG 0x00 30*99918e78SShen Jianping #define SMI240_SOFT_CONFIG_REG 0x0A 31*99918e78SShen Jianping #define SMI240_TEMP_CUR_REG 0x10 32*99918e78SShen Jianping #define SMI240_ACCEL_X_CUR_REG 0x11 33*99918e78SShen Jianping #define SMI240_GYRO_X_CUR_REG 0x14 34*99918e78SShen Jianping #define SMI240_DATA_CAP_FIRST_REG 0x17 35*99918e78SShen Jianping #define SMI240_CMD_REG 0x2F 36*99918e78SShen Jianping 37*99918e78SShen Jianping #define SMI240_SOFT_RESET_CMD 0xB6 38*99918e78SShen Jianping 39*99918e78SShen Jianping #define SMI240_BITE_SEQUENCE_DELAY_US 140000 40*99918e78SShen Jianping #define SMI240_FILTER_FLUSH_DELAY_US 60000 41*99918e78SShen Jianping #define SMI240_DIGITAL_STARTUP_DELAY_US 120000 42*99918e78SShen Jianping #define SMI240_MECH_STARTUP_DELAY_US 100000 43*99918e78SShen Jianping 44*99918e78SShen Jianping #define SMI240_BUS_ID 0x00 45*99918e78SShen Jianping #define SMI240_CRC_INIT 0x05 46*99918e78SShen Jianping #define SMI240_CRC_POLY 0x0B 47*99918e78SShen Jianping #define SMI240_CRC_MASK GENMASK(2, 0) 48*99918e78SShen Jianping 49*99918e78SShen Jianping #define SMI240_READ_SD_BIT_MASK BIT(31) 50*99918e78SShen Jianping #define SMI240_READ_DATA_MASK GENMASK(19, 4) 51*99918e78SShen Jianping #define SMI240_READ_CS_BIT_MASK BIT(3) 52*99918e78SShen Jianping 53*99918e78SShen Jianping #define SMI240_WRITE_BUS_ID_MASK GENMASK(31, 30) 54*99918e78SShen Jianping #define SMI240_WRITE_ADDR_MASK GENMASK(29, 22) 55*99918e78SShen Jianping #define SMI240_WRITE_BIT_MASK BIT(21) 56*99918e78SShen Jianping #define SMI240_WRITE_CAP_BIT_MASK BIT(20) 57*99918e78SShen Jianping #define SMI240_WRITE_DATA_MASK GENMASK(18, 3) 58*99918e78SShen Jianping 59*99918e78SShen Jianping /* T°C = (temp / 256) + 25 */ 60*99918e78SShen Jianping #define SMI240_TEMP_OFFSET 6400 /* 25 * 256 */ 61*99918e78SShen Jianping #define SMI240_TEMP_SCALE 3906250 /* (1 / 256) * 1e9 */ 62*99918e78SShen Jianping 63*99918e78SShen Jianping #define SMI240_ACCEL_SCALE 500 /* (1 / 2000) * 1e6 */ 64*99918e78SShen Jianping #define SMI240_GYRO_SCALE 10000 /* (1 / 100) * 1e6 */ 65*99918e78SShen Jianping 66*99918e78SShen Jianping #define SMI240_LOW_BANDWIDTH_HZ 50 67*99918e78SShen Jianping #define SMI240_HIGH_BANDWIDTH_HZ 400 68*99918e78SShen Jianping 69*99918e78SShen Jianping #define SMI240_BUILT_IN_SELF_TEST_COUNT 3 70*99918e78SShen Jianping 71*99918e78SShen Jianping #define SMI240_DATA_CHANNEL(_type, _axis, _index) { \ 72*99918e78SShen Jianping .type = _type, \ 73*99918e78SShen Jianping .modified = 1, \ 74*99918e78SShen Jianping .channel2 = IIO_MOD_##_axis, \ 75*99918e78SShen Jianping .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 76*99918e78SShen Jianping .info_mask_shared_by_type = \ 77*99918e78SShen Jianping BIT(IIO_CHAN_INFO_SCALE) | \ 78*99918e78SShen Jianping BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 79*99918e78SShen Jianping .info_mask_shared_by_type_available = \ 80*99918e78SShen Jianping BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ 81*99918e78SShen Jianping .scan_index = _index, \ 82*99918e78SShen Jianping .scan_type = { \ 83*99918e78SShen Jianping .sign = 's', \ 84*99918e78SShen Jianping .realbits = 16, \ 85*99918e78SShen Jianping .storagebits = 16, \ 86*99918e78SShen Jianping .endianness = IIO_CPU, \ 87*99918e78SShen Jianping }, \ 88*99918e78SShen Jianping } 89*99918e78SShen Jianping 90*99918e78SShen Jianping #define SMI240_TEMP_CHANNEL(_index) { \ 91*99918e78SShen Jianping .type = IIO_TEMP, \ 92*99918e78SShen Jianping .modified = 1, \ 93*99918e78SShen Jianping .channel2 = IIO_MOD_TEMP_OBJECT, \ 94*99918e78SShen Jianping .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 95*99918e78SShen Jianping BIT(IIO_CHAN_INFO_OFFSET) | \ 96*99918e78SShen Jianping BIT(IIO_CHAN_INFO_SCALE), \ 97*99918e78SShen Jianping .scan_index = _index, \ 98*99918e78SShen Jianping .scan_type = { \ 99*99918e78SShen Jianping .sign = 's', \ 100*99918e78SShen Jianping .realbits = 16, \ 101*99918e78SShen Jianping .storagebits = 16, \ 102*99918e78SShen Jianping .endianness = IIO_CPU, \ 103*99918e78SShen Jianping }, \ 104*99918e78SShen Jianping } 105*99918e78SShen Jianping 106*99918e78SShen Jianping enum capture_mode { SMI240_CAPTURE_OFF = 0, SMI240_CAPTURE_ON = 1 }; 107*99918e78SShen Jianping 108*99918e78SShen Jianping struct smi240_data { 109*99918e78SShen Jianping struct regmap *regmap; 110*99918e78SShen Jianping u16 accel_filter_freq; 111*99918e78SShen Jianping u16 anglvel_filter_freq; 112*99918e78SShen Jianping u8 built_in_self_test_count; 113*99918e78SShen Jianping enum capture_mode capture; 114*99918e78SShen Jianping /* 115*99918e78SShen Jianping * Ensure natural alignment for timestamp if present. 116*99918e78SShen Jianping * Channel size: 2 bytes. 117*99918e78SShen Jianping * Max length needed: 2 * 3 channels + temp channel + 2 bytes padding + 8 byte ts. 118*99918e78SShen Jianping * If fewer channels are enabled, less space may be needed, as 119*99918e78SShen Jianping * long as the timestamp is still aligned to 8 bytes. 120*99918e78SShen Jianping */ 121*99918e78SShen Jianping s16 buf[12] __aligned(8); 122*99918e78SShen Jianping 123*99918e78SShen Jianping __be32 spi_buf __aligned(IIO_DMA_MINALIGN); 124*99918e78SShen Jianping }; 125*99918e78SShen Jianping 126*99918e78SShen Jianping enum { 127*99918e78SShen Jianping SMI240_TEMP_OBJECT, 128*99918e78SShen Jianping SMI240_SCAN_ACCEL_X, 129*99918e78SShen Jianping SMI240_SCAN_ACCEL_Y, 130*99918e78SShen Jianping SMI240_SCAN_ACCEL_Z, 131*99918e78SShen Jianping SMI240_SCAN_GYRO_X, 132*99918e78SShen Jianping SMI240_SCAN_GYRO_Y, 133*99918e78SShen Jianping SMI240_SCAN_GYRO_Z, 134*99918e78SShen Jianping SMI240_SCAN_TIMESTAMP, 135*99918e78SShen Jianping }; 136*99918e78SShen Jianping 137*99918e78SShen Jianping static const struct iio_chan_spec smi240_channels[] = { 138*99918e78SShen Jianping SMI240_TEMP_CHANNEL(SMI240_TEMP_OBJECT), 139*99918e78SShen Jianping SMI240_DATA_CHANNEL(IIO_ACCEL, X, SMI240_SCAN_ACCEL_X), 140*99918e78SShen Jianping SMI240_DATA_CHANNEL(IIO_ACCEL, Y, SMI240_SCAN_ACCEL_Y), 141*99918e78SShen Jianping SMI240_DATA_CHANNEL(IIO_ACCEL, Z, SMI240_SCAN_ACCEL_Z), 142*99918e78SShen Jianping SMI240_DATA_CHANNEL(IIO_ANGL_VEL, X, SMI240_SCAN_GYRO_X), 143*99918e78SShen Jianping SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Y, SMI240_SCAN_GYRO_Y), 144*99918e78SShen Jianping SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Z, SMI240_SCAN_GYRO_Z), 145*99918e78SShen Jianping IIO_CHAN_SOFT_TIMESTAMP(SMI240_SCAN_TIMESTAMP), 146*99918e78SShen Jianping }; 147*99918e78SShen Jianping 148*99918e78SShen Jianping static const int smi240_low_pass_freqs[] = { SMI240_LOW_BANDWIDTH_HZ, 149*99918e78SShen Jianping SMI240_HIGH_BANDWIDTH_HZ }; 150*99918e78SShen Jianping 151*99918e78SShen Jianping static u8 smi240_crc3(u32 data, u8 init, u8 poly) 152*99918e78SShen Jianping { 153*99918e78SShen Jianping u8 crc = init; 154*99918e78SShen Jianping u8 do_xor; 155*99918e78SShen Jianping s8 i = 31; 156*99918e78SShen Jianping 157*99918e78SShen Jianping do { 158*99918e78SShen Jianping do_xor = crc & 0x04; 159*99918e78SShen Jianping crc <<= 1; 160*99918e78SShen Jianping crc |= 0x01 & (data >> i); 161*99918e78SShen Jianping if (do_xor) 162*99918e78SShen Jianping crc ^= poly; 163*99918e78SShen Jianping 164*99918e78SShen Jianping crc &= SMI240_CRC_MASK; 165*99918e78SShen Jianping } while (--i >= 0); 166*99918e78SShen Jianping 167*99918e78SShen Jianping return crc; 168*99918e78SShen Jianping } 169*99918e78SShen Jianping 170*99918e78SShen Jianping static bool smi240_sensor_data_is_valid(u32 data) 171*99918e78SShen Jianping { 172*99918e78SShen Jianping if (smi240_crc3(data, SMI240_CRC_INIT, SMI240_CRC_POLY) != 0) 173*99918e78SShen Jianping return false; 174*99918e78SShen Jianping 175*99918e78SShen Jianping if (FIELD_GET(SMI240_READ_SD_BIT_MASK, data) & 176*99918e78SShen Jianping FIELD_GET(SMI240_READ_CS_BIT_MASK, data)) 177*99918e78SShen Jianping return false; 178*99918e78SShen Jianping 179*99918e78SShen Jianping return true; 180*99918e78SShen Jianping } 181*99918e78SShen Jianping 182*99918e78SShen Jianping static int smi240_regmap_spi_read(void *context, const void *reg_buf, 183*99918e78SShen Jianping size_t reg_size, void *val_buf, 184*99918e78SShen Jianping size_t val_size) 185*99918e78SShen Jianping { 186*99918e78SShen Jianping int ret; 187*99918e78SShen Jianping u32 request, response; 188*99918e78SShen Jianping u16 *val = val_buf; 189*99918e78SShen Jianping struct spi_device *spi = context; 190*99918e78SShen Jianping struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); 191*99918e78SShen Jianping struct smi240_data *iio_priv_data = iio_priv(indio_dev); 192*99918e78SShen Jianping 193*99918e78SShen Jianping if (reg_size != 1 || val_size != 2) 194*99918e78SShen Jianping return -EINVAL; 195*99918e78SShen Jianping 196*99918e78SShen Jianping request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID); 197*99918e78SShen Jianping request |= FIELD_PREP(SMI240_WRITE_CAP_BIT_MASK, iio_priv_data->capture); 198*99918e78SShen Jianping request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, *(u8 *)reg_buf); 199*99918e78SShen Jianping request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY); 200*99918e78SShen Jianping 201*99918e78SShen Jianping iio_priv_data->spi_buf = cpu_to_be32(request); 202*99918e78SShen Jianping 203*99918e78SShen Jianping /* 204*99918e78SShen Jianping * SMI240 module consists of a 32Bit Out Of Frame (OOF) 205*99918e78SShen Jianping * SPI protocol, where the slave interface responds to 206*99918e78SShen Jianping * the Master request in the next frame. 207*99918e78SShen Jianping * CS signal must toggle (> 700 ns) between the frames. 208*99918e78SShen Jianping */ 209*99918e78SShen Jianping ret = spi_write(spi, &iio_priv_data->spi_buf, sizeof(request)); 210*99918e78SShen Jianping if (ret) 211*99918e78SShen Jianping return ret; 212*99918e78SShen Jianping 213*99918e78SShen Jianping ret = spi_read(spi, &iio_priv_data->spi_buf, sizeof(response)); 214*99918e78SShen Jianping if (ret) 215*99918e78SShen Jianping return ret; 216*99918e78SShen Jianping 217*99918e78SShen Jianping response = be32_to_cpu(iio_priv_data->spi_buf); 218*99918e78SShen Jianping 219*99918e78SShen Jianping if (!smi240_sensor_data_is_valid(response)) 220*99918e78SShen Jianping return -EIO; 221*99918e78SShen Jianping 222*99918e78SShen Jianping *val = FIELD_GET(SMI240_READ_DATA_MASK, response); 223*99918e78SShen Jianping 224*99918e78SShen Jianping return 0; 225*99918e78SShen Jianping } 226*99918e78SShen Jianping 227*99918e78SShen Jianping static int smi240_regmap_spi_write(void *context, const void *data, 228*99918e78SShen Jianping size_t count) 229*99918e78SShen Jianping { 230*99918e78SShen Jianping u8 reg_addr; 231*99918e78SShen Jianping u16 reg_data; 232*99918e78SShen Jianping u32 request; 233*99918e78SShen Jianping const u8 *data_ptr = data; 234*99918e78SShen Jianping struct spi_device *spi = context; 235*99918e78SShen Jianping struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev); 236*99918e78SShen Jianping struct smi240_data *iio_priv_data = iio_priv(indio_dev); 237*99918e78SShen Jianping 238*99918e78SShen Jianping if (count < 2) 239*99918e78SShen Jianping return -EINVAL; 240*99918e78SShen Jianping 241*99918e78SShen Jianping reg_addr = data_ptr[0]; 242*99918e78SShen Jianping memcpy(®_data, &data_ptr[1], sizeof(reg_data)); 243*99918e78SShen Jianping 244*99918e78SShen Jianping request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID); 245*99918e78SShen Jianping request |= FIELD_PREP(SMI240_WRITE_BIT_MASK, 1); 246*99918e78SShen Jianping request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, reg_addr); 247*99918e78SShen Jianping request |= FIELD_PREP(SMI240_WRITE_DATA_MASK, reg_data); 248*99918e78SShen Jianping request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY); 249*99918e78SShen Jianping 250*99918e78SShen Jianping iio_priv_data->spi_buf = cpu_to_be32(request); 251*99918e78SShen Jianping 252*99918e78SShen Jianping return spi_write(spi, &iio_priv_data->spi_buf, sizeof(request)); 253*99918e78SShen Jianping } 254*99918e78SShen Jianping 255*99918e78SShen Jianping static const struct regmap_bus smi240_regmap_bus = { 256*99918e78SShen Jianping .read = smi240_regmap_spi_read, 257*99918e78SShen Jianping .write = smi240_regmap_spi_write, 258*99918e78SShen Jianping }; 259*99918e78SShen Jianping 260*99918e78SShen Jianping static const struct regmap_config smi240_regmap_config = { 261*99918e78SShen Jianping .reg_bits = 8, 262*99918e78SShen Jianping .val_bits = 16, 263*99918e78SShen Jianping .val_format_endian = REGMAP_ENDIAN_NATIVE, 264*99918e78SShen Jianping }; 265*99918e78SShen Jianping 266*99918e78SShen Jianping static int smi240_soft_reset(struct smi240_data *data) 267*99918e78SShen Jianping { 268*99918e78SShen Jianping int ret; 269*99918e78SShen Jianping 270*99918e78SShen Jianping ret = regmap_write(data->regmap, SMI240_CMD_REG, SMI240_SOFT_RESET_CMD); 271*99918e78SShen Jianping if (ret) 272*99918e78SShen Jianping return ret; 273*99918e78SShen Jianping fsleep(SMI240_DIGITAL_STARTUP_DELAY_US); 274*99918e78SShen Jianping 275*99918e78SShen Jianping return 0; 276*99918e78SShen Jianping } 277*99918e78SShen Jianping 278*99918e78SShen Jianping static int smi240_soft_config(struct smi240_data *data) 279*99918e78SShen Jianping { 280*99918e78SShen Jianping int ret; 281*99918e78SShen Jianping u8 acc_bw, gyr_bw; 282*99918e78SShen Jianping u16 request; 283*99918e78SShen Jianping 284*99918e78SShen Jianping switch (data->accel_filter_freq) { 285*99918e78SShen Jianping case SMI240_LOW_BANDWIDTH_HZ: 286*99918e78SShen Jianping acc_bw = 0x1; 287*99918e78SShen Jianping break; 288*99918e78SShen Jianping case SMI240_HIGH_BANDWIDTH_HZ: 289*99918e78SShen Jianping acc_bw = 0x0; 290*99918e78SShen Jianping break; 291*99918e78SShen Jianping default: 292*99918e78SShen Jianping return -EINVAL; 293*99918e78SShen Jianping } 294*99918e78SShen Jianping 295*99918e78SShen Jianping switch (data->anglvel_filter_freq) { 296*99918e78SShen Jianping case SMI240_LOW_BANDWIDTH_HZ: 297*99918e78SShen Jianping gyr_bw = 0x1; 298*99918e78SShen Jianping break; 299*99918e78SShen Jianping case SMI240_HIGH_BANDWIDTH_HZ: 300*99918e78SShen Jianping gyr_bw = 0x0; 301*99918e78SShen Jianping break; 302*99918e78SShen Jianping default: 303*99918e78SShen Jianping return -EINVAL; 304*99918e78SShen Jianping } 305*99918e78SShen Jianping 306*99918e78SShen Jianping request = FIELD_PREP(SMI240_SOFT_CONFIG_EOC_MASK, 1); 307*99918e78SShen Jianping request |= FIELD_PREP(SMI240_SOFT_CONFIG_GYR_BW_MASK, gyr_bw); 308*99918e78SShen Jianping request |= FIELD_PREP(SMI240_SOFT_CONFIG_ACC_BW_MASK, acc_bw); 309*99918e78SShen Jianping request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_AUTO_MASK, 1); 310*99918e78SShen Jianping request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_REP_MASK, 311*99918e78SShen Jianping data->built_in_self_test_count - 1); 312*99918e78SShen Jianping 313*99918e78SShen Jianping ret = regmap_write(data->regmap, SMI240_SOFT_CONFIG_REG, request); 314*99918e78SShen Jianping if (ret) 315*99918e78SShen Jianping return ret; 316*99918e78SShen Jianping 317*99918e78SShen Jianping fsleep(SMI240_MECH_STARTUP_DELAY_US + 318*99918e78SShen Jianping data->built_in_self_test_count * SMI240_BITE_SEQUENCE_DELAY_US + 319*99918e78SShen Jianping SMI240_FILTER_FLUSH_DELAY_US); 320*99918e78SShen Jianping 321*99918e78SShen Jianping return 0; 322*99918e78SShen Jianping } 323*99918e78SShen Jianping 324*99918e78SShen Jianping static int smi240_get_low_pass_filter_freq(struct smi240_data *data, 325*99918e78SShen Jianping int chan_type, int *val) 326*99918e78SShen Jianping { 327*99918e78SShen Jianping switch (chan_type) { 328*99918e78SShen Jianping case IIO_ACCEL: 329*99918e78SShen Jianping *val = data->accel_filter_freq; 330*99918e78SShen Jianping return 0; 331*99918e78SShen Jianping case IIO_ANGL_VEL: 332*99918e78SShen Jianping *val = data->anglvel_filter_freq; 333*99918e78SShen Jianping return 0; 334*99918e78SShen Jianping default: 335*99918e78SShen Jianping return -EINVAL; 336*99918e78SShen Jianping } 337*99918e78SShen Jianping } 338*99918e78SShen Jianping 339*99918e78SShen Jianping static int smi240_get_data(struct smi240_data *data, int chan_type, int axis, 340*99918e78SShen Jianping int *val) 341*99918e78SShen Jianping { 342*99918e78SShen Jianping u8 reg; 343*99918e78SShen Jianping int ret, sample; 344*99918e78SShen Jianping 345*99918e78SShen Jianping switch (chan_type) { 346*99918e78SShen Jianping case IIO_TEMP: 347*99918e78SShen Jianping reg = SMI240_TEMP_CUR_REG; 348*99918e78SShen Jianping break; 349*99918e78SShen Jianping case IIO_ACCEL: 350*99918e78SShen Jianping reg = SMI240_ACCEL_X_CUR_REG + (axis - IIO_MOD_X); 351*99918e78SShen Jianping break; 352*99918e78SShen Jianping case IIO_ANGL_VEL: 353*99918e78SShen Jianping reg = SMI240_GYRO_X_CUR_REG + (axis - IIO_MOD_X); 354*99918e78SShen Jianping break; 355*99918e78SShen Jianping default: 356*99918e78SShen Jianping return -EINVAL; 357*99918e78SShen Jianping } 358*99918e78SShen Jianping 359*99918e78SShen Jianping ret = regmap_read(data->regmap, reg, &sample); 360*99918e78SShen Jianping if (ret) 361*99918e78SShen Jianping return ret; 362*99918e78SShen Jianping 363*99918e78SShen Jianping *val = sign_extend32(sample, 15); 364*99918e78SShen Jianping 365*99918e78SShen Jianping return 0; 366*99918e78SShen Jianping } 367*99918e78SShen Jianping 368*99918e78SShen Jianping static irqreturn_t smi240_trigger_handler(int irq, void *p) 369*99918e78SShen Jianping { 370*99918e78SShen Jianping struct iio_poll_func *pf = p; 371*99918e78SShen Jianping struct iio_dev *indio_dev = pf->indio_dev; 372*99918e78SShen Jianping struct smi240_data *data = iio_priv(indio_dev); 373*99918e78SShen Jianping int base = SMI240_DATA_CAP_FIRST_REG, i = 0; 374*99918e78SShen Jianping int ret, chan, sample; 375*99918e78SShen Jianping 376*99918e78SShen Jianping data->capture = SMI240_CAPTURE_ON; 377*99918e78SShen Jianping 378*99918e78SShen Jianping iio_for_each_active_channel(indio_dev, chan) { 379*99918e78SShen Jianping ret = regmap_read(data->regmap, base + chan, &sample); 380*99918e78SShen Jianping data->capture = SMI240_CAPTURE_OFF; 381*99918e78SShen Jianping if (ret) 382*99918e78SShen Jianping goto out; 383*99918e78SShen Jianping data->buf[i++] = sample; 384*99918e78SShen Jianping } 385*99918e78SShen Jianping 386*99918e78SShen Jianping iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp); 387*99918e78SShen Jianping 388*99918e78SShen Jianping out: 389*99918e78SShen Jianping iio_trigger_notify_done(indio_dev->trig); 390*99918e78SShen Jianping return IRQ_HANDLED; 391*99918e78SShen Jianping } 392*99918e78SShen Jianping 393*99918e78SShen Jianping static int smi240_read_avail(struct iio_dev *indio_dev, 394*99918e78SShen Jianping struct iio_chan_spec const *chan, const int **vals, 395*99918e78SShen Jianping int *type, int *length, long mask) 396*99918e78SShen Jianping { 397*99918e78SShen Jianping switch (mask) { 398*99918e78SShen Jianping case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 399*99918e78SShen Jianping *vals = smi240_low_pass_freqs; 400*99918e78SShen Jianping *length = ARRAY_SIZE(smi240_low_pass_freqs); 401*99918e78SShen Jianping *type = IIO_VAL_INT; 402*99918e78SShen Jianping return IIO_AVAIL_LIST; 403*99918e78SShen Jianping default: 404*99918e78SShen Jianping return -EINVAL; 405*99918e78SShen Jianping } 406*99918e78SShen Jianping } 407*99918e78SShen Jianping 408*99918e78SShen Jianping static int smi240_read_raw(struct iio_dev *indio_dev, 409*99918e78SShen Jianping struct iio_chan_spec const *chan, int *val, 410*99918e78SShen Jianping int *val2, long mask) 411*99918e78SShen Jianping { 412*99918e78SShen Jianping int ret; 413*99918e78SShen Jianping struct smi240_data *data = iio_priv(indio_dev); 414*99918e78SShen Jianping 415*99918e78SShen Jianping switch (mask) { 416*99918e78SShen Jianping case IIO_CHAN_INFO_RAW: 417*99918e78SShen Jianping ret = iio_device_claim_direct_mode(indio_dev); 418*99918e78SShen Jianping if (ret) 419*99918e78SShen Jianping return ret; 420*99918e78SShen Jianping ret = smi240_get_data(data, chan->type, chan->channel2, val); 421*99918e78SShen Jianping iio_device_release_direct_mode(indio_dev); 422*99918e78SShen Jianping if (ret) 423*99918e78SShen Jianping return ret; 424*99918e78SShen Jianping return IIO_VAL_INT; 425*99918e78SShen Jianping 426*99918e78SShen Jianping case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 427*99918e78SShen Jianping ret = smi240_get_low_pass_filter_freq(data, chan->type, val); 428*99918e78SShen Jianping if (ret) 429*99918e78SShen Jianping return ret; 430*99918e78SShen Jianping return IIO_VAL_INT; 431*99918e78SShen Jianping 432*99918e78SShen Jianping case IIO_CHAN_INFO_SCALE: 433*99918e78SShen Jianping switch (chan->type) { 434*99918e78SShen Jianping case IIO_TEMP: 435*99918e78SShen Jianping *val = SMI240_TEMP_SCALE / GIGA; 436*99918e78SShen Jianping *val2 = SMI240_TEMP_SCALE % GIGA; 437*99918e78SShen Jianping return IIO_VAL_INT_PLUS_NANO; 438*99918e78SShen Jianping case IIO_ACCEL: 439*99918e78SShen Jianping *val = 0; 440*99918e78SShen Jianping *val2 = SMI240_ACCEL_SCALE; 441*99918e78SShen Jianping return IIO_VAL_INT_PLUS_MICRO; 442*99918e78SShen Jianping case IIO_ANGL_VEL: 443*99918e78SShen Jianping *val = 0; 444*99918e78SShen Jianping *val2 = SMI240_GYRO_SCALE; 445*99918e78SShen Jianping return IIO_VAL_INT_PLUS_MICRO; 446*99918e78SShen Jianping default: 447*99918e78SShen Jianping return -EINVAL; 448*99918e78SShen Jianping } 449*99918e78SShen Jianping 450*99918e78SShen Jianping case IIO_CHAN_INFO_OFFSET: 451*99918e78SShen Jianping if (chan->type == IIO_TEMP) { 452*99918e78SShen Jianping *val = SMI240_TEMP_OFFSET; 453*99918e78SShen Jianping return IIO_VAL_INT; 454*99918e78SShen Jianping } else { 455*99918e78SShen Jianping return -EINVAL; 456*99918e78SShen Jianping } 457*99918e78SShen Jianping 458*99918e78SShen Jianping default: 459*99918e78SShen Jianping return -EINVAL; 460*99918e78SShen Jianping } 461*99918e78SShen Jianping } 462*99918e78SShen Jianping 463*99918e78SShen Jianping static int smi240_write_raw(struct iio_dev *indio_dev, 464*99918e78SShen Jianping struct iio_chan_spec const *chan, int val, int val2, 465*99918e78SShen Jianping long mask) 466*99918e78SShen Jianping { 467*99918e78SShen Jianping int ret, i; 468*99918e78SShen Jianping struct smi240_data *data = iio_priv(indio_dev); 469*99918e78SShen Jianping 470*99918e78SShen Jianping switch (mask) { 471*99918e78SShen Jianping case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 472*99918e78SShen Jianping for (i = 0; i < ARRAY_SIZE(smi240_low_pass_freqs); i++) { 473*99918e78SShen Jianping if (val == smi240_low_pass_freqs[i]) 474*99918e78SShen Jianping break; 475*99918e78SShen Jianping } 476*99918e78SShen Jianping 477*99918e78SShen Jianping if (i == ARRAY_SIZE(smi240_low_pass_freqs)) 478*99918e78SShen Jianping return -EINVAL; 479*99918e78SShen Jianping 480*99918e78SShen Jianping switch (chan->type) { 481*99918e78SShen Jianping case IIO_ACCEL: 482*99918e78SShen Jianping data->accel_filter_freq = val; 483*99918e78SShen Jianping break; 484*99918e78SShen Jianping case IIO_ANGL_VEL: 485*99918e78SShen Jianping data->anglvel_filter_freq = val; 486*99918e78SShen Jianping break; 487*99918e78SShen Jianping default: 488*99918e78SShen Jianping return -EINVAL; 489*99918e78SShen Jianping } 490*99918e78SShen Jianping break; 491*99918e78SShen Jianping default: 492*99918e78SShen Jianping return -EINVAL; 493*99918e78SShen Jianping } 494*99918e78SShen Jianping 495*99918e78SShen Jianping /* Write access to soft config is locked until hard/soft reset */ 496*99918e78SShen Jianping ret = smi240_soft_reset(data); 497*99918e78SShen Jianping if (ret) 498*99918e78SShen Jianping return ret; 499*99918e78SShen Jianping 500*99918e78SShen Jianping return smi240_soft_config(data); 501*99918e78SShen Jianping } 502*99918e78SShen Jianping 503*99918e78SShen Jianping static int smi240_write_raw_get_fmt(struct iio_dev *indio_dev, 504*99918e78SShen Jianping struct iio_chan_spec const *chan, long info) 505*99918e78SShen Jianping { 506*99918e78SShen Jianping switch (info) { 507*99918e78SShen Jianping case IIO_CHAN_INFO_SCALE: 508*99918e78SShen Jianping switch (chan->type) { 509*99918e78SShen Jianping case IIO_TEMP: 510*99918e78SShen Jianping return IIO_VAL_INT_PLUS_NANO; 511*99918e78SShen Jianping default: 512*99918e78SShen Jianping return IIO_VAL_INT_PLUS_MICRO; 513*99918e78SShen Jianping } 514*99918e78SShen Jianping default: 515*99918e78SShen Jianping return IIO_VAL_INT_PLUS_MICRO; 516*99918e78SShen Jianping } 517*99918e78SShen Jianping } 518*99918e78SShen Jianping 519*99918e78SShen Jianping static int smi240_init(struct smi240_data *data) 520*99918e78SShen Jianping { 521*99918e78SShen Jianping int ret; 522*99918e78SShen Jianping 523*99918e78SShen Jianping data->accel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ; 524*99918e78SShen Jianping data->anglvel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ; 525*99918e78SShen Jianping data->built_in_self_test_count = SMI240_BUILT_IN_SELF_TEST_COUNT; 526*99918e78SShen Jianping 527*99918e78SShen Jianping ret = smi240_soft_reset(data); 528*99918e78SShen Jianping if (ret) 529*99918e78SShen Jianping return ret; 530*99918e78SShen Jianping 531*99918e78SShen Jianping return smi240_soft_config(data); 532*99918e78SShen Jianping } 533*99918e78SShen Jianping 534*99918e78SShen Jianping static const struct iio_info smi240_info = { 535*99918e78SShen Jianping .read_avail = smi240_read_avail, 536*99918e78SShen Jianping .read_raw = smi240_read_raw, 537*99918e78SShen Jianping .write_raw = smi240_write_raw, 538*99918e78SShen Jianping .write_raw_get_fmt = smi240_write_raw_get_fmt, 539*99918e78SShen Jianping }; 540*99918e78SShen Jianping 541*99918e78SShen Jianping static int smi240_probe(struct spi_device *spi) 542*99918e78SShen Jianping { 543*99918e78SShen Jianping struct device *dev = &spi->dev; 544*99918e78SShen Jianping struct iio_dev *indio_dev; 545*99918e78SShen Jianping struct regmap *regmap; 546*99918e78SShen Jianping struct smi240_data *data; 547*99918e78SShen Jianping int ret, response; 548*99918e78SShen Jianping 549*99918e78SShen Jianping indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 550*99918e78SShen Jianping if (!indio_dev) 551*99918e78SShen Jianping return -ENOMEM; 552*99918e78SShen Jianping 553*99918e78SShen Jianping regmap = devm_regmap_init(dev, &smi240_regmap_bus, dev, 554*99918e78SShen Jianping &smi240_regmap_config); 555*99918e78SShen Jianping if (IS_ERR(regmap)) 556*99918e78SShen Jianping return dev_err_probe(dev, PTR_ERR(regmap), 557*99918e78SShen Jianping "Failed to initialize SPI Regmap\n"); 558*99918e78SShen Jianping 559*99918e78SShen Jianping data = iio_priv(indio_dev); 560*99918e78SShen Jianping dev_set_drvdata(dev, indio_dev); 561*99918e78SShen Jianping data->regmap = regmap; 562*99918e78SShen Jianping data->capture = SMI240_CAPTURE_OFF; 563*99918e78SShen Jianping 564*99918e78SShen Jianping ret = regmap_read(data->regmap, SMI240_CHIP_ID_REG, &response); 565*99918e78SShen Jianping if (ret) 566*99918e78SShen Jianping return dev_err_probe(dev, ret, "Read chip id failed\n"); 567*99918e78SShen Jianping 568*99918e78SShen Jianping if (response != SMI240_CHIP_ID) 569*99918e78SShen Jianping dev_info(dev, "Unknown chip id: 0x%04x\n", response); 570*99918e78SShen Jianping 571*99918e78SShen Jianping ret = smi240_init(data); 572*99918e78SShen Jianping if (ret) 573*99918e78SShen Jianping return dev_err_probe(dev, ret, 574*99918e78SShen Jianping "Device initialization failed\n"); 575*99918e78SShen Jianping 576*99918e78SShen Jianping indio_dev->channels = smi240_channels; 577*99918e78SShen Jianping indio_dev->num_channels = ARRAY_SIZE(smi240_channels); 578*99918e78SShen Jianping indio_dev->name = "smi240"; 579*99918e78SShen Jianping indio_dev->modes = INDIO_DIRECT_MODE; 580*99918e78SShen Jianping indio_dev->info = &smi240_info; 581*99918e78SShen Jianping 582*99918e78SShen Jianping ret = devm_iio_triggered_buffer_setup(dev, indio_dev, 583*99918e78SShen Jianping iio_pollfunc_store_time, 584*99918e78SShen Jianping smi240_trigger_handler, NULL); 585*99918e78SShen Jianping if (ret) 586*99918e78SShen Jianping return dev_err_probe(dev, ret, 587*99918e78SShen Jianping "Setup triggered buffer failed\n"); 588*99918e78SShen Jianping 589*99918e78SShen Jianping ret = devm_iio_device_register(dev, indio_dev); 590*99918e78SShen Jianping if (ret) 591*99918e78SShen Jianping return dev_err_probe(dev, ret, "Register IIO device failed\n"); 592*99918e78SShen Jianping 593*99918e78SShen Jianping return 0; 594*99918e78SShen Jianping } 595*99918e78SShen Jianping 596*99918e78SShen Jianping static const struct spi_device_id smi240_spi_id[] = { 597*99918e78SShen Jianping { "smi240" }, 598*99918e78SShen Jianping { } 599*99918e78SShen Jianping }; 600*99918e78SShen Jianping MODULE_DEVICE_TABLE(spi, smi240_spi_id); 601*99918e78SShen Jianping 602*99918e78SShen Jianping static const struct of_device_id smi240_of_match[] = { 603*99918e78SShen Jianping { .compatible = "bosch,smi240" }, 604*99918e78SShen Jianping { } 605*99918e78SShen Jianping }; 606*99918e78SShen Jianping MODULE_DEVICE_TABLE(of, smi240_of_match); 607*99918e78SShen Jianping 608*99918e78SShen Jianping static struct spi_driver smi240_spi_driver = { 609*99918e78SShen Jianping .probe = smi240_probe, 610*99918e78SShen Jianping .id_table = smi240_spi_id, 611*99918e78SShen Jianping .driver = { 612*99918e78SShen Jianping .of_match_table = smi240_of_match, 613*99918e78SShen Jianping .name = "smi240", 614*99918e78SShen Jianping }, 615*99918e78SShen Jianping }; 616*99918e78SShen Jianping module_spi_driver(smi240_spi_driver); 617*99918e78SShen Jianping 618*99918e78SShen Jianping MODULE_AUTHOR("Markus Lochmann <markus.lochmann@de.bosch.com>"); 619*99918e78SShen Jianping MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>"); 620*99918e78SShen Jianping MODULE_DESCRIPTION("Bosch SMI240 SPI driver"); 621*99918e78SShen Jianping MODULE_LICENSE("Dual BSD/GPL"); 622