176 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ADIS16130 Digital Output, High Precision Angular Rate Sensor driver4 *5 * Copyright 2010 Analog Devices Inc.6 */7 8#include <linux/mutex.h>9#include <linux/kernel.h>10#include <linux/spi/spi.h>11#include <linux/module.h>12 13#include <linux/iio/iio.h>14 15#include <linux/unaligned.h>16 17#define ADIS16130_CON 0x018#define ADIS16130_CON_RD (1 << 6)19#define ADIS16130_IOP 0x120 21/* 1 = data-ready signal low when unread data on all channels; */22#define ADIS16130_IOP_ALL_RDY (1 << 3)23#define ADIS16130_IOP_SYNC (1 << 0) /* 1 = synchronization enabled */24#define ADIS16130_RATEDATA 0x8 /* Gyroscope output, rate of rotation */25#define ADIS16130_TEMPDATA 0xA /* Temperature output */26#define ADIS16130_RATECS 0x28 /* Gyroscope channel setup */27#define ADIS16130_RATECS_EN (1 << 3) /* 1 = channel enable; */28#define ADIS16130_TEMPCS 0x2A /* Temperature channel setup */29#define ADIS16130_TEMPCS_EN (1 << 3)30#define ADIS16130_RATECONV 0x3031#define ADIS16130_TEMPCONV 0x3232#define ADIS16130_MODE 0x3833#define ADIS16130_MODE_24BIT (1 << 1) /* 1 = 24-bit resolution; */34 35/**36 * struct adis16130_state - device instance specific data37 * @us: actual spi_device to write data38 * @buf_lock: mutex to protect tx and rx39 * @buf: unified tx/rx buffer40 **/41struct adis16130_state {42 struct spi_device *us;43 struct mutex buf_lock;44 u8 buf[4] __aligned(IIO_DMA_MINALIGN);45};46 47static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)48{49 int ret;50 struct adis16130_state *st = iio_priv(indio_dev);51 struct spi_transfer xfer = {52 .tx_buf = st->buf,53 .rx_buf = st->buf,54 .len = 4,55 };56 57 mutex_lock(&st->buf_lock);58 59 st->buf[0] = ADIS16130_CON_RD | reg_addr;60 st->buf[1] = st->buf[2] = st->buf[3] = 0;61 62 ret = spi_sync_transfer(st->us, &xfer, 1);63 if (ret == 0)64 *val = get_unaligned_be24(&st->buf[1]);65 mutex_unlock(&st->buf_lock);66 67 return ret;68}69 70static int adis16130_read_raw(struct iio_dev *indio_dev,71 struct iio_chan_spec const *chan,72 int *val, int *val2,73 long mask)74{75 int ret;76 u32 temp;77 78 switch (mask) {79 case IIO_CHAN_INFO_RAW:80 /* Take the iio_dev status lock */81 ret = adis16130_spi_read(indio_dev, chan->address, &temp);82 if (ret)83 return ret;84 *val = temp;85 return IIO_VAL_INT;86 case IIO_CHAN_INFO_SCALE:87 switch (chan->type) {88 case IIO_ANGL_VEL:89 /* 0 degree = 838860, 250 degree = 14260608 */90 *val = 250;91 *val2 = 336440817; /* RAD_TO_DEGREE(14260608 - 8388608) */92 return IIO_VAL_FRACTIONAL;93 case IIO_TEMP:94 /* 0C = 8036283, 105C = 9516048 */95 *val = 105000;96 *val2 = 9516048 - 8036283;97 return IIO_VAL_FRACTIONAL;98 default:99 return -EINVAL;100 }101 case IIO_CHAN_INFO_OFFSET:102 switch (chan->type) {103 case IIO_ANGL_VEL:104 *val = -8388608;105 return IIO_VAL_INT;106 case IIO_TEMP:107 *val = -8036283;108 return IIO_VAL_INT;109 default:110 return -EINVAL;111 }112 }113 114 return -EINVAL;115}116 117static const struct iio_chan_spec adis16130_channels[] = {118 {119 .type = IIO_ANGL_VEL,120 .modified = 1,121 .channel2 = IIO_MOD_Z,122 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |123 BIT(IIO_CHAN_INFO_SCALE) |124 BIT(IIO_CHAN_INFO_OFFSET),125 .address = ADIS16130_RATEDATA,126 }, {127 .type = IIO_TEMP,128 .indexed = 1,129 .channel = 0,130 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |131 BIT(IIO_CHAN_INFO_SCALE) |132 BIT(IIO_CHAN_INFO_OFFSET),133 .address = ADIS16130_TEMPDATA,134 }135};136 137static const struct iio_info adis16130_info = {138 .read_raw = &adis16130_read_raw,139};140 141static int adis16130_probe(struct spi_device *spi)142{143 struct adis16130_state *st;144 struct iio_dev *indio_dev;145 146 /* setup the industrialio driver allocated elements */147 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));148 if (!indio_dev)149 return -ENOMEM;150 st = iio_priv(indio_dev);151 /* this is only used for removal purposes */152 spi_set_drvdata(spi, indio_dev);153 st->us = spi;154 mutex_init(&st->buf_lock);155 indio_dev->name = spi->dev.driver->name;156 indio_dev->channels = adis16130_channels;157 indio_dev->num_channels = ARRAY_SIZE(adis16130_channels);158 indio_dev->info = &adis16130_info;159 indio_dev->modes = INDIO_DIRECT_MODE;160 161 return devm_iio_device_register(&spi->dev, indio_dev);162}163 164static struct spi_driver adis16130_driver = {165 .driver = {166 .name = "adis16130",167 },168 .probe = adis16130_probe,169};170module_spi_driver(adis16130_driver);171 172MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");173MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate");174MODULE_LICENSE("GPL v2");175MODULE_ALIAS("spi:adis16130");176