1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2010 Analog Devices Inc.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/device.h>
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/mutex.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/spi/spi.h>
14*4882a593Smuzhiyun #include <linux/sysfs.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <linux/iio/iio.h>
17*4882a593Smuzhiyun #include <linux/iio/imu/adis.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define ADIS16201_STARTUP_DELAY_MS 220
20*4882a593Smuzhiyun #define ADIS16201_FLASH_CNT 0x00
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* Data Output Register Information */
23*4882a593Smuzhiyun #define ADIS16201_SUPPLY_OUT_REG 0x02
24*4882a593Smuzhiyun #define ADIS16201_XACCL_OUT_REG 0x04
25*4882a593Smuzhiyun #define ADIS16201_YACCL_OUT_REG 0x06
26*4882a593Smuzhiyun #define ADIS16201_AUX_ADC_REG 0x08
27*4882a593Smuzhiyun #define ADIS16201_TEMP_OUT_REG 0x0A
28*4882a593Smuzhiyun #define ADIS16201_XINCL_OUT_REG 0x0C
29*4882a593Smuzhiyun #define ADIS16201_YINCL_OUT_REG 0x0E
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* Calibration Register Definition */
32*4882a593Smuzhiyun #define ADIS16201_XACCL_OFFS_REG 0x10
33*4882a593Smuzhiyun #define ADIS16201_YACCL_OFFS_REG 0x12
34*4882a593Smuzhiyun #define ADIS16201_XACCL_SCALE_REG 0x14
35*4882a593Smuzhiyun #define ADIS16201_YACCL_SCALE_REG 0x16
36*4882a593Smuzhiyun #define ADIS16201_XINCL_OFFS_REG 0x18
37*4882a593Smuzhiyun #define ADIS16201_YINCL_OFFS_REG 0x1A
38*4882a593Smuzhiyun #define ADIS16201_XINCL_SCALE_REG 0x1C
39*4882a593Smuzhiyun #define ADIS16201_YINCL_SCALE_REG 0x1E
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /* Alarm Register Definition */
42*4882a593Smuzhiyun #define ADIS16201_ALM_MAG1_REG 0x20
43*4882a593Smuzhiyun #define ADIS16201_ALM_MAG2_REG 0x22
44*4882a593Smuzhiyun #define ADIS16201_ALM_SMPL1_REG 0x24
45*4882a593Smuzhiyun #define ADIS16201_ALM_SMPL2_REG 0x26
46*4882a593Smuzhiyun #define ADIS16201_ALM_CTRL_REG 0x28
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define ADIS16201_AUX_DAC_REG 0x30
49*4882a593Smuzhiyun #define ADIS16201_GPIO_CTRL_REG 0x32
50*4882a593Smuzhiyun #define ADIS16201_SMPL_PRD_REG 0x36
51*4882a593Smuzhiyun /* Operation, filter configuration */
52*4882a593Smuzhiyun #define ADIS16201_AVG_CNT_REG 0x38
53*4882a593Smuzhiyun #define ADIS16201_SLP_CNT_REG 0x3A
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* Miscellaneous Control Register Definition */
56*4882a593Smuzhiyun #define ADIS16201_MSC_CTRL_REG 0x34
57*4882a593Smuzhiyun #define ADIS16201_MSC_CTRL_SELF_TEST_EN BIT(8)
58*4882a593Smuzhiyun /* Data-ready enable: 1 = enabled, 0 = disabled */
59*4882a593Smuzhiyun #define ADIS16201_MSC_CTRL_DATA_RDY_EN BIT(2)
60*4882a593Smuzhiyun /* Data-ready polarity: 1 = active high, 0 = active low */
61*4882a593Smuzhiyun #define ADIS16201_MSC_CTRL_ACTIVE_DATA_RDY_HIGH BIT(1)
62*4882a593Smuzhiyun /* Data-ready line selection: 1 = DIO1, 0 = DIO0 */
63*4882a593Smuzhiyun #define ADIS16201_MSC_CTRL_DATA_RDY_DIO1 BIT(0)
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* Diagnostics System Status Register Definition */
66*4882a593Smuzhiyun #define ADIS16201_DIAG_STAT_REG 0x3C
67*4882a593Smuzhiyun #define ADIS16201_DIAG_STAT_ALARM2 BIT(9)
68*4882a593Smuzhiyun #define ADIS16201_DIAG_STAT_ALARM1 BIT(8)
69*4882a593Smuzhiyun #define ADIS16201_DIAG_STAT_SPI_FAIL_BIT 3
70*4882a593Smuzhiyun #define ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT 2
71*4882a593Smuzhiyun /* Power supply above 3.625 V */
72*4882a593Smuzhiyun #define ADIS16201_DIAG_STAT_POWER_HIGH_BIT 1
73*4882a593Smuzhiyun /* Power supply below 2.975 V */
74*4882a593Smuzhiyun #define ADIS16201_DIAG_STAT_POWER_LOW_BIT 0
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* System Command Register Definition */
77*4882a593Smuzhiyun #define ADIS16201_GLOB_CMD_REG 0x3E
78*4882a593Smuzhiyun #define ADIS16201_GLOB_CMD_SW_RESET BIT(7)
79*4882a593Smuzhiyun #define ADIS16201_GLOB_CMD_FACTORY_RESET BIT(1)
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun #define ADIS16201_ERROR_ACTIVE BIT(14)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun enum adis16201_scan {
84*4882a593Smuzhiyun ADIS16201_SCAN_ACC_X,
85*4882a593Smuzhiyun ADIS16201_SCAN_ACC_Y,
86*4882a593Smuzhiyun ADIS16201_SCAN_INCLI_X,
87*4882a593Smuzhiyun ADIS16201_SCAN_INCLI_Y,
88*4882a593Smuzhiyun ADIS16201_SCAN_SUPPLY,
89*4882a593Smuzhiyun ADIS16201_SCAN_AUX_ADC,
90*4882a593Smuzhiyun ADIS16201_SCAN_TEMP,
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun static const u8 adis16201_addresses[] = {
94*4882a593Smuzhiyun [ADIS16201_SCAN_ACC_X] = ADIS16201_XACCL_OFFS_REG,
95*4882a593Smuzhiyun [ADIS16201_SCAN_ACC_Y] = ADIS16201_YACCL_OFFS_REG,
96*4882a593Smuzhiyun [ADIS16201_SCAN_INCLI_X] = ADIS16201_XINCL_OFFS_REG,
97*4882a593Smuzhiyun [ADIS16201_SCAN_INCLI_Y] = ADIS16201_YINCL_OFFS_REG,
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
adis16201_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)100*4882a593Smuzhiyun static int adis16201_read_raw(struct iio_dev *indio_dev,
101*4882a593Smuzhiyun struct iio_chan_spec const *chan,
102*4882a593Smuzhiyun int *val, int *val2,
103*4882a593Smuzhiyun long mask)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun struct adis *st = iio_priv(indio_dev);
106*4882a593Smuzhiyun int ret;
107*4882a593Smuzhiyun int bits;
108*4882a593Smuzhiyun u8 addr;
109*4882a593Smuzhiyun s16 val16;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun switch (mask) {
112*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
113*4882a593Smuzhiyun return adis_single_conversion(indio_dev, chan,
114*4882a593Smuzhiyun ADIS16201_ERROR_ACTIVE, val);
115*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
116*4882a593Smuzhiyun switch (chan->type) {
117*4882a593Smuzhiyun case IIO_VOLTAGE:
118*4882a593Smuzhiyun if (chan->channel == 0) {
119*4882a593Smuzhiyun /* Voltage base units are mV hence 1.22 mV */
120*4882a593Smuzhiyun *val = 1;
121*4882a593Smuzhiyun *val2 = 220000;
122*4882a593Smuzhiyun } else {
123*4882a593Smuzhiyun /* Voltage base units are mV hence 0.61 mV */
124*4882a593Smuzhiyun *val = 0;
125*4882a593Smuzhiyun *val2 = 610000;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_MICRO;
128*4882a593Smuzhiyun case IIO_TEMP:
129*4882a593Smuzhiyun *val = -470;
130*4882a593Smuzhiyun *val2 = 0;
131*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_MICRO;
132*4882a593Smuzhiyun case IIO_ACCEL:
133*4882a593Smuzhiyun /*
134*4882a593Smuzhiyun * IIO base unit for sensitivity of accelerometer
135*4882a593Smuzhiyun * is milli g.
136*4882a593Smuzhiyun * 1 LSB represents 0.244 mg.
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun *val = 0;
139*4882a593Smuzhiyun *val2 = IIO_G_TO_M_S_2(462400);
140*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_NANO;
141*4882a593Smuzhiyun case IIO_INCLI:
142*4882a593Smuzhiyun *val = 0;
143*4882a593Smuzhiyun *val2 = 100000;
144*4882a593Smuzhiyun return IIO_VAL_INT_PLUS_MICRO;
145*4882a593Smuzhiyun default:
146*4882a593Smuzhiyun return -EINVAL;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun break;
149*4882a593Smuzhiyun case IIO_CHAN_INFO_OFFSET:
150*4882a593Smuzhiyun /*
151*4882a593Smuzhiyun * The raw ADC value is 1278 when the temperature
152*4882a593Smuzhiyun * is 25 degrees and the scale factor per milli
153*4882a593Smuzhiyun * degree celcius is -470.
154*4882a593Smuzhiyun */
155*4882a593Smuzhiyun *val = 25000 / -470 - 1278;
156*4882a593Smuzhiyun return IIO_VAL_INT;
157*4882a593Smuzhiyun case IIO_CHAN_INFO_CALIBBIAS:
158*4882a593Smuzhiyun switch (chan->type) {
159*4882a593Smuzhiyun case IIO_ACCEL:
160*4882a593Smuzhiyun bits = 12;
161*4882a593Smuzhiyun break;
162*4882a593Smuzhiyun case IIO_INCLI:
163*4882a593Smuzhiyun bits = 9;
164*4882a593Smuzhiyun break;
165*4882a593Smuzhiyun default:
166*4882a593Smuzhiyun return -EINVAL;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun addr = adis16201_addresses[chan->scan_index];
169*4882a593Smuzhiyun ret = adis_read_reg_16(st, addr, &val16);
170*4882a593Smuzhiyun if (ret)
171*4882a593Smuzhiyun return ret;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun *val = sign_extend32(val16, bits - 1);
174*4882a593Smuzhiyun return IIO_VAL_INT;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun return -EINVAL;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
adis16201_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)180*4882a593Smuzhiyun static int adis16201_write_raw(struct iio_dev *indio_dev,
181*4882a593Smuzhiyun struct iio_chan_spec const *chan,
182*4882a593Smuzhiyun int val,
183*4882a593Smuzhiyun int val2,
184*4882a593Smuzhiyun long mask)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun struct adis *st = iio_priv(indio_dev);
187*4882a593Smuzhiyun int m;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (mask != IIO_CHAN_INFO_CALIBBIAS)
190*4882a593Smuzhiyun return -EINVAL;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun switch (chan->type) {
193*4882a593Smuzhiyun case IIO_ACCEL:
194*4882a593Smuzhiyun m = GENMASK(11, 0);
195*4882a593Smuzhiyun break;
196*4882a593Smuzhiyun case IIO_INCLI:
197*4882a593Smuzhiyun m = GENMASK(8, 0);
198*4882a593Smuzhiyun break;
199*4882a593Smuzhiyun default:
200*4882a593Smuzhiyun return -EINVAL;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun return adis_write_reg_16(st, adis16201_addresses[chan->scan_index],
204*4882a593Smuzhiyun val & m);
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun static const struct iio_chan_spec adis16201_channels[] = {
208*4882a593Smuzhiyun ADIS_SUPPLY_CHAN(ADIS16201_SUPPLY_OUT_REG, ADIS16201_SCAN_SUPPLY, 0,
209*4882a593Smuzhiyun 12),
210*4882a593Smuzhiyun ADIS_TEMP_CHAN(ADIS16201_TEMP_OUT_REG, ADIS16201_SCAN_TEMP, 0, 12),
211*4882a593Smuzhiyun ADIS_ACCEL_CHAN(X, ADIS16201_XACCL_OUT_REG, ADIS16201_SCAN_ACC_X,
212*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
213*4882a593Smuzhiyun ADIS_ACCEL_CHAN(Y, ADIS16201_YACCL_OUT_REG, ADIS16201_SCAN_ACC_Y,
214*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
215*4882a593Smuzhiyun ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12),
216*4882a593Smuzhiyun ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT_REG, ADIS16201_SCAN_INCLI_X,
217*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
218*4882a593Smuzhiyun ADIS_INCLI_CHAN(Y, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y,
219*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
220*4882a593Smuzhiyun IIO_CHAN_SOFT_TIMESTAMP(7)
221*4882a593Smuzhiyun };
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun static const struct iio_info adis16201_info = {
224*4882a593Smuzhiyun .read_raw = adis16201_read_raw,
225*4882a593Smuzhiyun .write_raw = adis16201_write_raw,
226*4882a593Smuzhiyun .update_scan_mode = adis_update_scan_mode,
227*4882a593Smuzhiyun };
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun static const char * const adis16201_status_error_msgs[] = {
230*4882a593Smuzhiyun [ADIS16201_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
231*4882a593Smuzhiyun [ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT] = "Flash update failed",
232*4882a593Smuzhiyun [ADIS16201_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
233*4882a593Smuzhiyun [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
234*4882a593Smuzhiyun };
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun static const struct adis_timeout adis16201_timeouts = {
237*4882a593Smuzhiyun .reset_ms = ADIS16201_STARTUP_DELAY_MS,
238*4882a593Smuzhiyun .sw_reset_ms = ADIS16201_STARTUP_DELAY_MS,
239*4882a593Smuzhiyun .self_test_ms = ADIS16201_STARTUP_DELAY_MS,
240*4882a593Smuzhiyun };
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun static const struct adis_data adis16201_data = {
243*4882a593Smuzhiyun .read_delay = 20,
244*4882a593Smuzhiyun .msc_ctrl_reg = ADIS16201_MSC_CTRL_REG,
245*4882a593Smuzhiyun .glob_cmd_reg = ADIS16201_GLOB_CMD_REG,
246*4882a593Smuzhiyun .diag_stat_reg = ADIS16201_DIAG_STAT_REG,
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN,
249*4882a593Smuzhiyun .self_test_reg = ADIS16201_MSC_CTRL_REG,
250*4882a593Smuzhiyun .self_test_no_autoclear = true,
251*4882a593Smuzhiyun .timeouts = &adis16201_timeouts,
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun .status_error_msgs = adis16201_status_error_msgs,
254*4882a593Smuzhiyun .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) |
255*4882a593Smuzhiyun BIT(ADIS16201_DIAG_STAT_FLASH_UPT_FAIL_BIT) |
256*4882a593Smuzhiyun BIT(ADIS16201_DIAG_STAT_POWER_HIGH_BIT) |
257*4882a593Smuzhiyun BIT(ADIS16201_DIAG_STAT_POWER_LOW_BIT),
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun
adis16201_probe(struct spi_device * spi)260*4882a593Smuzhiyun static int adis16201_probe(struct spi_device *spi)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun struct iio_dev *indio_dev;
263*4882a593Smuzhiyun struct adis *st;
264*4882a593Smuzhiyun int ret;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
267*4882a593Smuzhiyun if (!indio_dev)
268*4882a593Smuzhiyun return -ENOMEM;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun st = iio_priv(indio_dev);
271*4882a593Smuzhiyun spi_set_drvdata(spi, indio_dev);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun indio_dev->name = spi->dev.driver->name;
274*4882a593Smuzhiyun indio_dev->info = &adis16201_info;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun indio_dev->channels = adis16201_channels;
277*4882a593Smuzhiyun indio_dev->num_channels = ARRAY_SIZE(adis16201_channels);
278*4882a593Smuzhiyun indio_dev->modes = INDIO_DIRECT_MODE;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun ret = adis_init(st, indio_dev, spi, &adis16201_data);
281*4882a593Smuzhiyun if (ret)
282*4882a593Smuzhiyun return ret;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun ret = devm_adis_setup_buffer_and_trigger(st, indio_dev, NULL);
285*4882a593Smuzhiyun if (ret)
286*4882a593Smuzhiyun return ret;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun ret = adis_initial_startup(st);
289*4882a593Smuzhiyun if (ret)
290*4882a593Smuzhiyun return ret;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun return devm_iio_device_register(&spi->dev, indio_dev);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun static struct spi_driver adis16201_driver = {
296*4882a593Smuzhiyun .driver = {
297*4882a593Smuzhiyun .name = "adis16201",
298*4882a593Smuzhiyun },
299*4882a593Smuzhiyun .probe = adis16201_probe,
300*4882a593Smuzhiyun };
301*4882a593Smuzhiyun module_spi_driver(adis16201_driver);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
304*4882a593Smuzhiyun MODULE_DESCRIPTION("Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer");
305*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
306*4882a593Smuzhiyun MODULE_ALIAS("spi:adis16201");
307