1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Common library for ADIS16XXX devices
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2012 Analog Devices Inc.
6*4882a593Smuzhiyun * Author: Lars-Peter Clausen <lars@metafoo.de>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
11*4882a593Smuzhiyun #include <linux/mutex.h>
12*4882a593Smuzhiyun #include <linux/device.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/spi/spi.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun #include <linux/sysfs.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <asm/unaligned.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <linux/iio/iio.h>
21*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
22*4882a593Smuzhiyun #include <linux/iio/buffer.h>
23*4882a593Smuzhiyun #include <linux/iio/imu/adis.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2)
26*4882a593Smuzhiyun #define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH BIT(1)
27*4882a593Smuzhiyun #define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
28*4882a593Smuzhiyun #define ADIS_GLOB_CMD_SW_RESET BIT(7)
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /**
31*4882a593Smuzhiyun * __adis_write_reg() - write N bytes to register (unlocked version)
32*4882a593Smuzhiyun * @adis: The adis device
33*4882a593Smuzhiyun * @reg: The address of the lower of the two registers
34*4882a593Smuzhiyun * @value: The value to write to device (up to 4 bytes)
35*4882a593Smuzhiyun * @size: The size of the @value (in bytes)
36*4882a593Smuzhiyun */
__adis_write_reg(struct adis * adis,unsigned int reg,unsigned int value,unsigned int size)37*4882a593Smuzhiyun int __adis_write_reg(struct adis *adis, unsigned int reg,
38*4882a593Smuzhiyun unsigned int value, unsigned int size)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun unsigned int page = reg / ADIS_PAGE_SIZE;
41*4882a593Smuzhiyun int ret, i;
42*4882a593Smuzhiyun struct spi_message msg;
43*4882a593Smuzhiyun struct spi_transfer xfers[] = {
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun .tx_buf = adis->tx,
46*4882a593Smuzhiyun .bits_per_word = 8,
47*4882a593Smuzhiyun .len = 2,
48*4882a593Smuzhiyun .cs_change = 1,
49*4882a593Smuzhiyun .delay.value = adis->data->write_delay,
50*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
51*4882a593Smuzhiyun .cs_change_delay.value = adis->data->cs_change_delay,
52*4882a593Smuzhiyun .cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
53*4882a593Smuzhiyun }, {
54*4882a593Smuzhiyun .tx_buf = adis->tx + 2,
55*4882a593Smuzhiyun .bits_per_word = 8,
56*4882a593Smuzhiyun .len = 2,
57*4882a593Smuzhiyun .cs_change = 1,
58*4882a593Smuzhiyun .delay.value = adis->data->write_delay,
59*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
60*4882a593Smuzhiyun .cs_change_delay.value = adis->data->cs_change_delay,
61*4882a593Smuzhiyun .cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
62*4882a593Smuzhiyun }, {
63*4882a593Smuzhiyun .tx_buf = adis->tx + 4,
64*4882a593Smuzhiyun .bits_per_word = 8,
65*4882a593Smuzhiyun .len = 2,
66*4882a593Smuzhiyun .cs_change = 1,
67*4882a593Smuzhiyun .delay.value = adis->data->write_delay,
68*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
69*4882a593Smuzhiyun .cs_change_delay.value = adis->data->cs_change_delay,
70*4882a593Smuzhiyun .cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
71*4882a593Smuzhiyun }, {
72*4882a593Smuzhiyun .tx_buf = adis->tx + 6,
73*4882a593Smuzhiyun .bits_per_word = 8,
74*4882a593Smuzhiyun .len = 2,
75*4882a593Smuzhiyun .delay.value = adis->data->write_delay,
76*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
77*4882a593Smuzhiyun }, {
78*4882a593Smuzhiyun .tx_buf = adis->tx + 8,
79*4882a593Smuzhiyun .bits_per_word = 8,
80*4882a593Smuzhiyun .len = 2,
81*4882a593Smuzhiyun .delay.value = adis->data->write_delay,
82*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
83*4882a593Smuzhiyun },
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun spi_message_init(&msg);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun if (adis->current_page != page) {
89*4882a593Smuzhiyun adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
90*4882a593Smuzhiyun adis->tx[1] = page;
91*4882a593Smuzhiyun spi_message_add_tail(&xfers[0], &msg);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun switch (size) {
95*4882a593Smuzhiyun case 4:
96*4882a593Smuzhiyun adis->tx[8] = ADIS_WRITE_REG(reg + 3);
97*4882a593Smuzhiyun adis->tx[9] = (value >> 24) & 0xff;
98*4882a593Smuzhiyun adis->tx[6] = ADIS_WRITE_REG(reg + 2);
99*4882a593Smuzhiyun adis->tx[7] = (value >> 16) & 0xff;
100*4882a593Smuzhiyun fallthrough;
101*4882a593Smuzhiyun case 2:
102*4882a593Smuzhiyun adis->tx[4] = ADIS_WRITE_REG(reg + 1);
103*4882a593Smuzhiyun adis->tx[5] = (value >> 8) & 0xff;
104*4882a593Smuzhiyun fallthrough;
105*4882a593Smuzhiyun case 1:
106*4882a593Smuzhiyun adis->tx[2] = ADIS_WRITE_REG(reg);
107*4882a593Smuzhiyun adis->tx[3] = value & 0xff;
108*4882a593Smuzhiyun break;
109*4882a593Smuzhiyun default:
110*4882a593Smuzhiyun return -EINVAL;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun xfers[size].cs_change = 0;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun for (i = 1; i <= size; i++)
116*4882a593Smuzhiyun spi_message_add_tail(&xfers[i], &msg);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun ret = spi_sync(adis->spi, &msg);
119*4882a593Smuzhiyun if (ret) {
120*4882a593Smuzhiyun dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n",
121*4882a593Smuzhiyun reg, ret);
122*4882a593Smuzhiyun } else {
123*4882a593Smuzhiyun adis->current_page = page;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun return ret;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__adis_write_reg);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /**
131*4882a593Smuzhiyun * __adis_read_reg() - read N bytes from register (unlocked version)
132*4882a593Smuzhiyun * @adis: The adis device
133*4882a593Smuzhiyun * @reg: The address of the lower of the two registers
134*4882a593Smuzhiyun * @val: The value read back from the device
135*4882a593Smuzhiyun * @size: The size of the @val buffer
136*4882a593Smuzhiyun */
__adis_read_reg(struct adis * adis,unsigned int reg,unsigned int * val,unsigned int size)137*4882a593Smuzhiyun int __adis_read_reg(struct adis *adis, unsigned int reg,
138*4882a593Smuzhiyun unsigned int *val, unsigned int size)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun unsigned int page = reg / ADIS_PAGE_SIZE;
141*4882a593Smuzhiyun struct spi_message msg;
142*4882a593Smuzhiyun int ret;
143*4882a593Smuzhiyun struct spi_transfer xfers[] = {
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun .tx_buf = adis->tx,
146*4882a593Smuzhiyun .bits_per_word = 8,
147*4882a593Smuzhiyun .len = 2,
148*4882a593Smuzhiyun .cs_change = 1,
149*4882a593Smuzhiyun .delay.value = adis->data->write_delay,
150*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
151*4882a593Smuzhiyun .cs_change_delay.value = adis->data->cs_change_delay,
152*4882a593Smuzhiyun .cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
153*4882a593Smuzhiyun }, {
154*4882a593Smuzhiyun .tx_buf = adis->tx + 2,
155*4882a593Smuzhiyun .bits_per_word = 8,
156*4882a593Smuzhiyun .len = 2,
157*4882a593Smuzhiyun .cs_change = 1,
158*4882a593Smuzhiyun .delay.value = adis->data->read_delay,
159*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
160*4882a593Smuzhiyun .cs_change_delay.value = adis->data->cs_change_delay,
161*4882a593Smuzhiyun .cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
162*4882a593Smuzhiyun }, {
163*4882a593Smuzhiyun .tx_buf = adis->tx + 4,
164*4882a593Smuzhiyun .rx_buf = adis->rx,
165*4882a593Smuzhiyun .bits_per_word = 8,
166*4882a593Smuzhiyun .len = 2,
167*4882a593Smuzhiyun .cs_change = 1,
168*4882a593Smuzhiyun .delay.value = adis->data->read_delay,
169*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
170*4882a593Smuzhiyun .cs_change_delay.value = adis->data->cs_change_delay,
171*4882a593Smuzhiyun .cs_change_delay.unit = SPI_DELAY_UNIT_USECS,
172*4882a593Smuzhiyun }, {
173*4882a593Smuzhiyun .rx_buf = adis->rx + 2,
174*4882a593Smuzhiyun .bits_per_word = 8,
175*4882a593Smuzhiyun .len = 2,
176*4882a593Smuzhiyun .delay.value = adis->data->read_delay,
177*4882a593Smuzhiyun .delay.unit = SPI_DELAY_UNIT_USECS,
178*4882a593Smuzhiyun },
179*4882a593Smuzhiyun };
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun spi_message_init(&msg);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun if (adis->current_page != page) {
184*4882a593Smuzhiyun adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
185*4882a593Smuzhiyun adis->tx[1] = page;
186*4882a593Smuzhiyun spi_message_add_tail(&xfers[0], &msg);
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun switch (size) {
190*4882a593Smuzhiyun case 4:
191*4882a593Smuzhiyun adis->tx[2] = ADIS_READ_REG(reg + 2);
192*4882a593Smuzhiyun adis->tx[3] = 0;
193*4882a593Smuzhiyun spi_message_add_tail(&xfers[1], &msg);
194*4882a593Smuzhiyun fallthrough;
195*4882a593Smuzhiyun case 2:
196*4882a593Smuzhiyun adis->tx[4] = ADIS_READ_REG(reg);
197*4882a593Smuzhiyun adis->tx[5] = 0;
198*4882a593Smuzhiyun spi_message_add_tail(&xfers[2], &msg);
199*4882a593Smuzhiyun spi_message_add_tail(&xfers[3], &msg);
200*4882a593Smuzhiyun break;
201*4882a593Smuzhiyun default:
202*4882a593Smuzhiyun return -EINVAL;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun ret = spi_sync(adis->spi, &msg);
206*4882a593Smuzhiyun if (ret) {
207*4882a593Smuzhiyun dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
208*4882a593Smuzhiyun reg, ret);
209*4882a593Smuzhiyun return ret;
210*4882a593Smuzhiyun } else {
211*4882a593Smuzhiyun adis->current_page = page;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun switch (size) {
215*4882a593Smuzhiyun case 4:
216*4882a593Smuzhiyun *val = get_unaligned_be32(adis->rx);
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun case 2:
219*4882a593Smuzhiyun *val = get_unaligned_be16(adis->rx + 2);
220*4882a593Smuzhiyun break;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun return ret;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__adis_read_reg);
226*4882a593Smuzhiyun /**
227*4882a593Smuzhiyun * __adis_update_bits_base() - ADIS Update bits function - Unlocked version
228*4882a593Smuzhiyun * @adis: The adis device
229*4882a593Smuzhiyun * @reg: The address of the lower of the two registers
230*4882a593Smuzhiyun * @mask: Bitmask to change
231*4882a593Smuzhiyun * @val: Value to be written
232*4882a593Smuzhiyun * @size: Size of the register to update
233*4882a593Smuzhiyun *
234*4882a593Smuzhiyun * Updates the desired bits of @reg in accordance with @mask and @val.
235*4882a593Smuzhiyun */
__adis_update_bits_base(struct adis * adis,unsigned int reg,const u32 mask,const u32 val,u8 size)236*4882a593Smuzhiyun int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
237*4882a593Smuzhiyun const u32 val, u8 size)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun int ret;
240*4882a593Smuzhiyun u32 __val;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun ret = __adis_read_reg(adis, reg, &__val, size);
243*4882a593Smuzhiyun if (ret)
244*4882a593Smuzhiyun return ret;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun __val = (__val & ~mask) | (val & mask);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun return __adis_write_reg(adis, reg, __val, size);
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__adis_update_bits_base);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
253*4882a593Smuzhiyun
adis_debugfs_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)254*4882a593Smuzhiyun int adis_debugfs_reg_access(struct iio_dev *indio_dev,
255*4882a593Smuzhiyun unsigned int reg, unsigned int writeval, unsigned int *readval)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun struct adis *adis = iio_device_get_drvdata(indio_dev);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (readval) {
260*4882a593Smuzhiyun uint16_t val16;
261*4882a593Smuzhiyun int ret;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun ret = adis_read_reg_16(adis, reg, &val16);
264*4882a593Smuzhiyun if (ret == 0)
265*4882a593Smuzhiyun *readval = val16;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun return ret;
268*4882a593Smuzhiyun } else {
269*4882a593Smuzhiyun return adis_write_reg_16(adis, reg, writeval);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun EXPORT_SYMBOL(adis_debugfs_reg_access);
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun #endif
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /**
277*4882a593Smuzhiyun * adis_enable_irq() - Enable or disable data ready IRQ
278*4882a593Smuzhiyun * @adis: The adis device
279*4882a593Smuzhiyun * @enable: Whether to enable the IRQ
280*4882a593Smuzhiyun *
281*4882a593Smuzhiyun * Returns 0 on success, negative error code otherwise
282*4882a593Smuzhiyun */
adis_enable_irq(struct adis * adis,bool enable)283*4882a593Smuzhiyun int adis_enable_irq(struct adis *adis, bool enable)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun int ret = 0;
286*4882a593Smuzhiyun uint16_t msc;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun mutex_lock(&adis->state_lock);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun if (adis->data->enable_irq) {
291*4882a593Smuzhiyun ret = adis->data->enable_irq(adis, enable);
292*4882a593Smuzhiyun goto out_unlock;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
296*4882a593Smuzhiyun if (ret)
297*4882a593Smuzhiyun goto out_unlock;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;
300*4882a593Smuzhiyun msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;
301*4882a593Smuzhiyun if (enable)
302*4882a593Smuzhiyun msc |= ADIS_MSC_CTRL_DATA_RDY_EN;
303*4882a593Smuzhiyun else
304*4882a593Smuzhiyun msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun out_unlock:
309*4882a593Smuzhiyun mutex_unlock(&adis->state_lock);
310*4882a593Smuzhiyun return ret;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun EXPORT_SYMBOL(adis_enable_irq);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /**
315*4882a593Smuzhiyun * __adis_check_status() - Check the device for error conditions (unlocked)
316*4882a593Smuzhiyun * @adis: The adis device
317*4882a593Smuzhiyun *
318*4882a593Smuzhiyun * Returns 0 on success, a negative error code otherwise
319*4882a593Smuzhiyun */
__adis_check_status(struct adis * adis)320*4882a593Smuzhiyun int __adis_check_status(struct adis *adis)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun uint16_t status;
323*4882a593Smuzhiyun int ret;
324*4882a593Smuzhiyun int i;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
327*4882a593Smuzhiyun if (ret)
328*4882a593Smuzhiyun return ret;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun status &= adis->data->status_error_mask;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun if (status == 0)
333*4882a593Smuzhiyun return 0;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun for (i = 0; i < 16; ++i) {
336*4882a593Smuzhiyun if (status & BIT(i)) {
337*4882a593Smuzhiyun dev_err(&adis->spi->dev, "%s.\n",
338*4882a593Smuzhiyun adis->data->status_error_msgs[i]);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun return -EIO;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__adis_check_status);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /**
347*4882a593Smuzhiyun * __adis_reset() - Reset the device (unlocked version)
348*4882a593Smuzhiyun * @adis: The adis device
349*4882a593Smuzhiyun *
350*4882a593Smuzhiyun * Returns 0 on success, a negative error code otherwise
351*4882a593Smuzhiyun */
__adis_reset(struct adis * adis)352*4882a593Smuzhiyun int __adis_reset(struct adis *adis)
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun int ret;
355*4882a593Smuzhiyun const struct adis_timeout *timeouts = adis->data->timeouts;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg,
358*4882a593Smuzhiyun ADIS_GLOB_CMD_SW_RESET);
359*4882a593Smuzhiyun if (ret) {
360*4882a593Smuzhiyun dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
361*4882a593Smuzhiyun return ret;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun msleep(timeouts->sw_reset_ms);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return 0;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__adis_reset);
369*4882a593Smuzhiyun
adis_self_test(struct adis * adis)370*4882a593Smuzhiyun static int adis_self_test(struct adis *adis)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun int ret;
373*4882a593Smuzhiyun const struct adis_timeout *timeouts = adis->data->timeouts;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun ret = __adis_write_reg_16(adis, adis->data->self_test_reg,
376*4882a593Smuzhiyun adis->data->self_test_mask);
377*4882a593Smuzhiyun if (ret) {
378*4882a593Smuzhiyun dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
379*4882a593Smuzhiyun ret);
380*4882a593Smuzhiyun return ret;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun msleep(timeouts->self_test_ms);
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun ret = __adis_check_status(adis);
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun if (adis->data->self_test_no_autoclear)
388*4882a593Smuzhiyun __adis_write_reg_16(adis, adis->data->self_test_reg, 0x00);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun return ret;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun /**
394*4882a593Smuzhiyun * __adis_initial_startup() - Device initial setup
395*4882a593Smuzhiyun * @adis: The adis device
396*4882a593Smuzhiyun *
397*4882a593Smuzhiyun * The function performs a HW reset via a reset pin that should be specified
398*4882a593Smuzhiyun * via GPIOLIB. If no pin is configured a SW reset will be performed.
399*4882a593Smuzhiyun * The RST pin for the ADIS devices should be configured as ACTIVE_LOW.
400*4882a593Smuzhiyun *
401*4882a593Smuzhiyun * After the self-test operation is performed, the function will also check
402*4882a593Smuzhiyun * that the product ID is as expected. This assumes that drivers providing
403*4882a593Smuzhiyun * 'prod_id_reg' will also provide the 'prod_id'.
404*4882a593Smuzhiyun *
405*4882a593Smuzhiyun * Returns 0 if the device is operational, a negative error code otherwise.
406*4882a593Smuzhiyun *
407*4882a593Smuzhiyun * This function should be called early on in the device initialization sequence
408*4882a593Smuzhiyun * to ensure that the device is in a sane and known state and that it is usable.
409*4882a593Smuzhiyun */
__adis_initial_startup(struct adis * adis)410*4882a593Smuzhiyun int __adis_initial_startup(struct adis *adis)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun const struct adis_timeout *timeouts = adis->data->timeouts;
413*4882a593Smuzhiyun struct gpio_desc *gpio;
414*4882a593Smuzhiyun uint16_t prod_id;
415*4882a593Smuzhiyun int ret;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* check if the device has rst pin low */
418*4882a593Smuzhiyun gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_OUT_HIGH);
419*4882a593Smuzhiyun if (IS_ERR(gpio))
420*4882a593Smuzhiyun return PTR_ERR(gpio);
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun if (gpio) {
423*4882a593Smuzhiyun msleep(10);
424*4882a593Smuzhiyun /* bring device out of reset */
425*4882a593Smuzhiyun gpiod_set_value_cansleep(gpio, 0);
426*4882a593Smuzhiyun msleep(timeouts->reset_ms);
427*4882a593Smuzhiyun } else {
428*4882a593Smuzhiyun ret = __adis_reset(adis);
429*4882a593Smuzhiyun if (ret)
430*4882a593Smuzhiyun return ret;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun ret = adis_self_test(adis);
434*4882a593Smuzhiyun if (ret)
435*4882a593Smuzhiyun return ret;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun adis_enable_irq(adis, false);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun if (!adis->data->prod_id_reg)
440*4882a593Smuzhiyun return 0;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun ret = adis_read_reg_16(adis, adis->data->prod_id_reg, &prod_id);
443*4882a593Smuzhiyun if (ret)
444*4882a593Smuzhiyun return ret;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun if (prod_id != adis->data->prod_id)
447*4882a593Smuzhiyun dev_warn(&adis->spi->dev,
448*4882a593Smuzhiyun "Device ID(%u) and product ID(%u) do not match.\n",
449*4882a593Smuzhiyun adis->data->prod_id, prod_id);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun return 0;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__adis_initial_startup);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun /**
456*4882a593Smuzhiyun * adis_single_conversion() - Performs a single sample conversion
457*4882a593Smuzhiyun * @indio_dev: The IIO device
458*4882a593Smuzhiyun * @chan: The IIO channel
459*4882a593Smuzhiyun * @error_mask: Mask for the error bit
460*4882a593Smuzhiyun * @val: Result of the conversion
461*4882a593Smuzhiyun *
462*4882a593Smuzhiyun * Returns IIO_VAL_INT on success, a negative error code otherwise.
463*4882a593Smuzhiyun *
464*4882a593Smuzhiyun * The function performs a single conversion on a given channel and post
465*4882a593Smuzhiyun * processes the value accordingly to the channel spec. If a error_mask is given
466*4882a593Smuzhiyun * the function will check if the mask is set in the returned raw value. If it
467*4882a593Smuzhiyun * is set the function will perform a self-check. If the device does not report
468*4882a593Smuzhiyun * a error bit in the channels raw value set error_mask to 0.
469*4882a593Smuzhiyun */
adis_single_conversion(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,unsigned int error_mask,int * val)470*4882a593Smuzhiyun int adis_single_conversion(struct iio_dev *indio_dev,
471*4882a593Smuzhiyun const struct iio_chan_spec *chan, unsigned int error_mask, int *val)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun struct adis *adis = iio_device_get_drvdata(indio_dev);
474*4882a593Smuzhiyun unsigned int uval;
475*4882a593Smuzhiyun int ret;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun mutex_lock(&adis->state_lock);
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun ret = __adis_read_reg(adis, chan->address, &uval,
480*4882a593Smuzhiyun chan->scan_type.storagebits / 8);
481*4882a593Smuzhiyun if (ret)
482*4882a593Smuzhiyun goto err_unlock;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun if (uval & error_mask) {
485*4882a593Smuzhiyun ret = __adis_check_status(adis);
486*4882a593Smuzhiyun if (ret)
487*4882a593Smuzhiyun goto err_unlock;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun if (chan->scan_type.sign == 's')
491*4882a593Smuzhiyun *val = sign_extend32(uval, chan->scan_type.realbits - 1);
492*4882a593Smuzhiyun else
493*4882a593Smuzhiyun *val = uval & ((1 << chan->scan_type.realbits) - 1);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun ret = IIO_VAL_INT;
496*4882a593Smuzhiyun err_unlock:
497*4882a593Smuzhiyun mutex_unlock(&adis->state_lock);
498*4882a593Smuzhiyun return ret;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adis_single_conversion);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /**
503*4882a593Smuzhiyun * adis_init() - Initialize adis device structure
504*4882a593Smuzhiyun * @adis: The adis device
505*4882a593Smuzhiyun * @indio_dev: The iio device
506*4882a593Smuzhiyun * @spi: The spi device
507*4882a593Smuzhiyun * @data: Chip specific data
508*4882a593Smuzhiyun *
509*4882a593Smuzhiyun * Returns 0 on success, a negative error code otherwise.
510*4882a593Smuzhiyun *
511*4882a593Smuzhiyun * This function must be called, before any other adis helper function may be
512*4882a593Smuzhiyun * called.
513*4882a593Smuzhiyun */
adis_init(struct adis * adis,struct iio_dev * indio_dev,struct spi_device * spi,const struct adis_data * data)514*4882a593Smuzhiyun int adis_init(struct adis *adis, struct iio_dev *indio_dev,
515*4882a593Smuzhiyun struct spi_device *spi, const struct adis_data *data)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun if (!data || !data->timeouts) {
518*4882a593Smuzhiyun dev_err(&spi->dev, "No config data or timeouts not defined!\n");
519*4882a593Smuzhiyun return -EINVAL;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun mutex_init(&adis->state_lock);
523*4882a593Smuzhiyun adis->spi = spi;
524*4882a593Smuzhiyun adis->data = data;
525*4882a593Smuzhiyun iio_device_set_drvdata(indio_dev, adis);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (data->has_paging) {
528*4882a593Smuzhiyun /* Need to set the page before first read/write */
529*4882a593Smuzhiyun adis->current_page = -1;
530*4882a593Smuzhiyun } else {
531*4882a593Smuzhiyun /* Page will always be 0 */
532*4882a593Smuzhiyun adis->current_page = 0;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun return 0;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adis_init);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun MODULE_LICENSE("GPL");
540*4882a593Smuzhiyun MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
541*4882a593Smuzhiyun MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");
542