709 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ADXRS290 SPI Gyroscope Driver4 *5 * Copyright (C) 2020 Nishant Malpani <nish.malpani25@gmail.com>6 * Copyright (C) 2020 Analog Devices, Inc.7 */8 9#include <linux/bitfield.h>10#include <linux/bitops.h>11#include <linux/delay.h>12#include <linux/device.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/spi/spi.h>16 17#include <linux/iio/buffer.h>18#include <linux/iio/iio.h>19#include <linux/iio/sysfs.h>20#include <linux/iio/trigger.h>21#include <linux/iio/triggered_buffer.h>22#include <linux/iio/trigger_consumer.h>23 24#define ADXRS290_ADI_ID 0xAD25#define ADXRS290_MEMS_ID 0x1D26#define ADXRS290_DEV_ID 0x9227 28#define ADXRS290_REG_ADI_ID 0x0029#define ADXRS290_REG_MEMS_ID 0x0130#define ADXRS290_REG_DEV_ID 0x0231#define ADXRS290_REG_REV_ID 0x0332#define ADXRS290_REG_SN0 0x04 /* Serial Number Registers, 4 bytes */33#define ADXRS290_REG_DATAX0 0x08 /* Roll Rate o/p Data Regs, 2 bytes */34#define ADXRS290_REG_DATAY0 0x0A /* Pitch Rate o/p Data Regs, 2 bytes */35#define ADXRS290_REG_TEMP0 0x0C36#define ADXRS290_REG_POWER_CTL 0x1037#define ADXRS290_REG_FILTER 0x1138#define ADXRS290_REG_DATA_RDY 0x1239 40#define ADXRS290_READ BIT(7)41#define ADXRS290_TSM BIT(0)42#define ADXRS290_MEASUREMENT BIT(1)43#define ADXRS290_DATA_RDY_OUT BIT(0)44#define ADXRS290_SYNC_MASK GENMASK(1, 0)45#define ADXRS290_SYNC(x) FIELD_PREP(ADXRS290_SYNC_MASK, x)46#define ADXRS290_LPF_MASK GENMASK(2, 0)47#define ADXRS290_LPF(x) FIELD_PREP(ADXRS290_LPF_MASK, x)48#define ADXRS290_HPF_MASK GENMASK(7, 4)49#define ADXRS290_HPF(x) FIELD_PREP(ADXRS290_HPF_MASK, x)50 51#define ADXRS290_READ_REG(reg) (ADXRS290_READ | (reg))52 53#define ADXRS290_MAX_TRANSITION_TIME_MS 10054 55enum adxrs290_mode {56 ADXRS290_MODE_STANDBY,57 ADXRS290_MODE_MEASUREMENT,58};59 60enum adxrs290_scan_index {61 ADXRS290_IDX_X,62 ADXRS290_IDX_Y,63 ADXRS290_IDX_TEMP,64 ADXRS290_IDX_TS,65};66 67struct adxrs290_state {68 struct spi_device *spi;69 /* Serialize reads and their subsequent processing */70 struct mutex lock;71 enum adxrs290_mode mode;72 unsigned int lpf_3db_freq_idx;73 unsigned int hpf_3db_freq_idx;74 struct iio_trigger *dready_trig;75 /* Ensure correct alignment of timestamp when present */76 struct {77 s16 channels[3];78 s64 ts __aligned(8);79 } buffer;80};81 82/*83 * Available cut-off frequencies of the low pass filter in Hz.84 * The integer part and fractional part are represented separately.85 */86static const int adxrs290_lpf_3db_freq_hz_table[][2] = {87 [0] = {480, 0},88 [1] = {320, 0},89 [2] = {160, 0},90 [3] = {80, 0},91 [4] = {56, 600000},92 [5] = {40, 0},93 [6] = {28, 300000},94 [7] = {20, 0},95};96 97/*98 * Available cut-off frequencies of the high pass filter in Hz.99 * The integer part and fractional part are represented separately.100 */101static const int adxrs290_hpf_3db_freq_hz_table[][2] = {102 [0] = {0, 0},103 [1] = {0, 11000},104 [2] = {0, 22000},105 [3] = {0, 44000},106 [4] = {0, 87000},107 [5] = {0, 175000},108 [6] = {0, 350000},109 [7] = {0, 700000},110 [8] = {1, 400000},111 [9] = {2, 800000},112 [10] = {11, 300000},113};114 115static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int *val)116{117 struct adxrs290_state *st = iio_priv(indio_dev);118 int ret = 0;119 int temp;120 121 mutex_lock(&st->lock);122 temp = spi_w8r16(st->spi, cmd);123 if (temp < 0) {124 ret = temp;125 goto err_unlock;126 }127 128 *val = sign_extend32(temp, 15);129 130err_unlock:131 mutex_unlock(&st->lock);132 return ret;133}134 135static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val)136{137 const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_TEMP0);138 struct adxrs290_state *st = iio_priv(indio_dev);139 int ret = 0;140 int temp;141 142 mutex_lock(&st->lock);143 temp = spi_w8r16(st->spi, cmd);144 if (temp < 0) {145 ret = temp;146 goto err_unlock;147 }148 149 /* extract lower 12 bits temperature reading */150 *val = sign_extend32(temp, 11);151 152err_unlock:153 mutex_unlock(&st->lock);154 return ret;155}156 157static int adxrs290_get_3db_freq(struct iio_dev *indio_dev, u8 *val, u8 *val2)158{159 const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_FILTER);160 struct adxrs290_state *st = iio_priv(indio_dev);161 int ret = 0;162 short temp;163 164 mutex_lock(&st->lock);165 temp = spi_w8r8(st->spi, cmd);166 if (temp < 0) {167 ret = temp;168 goto err_unlock;169 }170 171 *val = FIELD_GET(ADXRS290_LPF_MASK, temp);172 *val2 = FIELD_GET(ADXRS290_HPF_MASK, temp);173 174err_unlock:175 mutex_unlock(&st->lock);176 return ret;177}178 179static int adxrs290_spi_write_reg(struct spi_device *spi, const u8 reg,180 const u8 val)181{182 u8 buf[2];183 184 buf[0] = reg;185 buf[1] = val;186 187 return spi_write_then_read(spi, buf, ARRAY_SIZE(buf), NULL, 0);188}189 190static int adxrs290_find_match(const int (*freq_tbl)[2], const int n,191 const int val, const int val2)192{193 int i;194 195 for (i = 0; i < n; i++) {196 if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2)197 return i;198 }199 200 return -EINVAL;201}202 203static int adxrs290_set_filter_freq(struct iio_dev *indio_dev,204 const unsigned int lpf_idx,205 const unsigned int hpf_idx)206{207 struct adxrs290_state *st = iio_priv(indio_dev);208 u8 val;209 210 val = ADXRS290_HPF(hpf_idx) | ADXRS290_LPF(lpf_idx);211 212 return adxrs290_spi_write_reg(st->spi, ADXRS290_REG_FILTER, val);213}214 215static int adxrs290_set_mode(struct iio_dev *indio_dev, enum adxrs290_mode mode)216{217 struct adxrs290_state *st = iio_priv(indio_dev);218 int val, ret;219 220 if (st->mode == mode)221 return 0;222 223 mutex_lock(&st->lock);224 225 ret = spi_w8r8(st->spi, ADXRS290_READ_REG(ADXRS290_REG_POWER_CTL));226 if (ret < 0)227 goto out_unlock;228 229 val = ret;230 231 switch (mode) {232 case ADXRS290_MODE_STANDBY:233 val &= ~ADXRS290_MEASUREMENT;234 break;235 case ADXRS290_MODE_MEASUREMENT:236 val |= ADXRS290_MEASUREMENT;237 break;238 default:239 ret = -EINVAL;240 goto out_unlock;241 }242 243 ret = adxrs290_spi_write_reg(st->spi, ADXRS290_REG_POWER_CTL, val);244 if (ret < 0) {245 dev_err(&st->spi->dev, "unable to set mode: %d\n", ret);246 goto out_unlock;247 }248 249 /* update cached mode */250 st->mode = mode;251 252out_unlock:253 mutex_unlock(&st->lock);254 return ret;255}256 257static void adxrs290_chip_off_action(void *data)258{259 struct iio_dev *indio_dev = data;260 261 adxrs290_set_mode(indio_dev, ADXRS290_MODE_STANDBY);262}263 264static int adxrs290_initial_setup(struct iio_dev *indio_dev)265{266 struct adxrs290_state *st = iio_priv(indio_dev);267 struct spi_device *spi = st->spi;268 int ret;269 270 ret = adxrs290_spi_write_reg(spi, ADXRS290_REG_POWER_CTL,271 ADXRS290_MEASUREMENT | ADXRS290_TSM);272 if (ret < 0)273 return ret;274 275 st->mode = ADXRS290_MODE_MEASUREMENT;276 277 return devm_add_action_or_reset(&spi->dev, adxrs290_chip_off_action,278 indio_dev);279}280 281static int adxrs290_read_raw(struct iio_dev *indio_dev,282 struct iio_chan_spec const *chan,283 int *val,284 int *val2,285 long mask)286{287 struct adxrs290_state *st = iio_priv(indio_dev);288 unsigned int t;289 int ret;290 291 switch (mask) {292 case IIO_CHAN_INFO_RAW:293 ret = iio_device_claim_direct_mode(indio_dev);294 if (ret)295 return ret;296 297 switch (chan->type) {298 case IIO_ANGL_VEL:299 ret = adxrs290_get_rate_data(indio_dev,300 ADXRS290_READ_REG(chan->address),301 val);302 if (ret < 0)303 break;304 305 ret = IIO_VAL_INT;306 break;307 case IIO_TEMP:308 ret = adxrs290_get_temp_data(indio_dev, val);309 if (ret < 0)310 break;311 312 ret = IIO_VAL_INT;313 break;314 default:315 ret = -EINVAL;316 break;317 }318 319 iio_device_release_direct_mode(indio_dev);320 return ret;321 case IIO_CHAN_INFO_SCALE:322 switch (chan->type) {323 case IIO_ANGL_VEL:324 /* 1 LSB = 0.005 degrees/sec */325 *val = 0;326 *val2 = 87266;327 return IIO_VAL_INT_PLUS_NANO;328 case IIO_TEMP:329 /* 1 LSB = 0.1 degrees Celsius */330 *val = 100;331 return IIO_VAL_INT;332 default:333 return -EINVAL;334 }335 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:336 switch (chan->type) {337 case IIO_ANGL_VEL:338 t = st->lpf_3db_freq_idx;339 *val = adxrs290_lpf_3db_freq_hz_table[t][0];340 *val2 = adxrs290_lpf_3db_freq_hz_table[t][1];341 return IIO_VAL_INT_PLUS_MICRO;342 default:343 return -EINVAL;344 }345 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:346 switch (chan->type) {347 case IIO_ANGL_VEL:348 t = st->hpf_3db_freq_idx;349 *val = adxrs290_hpf_3db_freq_hz_table[t][0];350 *val2 = adxrs290_hpf_3db_freq_hz_table[t][1];351 return IIO_VAL_INT_PLUS_MICRO;352 default:353 return -EINVAL;354 }355 }356 357 return -EINVAL;358}359 360static int adxrs290_write_raw(struct iio_dev *indio_dev,361 struct iio_chan_spec const *chan,362 int val,363 int val2,364 long mask)365{366 struct adxrs290_state *st = iio_priv(indio_dev);367 int ret, lpf_idx, hpf_idx;368 369 ret = iio_device_claim_direct_mode(indio_dev);370 if (ret)371 return ret;372 373 switch (mask) {374 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:375 lpf_idx = adxrs290_find_match(adxrs290_lpf_3db_freq_hz_table,376 ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table),377 val, val2);378 if (lpf_idx < 0) {379 ret = -EINVAL;380 break;381 }382 383 /* caching the updated state of the low-pass filter */384 st->lpf_3db_freq_idx = lpf_idx;385 /* retrieving the current state of the high-pass filter */386 hpf_idx = st->hpf_3db_freq_idx;387 ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx);388 break;389 390 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:391 hpf_idx = adxrs290_find_match(adxrs290_hpf_3db_freq_hz_table,392 ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table),393 val, val2);394 if (hpf_idx < 0) {395 ret = -EINVAL;396 break;397 }398 399 /* caching the updated state of the high-pass filter */400 st->hpf_3db_freq_idx = hpf_idx;401 /* retrieving the current state of the low-pass filter */402 lpf_idx = st->lpf_3db_freq_idx;403 ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx);404 break;405 406 default:407 ret = -EINVAL;408 break;409 }410 411 iio_device_release_direct_mode(indio_dev);412 return ret;413}414 415static int adxrs290_read_avail(struct iio_dev *indio_dev,416 struct iio_chan_spec const *chan,417 const int **vals, int *type, int *length,418 long mask)419{420 switch (mask) {421 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:422 *vals = (const int *)adxrs290_lpf_3db_freq_hz_table;423 *type = IIO_VAL_INT_PLUS_MICRO;424 /* Values are stored in a 2D matrix */425 *length = ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table) * 2;426 427 return IIO_AVAIL_LIST;428 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:429 *vals = (const int *)adxrs290_hpf_3db_freq_hz_table;430 *type = IIO_VAL_INT_PLUS_MICRO;431 /* Values are stored in a 2D matrix */432 *length = ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table) * 2;433 434 return IIO_AVAIL_LIST;435 default:436 return -EINVAL;437 }438}439 440static int adxrs290_reg_access_rw(struct spi_device *spi, unsigned int reg,441 unsigned int *readval)442{443 int ret;444 445 ret = spi_w8r8(spi, ADXRS290_READ_REG(reg));446 if (ret < 0)447 return ret;448 449 *readval = ret;450 451 return 0;452}453 454static int adxrs290_reg_access(struct iio_dev *indio_dev, unsigned int reg,455 unsigned int writeval, unsigned int *readval)456{457 struct adxrs290_state *st = iio_priv(indio_dev);458 459 if (readval)460 return adxrs290_reg_access_rw(st->spi, reg, readval);461 else462 return adxrs290_spi_write_reg(st->spi, reg, writeval);463}464 465static int adxrs290_data_rdy_trigger_set_state(struct iio_trigger *trig,466 bool state)467{468 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);469 struct adxrs290_state *st = iio_priv(indio_dev);470 int ret;471 u8 val;472 473 val = state ? ADXRS290_SYNC(ADXRS290_DATA_RDY_OUT) : 0;474 475 ret = adxrs290_spi_write_reg(st->spi, ADXRS290_REG_DATA_RDY, val);476 if (ret < 0)477 dev_err(&st->spi->dev, "failed to start data rdy interrupt\n");478 479 return ret;480}481 482static void adxrs290_reset_trig(struct iio_trigger *trig)483{484 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);485 int val;486 487 /*488 * Data ready interrupt is reset after a read of the data registers.489 * Here, we only read the 16b DATAY registers as that marks the end of490 * a read of the data registers and initiates a reset for the interrupt491 * line.492 */493 adxrs290_get_rate_data(indio_dev,494 ADXRS290_READ_REG(ADXRS290_REG_DATAY0), &val);495}496 497static const struct iio_trigger_ops adxrs290_trigger_ops = {498 .set_trigger_state = &adxrs290_data_rdy_trigger_set_state,499 .validate_device = &iio_trigger_validate_own_device,500 .reenable = &adxrs290_reset_trig,501};502 503static irqreturn_t adxrs290_trigger_handler(int irq, void *p)504{505 struct iio_poll_func *pf = p;506 struct iio_dev *indio_dev = pf->indio_dev;507 struct adxrs290_state *st = iio_priv(indio_dev);508 u8 tx = ADXRS290_READ_REG(ADXRS290_REG_DATAX0);509 int ret;510 511 mutex_lock(&st->lock);512 513 /* exercise a bulk data capture starting from reg DATAX0... */514 ret = spi_write_then_read(st->spi, &tx, sizeof(tx), st->buffer.channels,515 sizeof(st->buffer.channels));516 if (ret < 0)517 goto out_unlock_notify;518 519 iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,520 pf->timestamp);521 522out_unlock_notify:523 mutex_unlock(&st->lock);524 iio_trigger_notify_done(indio_dev->trig);525 526 return IRQ_HANDLED;527}528 529#define ADXRS290_ANGL_VEL_CHANNEL(reg, axis) { \530 .type = IIO_ANGL_VEL, \531 .address = reg, \532 .modified = 1, \533 .channel2 = IIO_MOD_##axis, \534 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \535 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \536 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \537 BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \538 .info_mask_shared_by_type_available = \539 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \540 BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \541 .scan_index = ADXRS290_IDX_##axis, \542 .scan_type = { \543 .sign = 's', \544 .realbits = 16, \545 .storagebits = 16, \546 .endianness = IIO_LE, \547 }, \548}549 550static const struct iio_chan_spec adxrs290_channels[] = {551 ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAX0, X),552 ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAY0, Y),553 {554 .type = IIO_TEMP,555 .address = ADXRS290_REG_TEMP0,556 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |557 BIT(IIO_CHAN_INFO_SCALE),558 .scan_index = ADXRS290_IDX_TEMP,559 .scan_type = {560 .sign = 's',561 .realbits = 12,562 .storagebits = 16,563 .endianness = IIO_LE,564 },565 },566 IIO_CHAN_SOFT_TIMESTAMP(ADXRS290_IDX_TS),567};568 569static const unsigned long adxrs290_avail_scan_masks[] = {570 BIT(ADXRS290_IDX_X) | BIT(ADXRS290_IDX_Y) | BIT(ADXRS290_IDX_TEMP),571 0572};573 574static const struct iio_info adxrs290_info = {575 .read_raw = &adxrs290_read_raw,576 .write_raw = &adxrs290_write_raw,577 .read_avail = &adxrs290_read_avail,578 .debugfs_reg_access = &adxrs290_reg_access,579};580 581static int adxrs290_probe_trigger(struct iio_dev *indio_dev)582{583 struct adxrs290_state *st = iio_priv(indio_dev);584 int ret;585 586 if (!st->spi->irq) {587 dev_info(&st->spi->dev, "no irq, using polling\n");588 return 0;589 }590 591 st->dready_trig = devm_iio_trigger_alloc(&st->spi->dev, "%s-dev%d",592 indio_dev->name,593 iio_device_id(indio_dev));594 if (!st->dready_trig)595 return -ENOMEM;596 597 st->dready_trig->ops = &adxrs290_trigger_ops;598 iio_trigger_set_drvdata(st->dready_trig, indio_dev);599 600 ret = devm_request_irq(&st->spi->dev, st->spi->irq,601 &iio_trigger_generic_data_rdy_poll,602 IRQF_ONESHOT, "adxrs290_irq", st->dready_trig);603 if (ret < 0)604 return dev_err_probe(&st->spi->dev, ret,605 "request irq %d failed\n", st->spi->irq);606 607 ret = devm_iio_trigger_register(&st->spi->dev, st->dready_trig);608 if (ret) {609 dev_err(&st->spi->dev, "iio trigger register failed\n");610 return ret;611 }612 613 indio_dev->trig = iio_trigger_get(st->dready_trig);614 615 return 0;616}617 618static int adxrs290_probe(struct spi_device *spi)619{620 struct iio_dev *indio_dev;621 struct adxrs290_state *st;622 u8 val, val2;623 int ret;624 625 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));626 if (!indio_dev)627 return -ENOMEM;628 629 st = iio_priv(indio_dev);630 st->spi = spi;631 632 indio_dev->name = "adxrs290";633 indio_dev->modes = INDIO_DIRECT_MODE;634 indio_dev->channels = adxrs290_channels;635 indio_dev->num_channels = ARRAY_SIZE(adxrs290_channels);636 indio_dev->info = &adxrs290_info;637 indio_dev->available_scan_masks = adxrs290_avail_scan_masks;638 639 mutex_init(&st->lock);640 641 val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_ADI_ID));642 if (val != ADXRS290_ADI_ID) {643 dev_err(&spi->dev, "Wrong ADI ID 0x%02x\n", val);644 return -ENODEV;645 }646 647 val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_MEMS_ID));648 if (val != ADXRS290_MEMS_ID) {649 dev_err(&spi->dev, "Wrong MEMS ID 0x%02x\n", val);650 return -ENODEV;651 }652 653 val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_DEV_ID));654 if (val != ADXRS290_DEV_ID) {655 dev_err(&spi->dev, "Wrong DEV ID 0x%02x\n", val);656 return -ENODEV;657 }658 659 /* default mode the gyroscope starts in */660 st->mode = ADXRS290_MODE_STANDBY;661 662 /* switch to measurement mode and switch on the temperature sensor */663 ret = adxrs290_initial_setup(indio_dev);664 if (ret < 0)665 return ret;666 667 /* max transition time to measurement mode */668 msleep(ADXRS290_MAX_TRANSITION_TIME_MS);669 670 ret = adxrs290_get_3db_freq(indio_dev, &val, &val2);671 if (ret < 0)672 return ret;673 674 st->lpf_3db_freq_idx = val;675 st->hpf_3db_freq_idx = val2;676 677 ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,678 &iio_pollfunc_store_time,679 &adxrs290_trigger_handler, NULL);680 if (ret < 0)681 return dev_err_probe(&spi->dev, ret,682 "iio triggered buffer setup failed\n");683 684 ret = adxrs290_probe_trigger(indio_dev);685 if (ret < 0)686 return ret;687 688 return devm_iio_device_register(&spi->dev, indio_dev);689}690 691static const struct of_device_id adxrs290_of_match[] = {692 { .compatible = "adi,adxrs290" },693 { }694};695MODULE_DEVICE_TABLE(of, adxrs290_of_match);696 697static struct spi_driver adxrs290_driver = {698 .driver = {699 .name = "adxrs290",700 .of_match_table = adxrs290_of_match,701 },702 .probe = adxrs290_probe,703};704module_spi_driver(adxrs290_driver);705 706MODULE_AUTHOR("Nishant Malpani <nish.malpani25@gmail.com>");707MODULE_DESCRIPTION("Analog Devices ADXRS290 Gyroscope SPI driver");708MODULE_LICENSE("GPL");709