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.

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