1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * BMA220 Digital triaxial acceleration sensor driver 4 * 5 * Copyright (c) 2016,2020 Intel Corporation. 6 */ 7 8 #include <linux/bits.h> 9 #include <linux/kernel.h> 10 #include <linux/mod_devicetable.h> 11 #include <linux/module.h> 12 #include <linux/spi/spi.h> 13 14 #include <linux/iio/buffer.h> 15 #include <linux/iio/iio.h> 16 #include <linux/iio/sysfs.h> 17 #include <linux/iio/trigger_consumer.h> 18 #include <linux/iio/triggered_buffer.h> 19 20 #define BMA220_REG_ID 0x00 21 #define BMA220_REG_ACCEL_X 0x02 22 #define BMA220_REG_ACCEL_Y 0x03 23 #define BMA220_REG_ACCEL_Z 0x04 24 #define BMA220_REG_RANGE 0x11 25 #define BMA220_REG_SUSPEND 0x18 26 27 #define BMA220_CHIP_ID 0xDD 28 #define BMA220_READ_MASK BIT(7) 29 #define BMA220_RANGE_MASK GENMASK(1, 0) 30 #define BMA220_SUSPEND_SLEEP 0xFF 31 #define BMA220_SUSPEND_WAKE 0x00 32 33 #define BMA220_DEVICE_NAME "bma220" 34 35 #define BMA220_ACCEL_CHANNEL(index, reg, axis) { \ 36 .type = IIO_ACCEL, \ 37 .address = reg, \ 38 .modified = 1, \ 39 .channel2 = IIO_MOD_##axis, \ 40 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 41 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 42 .scan_index = index, \ 43 .scan_type = { \ 44 .sign = 's', \ 45 .realbits = 6, \ 46 .storagebits = 8, \ 47 .shift = 2, \ 48 .endianness = IIO_CPU, \ 49 }, \ 50 } 51 52 enum bma220_axis { 53 AXIS_X, 54 AXIS_Y, 55 AXIS_Z, 56 }; 57 58 static const int bma220_scale_table[][2] = { 59 {0, 623000}, {1, 248000}, {2, 491000}, {4, 983000}, 60 }; 61 62 struct bma220_data { 63 struct spi_device *spi_device; 64 struct mutex lock; 65 struct { 66 s8 chans[3]; 67 /* Ensure timestamp is naturally aligned. */ 68 s64 timestamp __aligned(8); 69 } scan; 70 u8 tx_buf[2] __aligned(IIO_DMA_MINALIGN); 71 }; 72 73 static const struct iio_chan_spec bma220_channels[] = { 74 BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X), 75 BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y), 76 BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z), 77 IIO_CHAN_SOFT_TIMESTAMP(3), 78 }; 79 80 static inline int bma220_read_reg(struct spi_device *spi, u8 reg) 81 { 82 return spi_w8r8(spi, reg | BMA220_READ_MASK); 83 } 84 85 static const unsigned long bma220_accel_scan_masks[] = { 86 BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z), 87 0 88 }; 89 90 static irqreturn_t bma220_trigger_handler(int irq, void *p) 91 { 92 int ret; 93 struct iio_poll_func *pf = p; 94 struct iio_dev *indio_dev = pf->indio_dev; 95 struct bma220_data *data = iio_priv(indio_dev); 96 struct spi_device *spi = data->spi_device; 97 98 mutex_lock(&data->lock); 99 data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK; 100 ret = spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans, 101 ARRAY_SIZE(bma220_channels) - 1); 102 if (ret < 0) 103 goto err; 104 105 iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, 106 pf->timestamp); 107 err: 108 mutex_unlock(&data->lock); 109 iio_trigger_notify_done(indio_dev->trig); 110 111 return IRQ_HANDLED; 112 } 113 114 static int bma220_read_raw(struct iio_dev *indio_dev, 115 struct iio_chan_spec const *chan, 116 int *val, int *val2, long mask) 117 { 118 int ret; 119 u8 range_idx; 120 struct bma220_data *data = iio_priv(indio_dev); 121 122 switch (mask) { 123 case IIO_CHAN_INFO_RAW: 124 ret = bma220_read_reg(data->spi_device, chan->address); 125 if (ret < 0) 126 return -EINVAL; 127 *val = sign_extend32(ret >> chan->scan_type.shift, 128 chan->scan_type.realbits - 1); 129 return IIO_VAL_INT; 130 case IIO_CHAN_INFO_SCALE: 131 ret = bma220_read_reg(data->spi_device, BMA220_REG_RANGE); 132 if (ret < 0) 133 return ret; 134 range_idx = ret & BMA220_RANGE_MASK; 135 *val = bma220_scale_table[range_idx][0]; 136 *val2 = bma220_scale_table[range_idx][1]; 137 return IIO_VAL_INT_PLUS_MICRO; 138 } 139 140 return -EINVAL; 141 } 142 143 static int bma220_write_raw(struct iio_dev *indio_dev, 144 struct iio_chan_spec const *chan, 145 int val, int val2, long mask) 146 { 147 int i; 148 int ret; 149 int index = -1; 150 struct bma220_data *data = iio_priv(indio_dev); 151 152 switch (mask) { 153 case IIO_CHAN_INFO_SCALE: 154 for (i = 0; i < ARRAY_SIZE(bma220_scale_table); i++) 155 if (val == bma220_scale_table[i][0] && 156 val2 == bma220_scale_table[i][1]) { 157 index = i; 158 break; 159 } 160 if (index < 0) 161 return -EINVAL; 162 163 mutex_lock(&data->lock); 164 data->tx_buf[0] = BMA220_REG_RANGE; 165 data->tx_buf[1] = index; 166 ret = spi_write(data->spi_device, data->tx_buf, 167 sizeof(data->tx_buf)); 168 if (ret < 0) 169 dev_err(&data->spi_device->dev, 170 "failed to set measurement range\n"); 171 mutex_unlock(&data->lock); 172 173 return 0; 174 } 175 176 return -EINVAL; 177 } 178 179 static int bma220_read_avail(struct iio_dev *indio_dev, 180 struct iio_chan_spec const *chan, 181 const int **vals, int *type, int *length, 182 long mask) 183 { 184 switch (mask) { 185 case IIO_CHAN_INFO_SCALE: 186 *vals = (int *)bma220_scale_table; 187 *type = IIO_VAL_INT_PLUS_MICRO; 188 *length = ARRAY_SIZE(bma220_scale_table) * 2; 189 return IIO_AVAIL_LIST; 190 default: 191 return -EINVAL; 192 } 193 } 194 195 static const struct iio_info bma220_info = { 196 .read_raw = bma220_read_raw, 197 .write_raw = bma220_write_raw, 198 .read_avail = bma220_read_avail, 199 }; 200 201 static int bma220_init(struct spi_device *spi) 202 { 203 int ret; 204 205 ret = bma220_read_reg(spi, BMA220_REG_ID); 206 if (ret != BMA220_CHIP_ID) 207 return -ENODEV; 208 209 /* Make sure the chip is powered on */ 210 ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); 211 if (ret == BMA220_SUSPEND_WAKE) 212 ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); 213 if (ret < 0) 214 return ret; 215 if (ret == BMA220_SUSPEND_WAKE) 216 return -EBUSY; 217 218 return 0; 219 } 220 221 static int bma220_power(struct spi_device *spi, bool up) 222 { 223 int i, ret; 224 225 /** 226 * The chip can be suspended/woken up by a simple register read. 227 * So, we need up to 2 register reads of the suspend register 228 * to make sure that the device is in the desired state. 229 */ 230 for (i = 0; i < 2; i++) { 231 ret = bma220_read_reg(spi, BMA220_REG_SUSPEND); 232 if (ret < 0) 233 return ret; 234 235 if (up && ret == BMA220_SUSPEND_SLEEP) 236 return 0; 237 238 if (!up && ret == BMA220_SUSPEND_WAKE) 239 return 0; 240 } 241 242 return -EBUSY; 243 } 244 245 static void bma220_deinit(void *spi) 246 { 247 bma220_power(spi, false); 248 } 249 250 static int bma220_probe(struct spi_device *spi) 251 { 252 int ret; 253 struct iio_dev *indio_dev; 254 struct bma220_data *data; 255 256 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data)); 257 if (!indio_dev) { 258 dev_err(&spi->dev, "iio allocation failed!\n"); 259 return -ENOMEM; 260 } 261 262 data = iio_priv(indio_dev); 263 data->spi_device = spi; 264 mutex_init(&data->lock); 265 266 indio_dev->info = &bma220_info; 267 indio_dev->name = BMA220_DEVICE_NAME; 268 indio_dev->modes = INDIO_DIRECT_MODE; 269 indio_dev->channels = bma220_channels; 270 indio_dev->num_channels = ARRAY_SIZE(bma220_channels); 271 indio_dev->available_scan_masks = bma220_accel_scan_masks; 272 273 ret = bma220_init(data->spi_device); 274 if (ret) 275 return ret; 276 277 ret = devm_add_action_or_reset(&spi->dev, bma220_deinit, spi); 278 if (ret) 279 return ret; 280 281 ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, 282 iio_pollfunc_store_time, 283 bma220_trigger_handler, NULL); 284 if (ret < 0) { 285 dev_err(&spi->dev, "iio triggered buffer setup failed\n"); 286 return ret; 287 } 288 289 return devm_iio_device_register(&spi->dev, indio_dev); 290 } 291 292 static int bma220_suspend(struct device *dev) 293 { 294 struct spi_device *spi = to_spi_device(dev); 295 296 return bma220_power(spi, false); 297 } 298 299 static int bma220_resume(struct device *dev) 300 { 301 struct spi_device *spi = to_spi_device(dev); 302 303 return bma220_power(spi, true); 304 } 305 static DEFINE_SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume); 306 307 static const struct spi_device_id bma220_spi_id[] = { 308 {"bma220", 0}, 309 {} 310 }; 311 312 static const struct acpi_device_id bma220_acpi_id[] = { 313 {"BMA0220", 0}, 314 {} 315 }; 316 MODULE_DEVICE_TABLE(spi, bma220_spi_id); 317 318 static struct spi_driver bma220_driver = { 319 .driver = { 320 .name = "bma220_spi", 321 .pm = pm_sleep_ptr(&bma220_pm_ops), 322 .acpi_match_table = bma220_acpi_id, 323 }, 324 .probe = bma220_probe, 325 .id_table = bma220_spi_id, 326 }; 327 module_spi_driver(bma220_driver); 328 329 MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); 330 MODULE_DESCRIPTION("BMA220 acceleration sensor driver"); 331 MODULE_LICENSE("GPL v2"); 332