xref: /OK3568_Linux_fs/kernel/drivers/iio/imu/adis.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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