1fda8d26eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2420b0fcbSLars-Peter Clausen /*
3420b0fcbSLars-Peter Clausen * ADXRS450/ADXRS453 Digital Output Gyroscope Driver
4420b0fcbSLars-Peter Clausen *
5420b0fcbSLars-Peter Clausen * Copyright 2011 Analog Devices Inc.
6420b0fcbSLars-Peter Clausen */
7420b0fcbSLars-Peter Clausen
8420b0fcbSLars-Peter Clausen #include <linux/interrupt.h>
9420b0fcbSLars-Peter Clausen #include <linux/irq.h>
10420b0fcbSLars-Peter Clausen #include <linux/delay.h>
11420b0fcbSLars-Peter Clausen #include <linux/mutex.h>
12420b0fcbSLars-Peter Clausen #include <linux/device.h>
13420b0fcbSLars-Peter Clausen #include <linux/kernel.h>
14420b0fcbSLars-Peter Clausen #include <linux/spi/spi.h>
15420b0fcbSLars-Peter Clausen #include <linux/slab.h>
16420b0fcbSLars-Peter Clausen #include <linux/sysfs.h>
17420b0fcbSLars-Peter Clausen #include <linux/list.h>
18420b0fcbSLars-Peter Clausen #include <linux/module.h>
19420b0fcbSLars-Peter Clausen
20420b0fcbSLars-Peter Clausen #include <linux/iio/iio.h>
21420b0fcbSLars-Peter Clausen #include <linux/iio/sysfs.h>
22420b0fcbSLars-Peter Clausen
23420b0fcbSLars-Peter Clausen #define ADXRS450_STARTUP_DELAY 50 /* ms */
24420b0fcbSLars-Peter Clausen
25420b0fcbSLars-Peter Clausen /* The MSB for the spi commands */
26420b0fcbSLars-Peter Clausen #define ADXRS450_SENSOR_DATA (0x20 << 24)
27420b0fcbSLars-Peter Clausen #define ADXRS450_WRITE_DATA (0x40 << 24)
28420b0fcbSLars-Peter Clausen #define ADXRS450_READ_DATA (0x80 << 24)
29420b0fcbSLars-Peter Clausen
30420b0fcbSLars-Peter Clausen #define ADXRS450_RATE1 0x00 /* Rate Registers */
31420b0fcbSLars-Peter Clausen #define ADXRS450_TEMP1 0x02 /* Temperature Registers */
32420b0fcbSLars-Peter Clausen #define ADXRS450_LOCST1 0x04 /* Low CST Memory Registers */
33420b0fcbSLars-Peter Clausen #define ADXRS450_HICST1 0x06 /* High CST Memory Registers */
34420b0fcbSLars-Peter Clausen #define ADXRS450_QUAD1 0x08 /* Quad Memory Registers */
35420b0fcbSLars-Peter Clausen #define ADXRS450_FAULT1 0x0A /* Fault Registers */
36420b0fcbSLars-Peter Clausen #define ADXRS450_PID1 0x0C /* Part ID Register 1 */
37420b0fcbSLars-Peter Clausen #define ADXRS450_SNH 0x0E /* Serial Number Registers, 4 bytes */
38420b0fcbSLars-Peter Clausen #define ADXRS450_SNL 0x10
39420b0fcbSLars-Peter Clausen #define ADXRS450_DNC1 0x12 /* Dynamic Null Correction Registers */
40420b0fcbSLars-Peter Clausen /* Check bits */
41420b0fcbSLars-Peter Clausen #define ADXRS450_P 0x01
42420b0fcbSLars-Peter Clausen #define ADXRS450_CHK 0x02
43420b0fcbSLars-Peter Clausen #define ADXRS450_CST 0x04
44420b0fcbSLars-Peter Clausen #define ADXRS450_PWR 0x08
45420b0fcbSLars-Peter Clausen #define ADXRS450_POR 0x10
46420b0fcbSLars-Peter Clausen #define ADXRS450_NVM 0x20
47420b0fcbSLars-Peter Clausen #define ADXRS450_Q 0x40
48420b0fcbSLars-Peter Clausen #define ADXRS450_PLL 0x80
49420b0fcbSLars-Peter Clausen #define ADXRS450_UV 0x100
50420b0fcbSLars-Peter Clausen #define ADXRS450_OV 0x200
51420b0fcbSLars-Peter Clausen #define ADXRS450_AMP 0x400
52420b0fcbSLars-Peter Clausen #define ADXRS450_FAIL 0x800
53420b0fcbSLars-Peter Clausen
54420b0fcbSLars-Peter Clausen #define ADXRS450_WRERR_MASK (0x7 << 29)
55420b0fcbSLars-Peter Clausen
56420b0fcbSLars-Peter Clausen #define ADXRS450_MAX_RX 4
57420b0fcbSLars-Peter Clausen #define ADXRS450_MAX_TX 4
58420b0fcbSLars-Peter Clausen
59420b0fcbSLars-Peter Clausen #define ADXRS450_GET_ST(a) ((a >> 26) & 0x3)
60420b0fcbSLars-Peter Clausen
61420b0fcbSLars-Peter Clausen enum {
62420b0fcbSLars-Peter Clausen ID_ADXRS450,
63420b0fcbSLars-Peter Clausen ID_ADXRS453,
64420b0fcbSLars-Peter Clausen };
65420b0fcbSLars-Peter Clausen
66420b0fcbSLars-Peter Clausen /**
67420b0fcbSLars-Peter Clausen * struct adxrs450_state - device instance specific data
68420b0fcbSLars-Peter Clausen * @us: actual spi_device
69420b0fcbSLars-Peter Clausen * @buf_lock: mutex to protect tx and rx
70420b0fcbSLars-Peter Clausen * @tx: transmit buffer
71420b0fcbSLars-Peter Clausen * @rx: receive buffer
72420b0fcbSLars-Peter Clausen **/
73420b0fcbSLars-Peter Clausen struct adxrs450_state {
74420b0fcbSLars-Peter Clausen struct spi_device *us;
75420b0fcbSLars-Peter Clausen struct mutex buf_lock;
76*966d2f4eSJonathan Cameron __be32 tx __aligned(IIO_DMA_MINALIGN);
77420b0fcbSLars-Peter Clausen __be32 rx;
78420b0fcbSLars-Peter Clausen
79420b0fcbSLars-Peter Clausen };
80420b0fcbSLars-Peter Clausen
81420b0fcbSLars-Peter Clausen /**
82420b0fcbSLars-Peter Clausen * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair
83420b0fcbSLars-Peter Clausen * @indio_dev: device associated with child of actual iio_dev
84420b0fcbSLars-Peter Clausen * @reg_address: the address of the lower of the two registers, which should be
85420b0fcbSLars-Peter Clausen * an even address, the second register's address is reg_address + 1.
86420b0fcbSLars-Peter Clausen * @val: somewhere to pass back the value read
87420b0fcbSLars-Peter Clausen **/
adxrs450_spi_read_reg_16(struct iio_dev * indio_dev,u8 reg_address,u16 * val)88420b0fcbSLars-Peter Clausen static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
89420b0fcbSLars-Peter Clausen u8 reg_address,
90420b0fcbSLars-Peter Clausen u16 *val)
91420b0fcbSLars-Peter Clausen {
92420b0fcbSLars-Peter Clausen struct adxrs450_state *st = iio_priv(indio_dev);
93420b0fcbSLars-Peter Clausen u32 tx;
94420b0fcbSLars-Peter Clausen int ret;
95420b0fcbSLars-Peter Clausen struct spi_transfer xfers[] = {
96420b0fcbSLars-Peter Clausen {
97420b0fcbSLars-Peter Clausen .tx_buf = &st->tx,
98420b0fcbSLars-Peter Clausen .bits_per_word = 8,
99420b0fcbSLars-Peter Clausen .len = sizeof(st->tx),
100420b0fcbSLars-Peter Clausen .cs_change = 1,
101420b0fcbSLars-Peter Clausen }, {
102420b0fcbSLars-Peter Clausen .rx_buf = &st->rx,
103420b0fcbSLars-Peter Clausen .bits_per_word = 8,
104420b0fcbSLars-Peter Clausen .len = sizeof(st->rx),
105420b0fcbSLars-Peter Clausen },
106420b0fcbSLars-Peter Clausen };
107420b0fcbSLars-Peter Clausen
108420b0fcbSLars-Peter Clausen mutex_lock(&st->buf_lock);
109420b0fcbSLars-Peter Clausen tx = ADXRS450_READ_DATA | (reg_address << 17);
110420b0fcbSLars-Peter Clausen
111420b0fcbSLars-Peter Clausen if (!(hweight32(tx) & 1))
112420b0fcbSLars-Peter Clausen tx |= ADXRS450_P;
113420b0fcbSLars-Peter Clausen
114420b0fcbSLars-Peter Clausen st->tx = cpu_to_be32(tx);
11535734fbdSLars-Peter Clausen ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
116420b0fcbSLars-Peter Clausen if (ret) {
117420b0fcbSLars-Peter Clausen dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n",
118420b0fcbSLars-Peter Clausen reg_address);
119420b0fcbSLars-Peter Clausen goto error_ret;
120420b0fcbSLars-Peter Clausen }
121420b0fcbSLars-Peter Clausen
122420b0fcbSLars-Peter Clausen *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF;
123420b0fcbSLars-Peter Clausen
124420b0fcbSLars-Peter Clausen error_ret:
125420b0fcbSLars-Peter Clausen mutex_unlock(&st->buf_lock);
126420b0fcbSLars-Peter Clausen return ret;
127420b0fcbSLars-Peter Clausen }
128420b0fcbSLars-Peter Clausen
129420b0fcbSLars-Peter Clausen /**
130420b0fcbSLars-Peter Clausen * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair
131420b0fcbSLars-Peter Clausen * @indio_dev: device associated with child of actual actual iio_dev
132420b0fcbSLars-Peter Clausen * @reg_address: the address of the lower of the two registers,which should be
133420b0fcbSLars-Peter Clausen * an even address, the second register's address is reg_address + 1.
134420b0fcbSLars-Peter Clausen * @val: value to be written.
135420b0fcbSLars-Peter Clausen **/
adxrs450_spi_write_reg_16(struct iio_dev * indio_dev,u8 reg_address,u16 val)136420b0fcbSLars-Peter Clausen static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
137420b0fcbSLars-Peter Clausen u8 reg_address,
138420b0fcbSLars-Peter Clausen u16 val)
139420b0fcbSLars-Peter Clausen {
140420b0fcbSLars-Peter Clausen struct adxrs450_state *st = iio_priv(indio_dev);
141420b0fcbSLars-Peter Clausen u32 tx;
142420b0fcbSLars-Peter Clausen int ret;
143420b0fcbSLars-Peter Clausen
144420b0fcbSLars-Peter Clausen mutex_lock(&st->buf_lock);
145420b0fcbSLars-Peter Clausen tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1);
146420b0fcbSLars-Peter Clausen
147420b0fcbSLars-Peter Clausen if (!(hweight32(tx) & 1))
148420b0fcbSLars-Peter Clausen tx |= ADXRS450_P;
149420b0fcbSLars-Peter Clausen
150420b0fcbSLars-Peter Clausen st->tx = cpu_to_be32(tx);
151420b0fcbSLars-Peter Clausen ret = spi_write(st->us, &st->tx, sizeof(st->tx));
152420b0fcbSLars-Peter Clausen if (ret)
153420b0fcbSLars-Peter Clausen dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n",
154420b0fcbSLars-Peter Clausen reg_address);
155420b0fcbSLars-Peter Clausen usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */
156420b0fcbSLars-Peter Clausen mutex_unlock(&st->buf_lock);
157420b0fcbSLars-Peter Clausen return ret;
158420b0fcbSLars-Peter Clausen }
159420b0fcbSLars-Peter Clausen
160420b0fcbSLars-Peter Clausen /**
161420b0fcbSLars-Peter Clausen * adxrs450_spi_sensor_data() - read 2 bytes sensor data
162420b0fcbSLars-Peter Clausen * @indio_dev: device associated with child of actual iio_dev
163420b0fcbSLars-Peter Clausen * @val: somewhere to pass back the value read
164420b0fcbSLars-Peter Clausen **/
adxrs450_spi_sensor_data(struct iio_dev * indio_dev,s16 * val)165420b0fcbSLars-Peter Clausen static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val)
166420b0fcbSLars-Peter Clausen {
167420b0fcbSLars-Peter Clausen struct adxrs450_state *st = iio_priv(indio_dev);
168420b0fcbSLars-Peter Clausen int ret;
169420b0fcbSLars-Peter Clausen struct spi_transfer xfers[] = {
170420b0fcbSLars-Peter Clausen {
171420b0fcbSLars-Peter Clausen .tx_buf = &st->tx,
172420b0fcbSLars-Peter Clausen .bits_per_word = 8,
173420b0fcbSLars-Peter Clausen .len = sizeof(st->tx),
174420b0fcbSLars-Peter Clausen .cs_change = 1,
175420b0fcbSLars-Peter Clausen }, {
176420b0fcbSLars-Peter Clausen .rx_buf = &st->rx,
177420b0fcbSLars-Peter Clausen .bits_per_word = 8,
178420b0fcbSLars-Peter Clausen .len = sizeof(st->rx),
179420b0fcbSLars-Peter Clausen },
180420b0fcbSLars-Peter Clausen };
181420b0fcbSLars-Peter Clausen
182420b0fcbSLars-Peter Clausen mutex_lock(&st->buf_lock);
183420b0fcbSLars-Peter Clausen st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA);
184420b0fcbSLars-Peter Clausen
18535734fbdSLars-Peter Clausen ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
186420b0fcbSLars-Peter Clausen if (ret) {
187420b0fcbSLars-Peter Clausen dev_err(&st->us->dev, "Problem while reading sensor data\n");
188420b0fcbSLars-Peter Clausen goto error_ret;
189420b0fcbSLars-Peter Clausen }
190420b0fcbSLars-Peter Clausen
191420b0fcbSLars-Peter Clausen *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF;
192420b0fcbSLars-Peter Clausen
193420b0fcbSLars-Peter Clausen error_ret:
194420b0fcbSLars-Peter Clausen mutex_unlock(&st->buf_lock);
195420b0fcbSLars-Peter Clausen return ret;
196420b0fcbSLars-Peter Clausen }
197420b0fcbSLars-Peter Clausen
198420b0fcbSLars-Peter Clausen /**
199420b0fcbSLars-Peter Clausen * adxrs450_spi_initial() - use for initializing procedure.
200420b0fcbSLars-Peter Clausen * @st: device instance specific data
201420b0fcbSLars-Peter Clausen * @val: somewhere to pass back the value read
202420b0fcbSLars-Peter Clausen * @chk: Whether to perform fault check
203420b0fcbSLars-Peter Clausen **/
adxrs450_spi_initial(struct adxrs450_state * st,u32 * val,char chk)204420b0fcbSLars-Peter Clausen static int adxrs450_spi_initial(struct adxrs450_state *st,
205420b0fcbSLars-Peter Clausen u32 *val, char chk)
206420b0fcbSLars-Peter Clausen {
207420b0fcbSLars-Peter Clausen int ret;
208420b0fcbSLars-Peter Clausen u32 tx;
209420b0fcbSLars-Peter Clausen struct spi_transfer xfers = {
210420b0fcbSLars-Peter Clausen .tx_buf = &st->tx,
211420b0fcbSLars-Peter Clausen .rx_buf = &st->rx,
212420b0fcbSLars-Peter Clausen .bits_per_word = 8,
213420b0fcbSLars-Peter Clausen .len = sizeof(st->tx),
214420b0fcbSLars-Peter Clausen };
215420b0fcbSLars-Peter Clausen
216420b0fcbSLars-Peter Clausen mutex_lock(&st->buf_lock);
217420b0fcbSLars-Peter Clausen tx = ADXRS450_SENSOR_DATA;
218420b0fcbSLars-Peter Clausen if (chk)
219420b0fcbSLars-Peter Clausen tx |= (ADXRS450_CHK | ADXRS450_P);
220420b0fcbSLars-Peter Clausen st->tx = cpu_to_be32(tx);
22114543a00SLars-Peter Clausen ret = spi_sync_transfer(st->us, &xfers, 1);
222420b0fcbSLars-Peter Clausen if (ret) {
223420b0fcbSLars-Peter Clausen dev_err(&st->us->dev, "Problem while reading initializing data\n");
224420b0fcbSLars-Peter Clausen goto error_ret;
225420b0fcbSLars-Peter Clausen }
226420b0fcbSLars-Peter Clausen
227420b0fcbSLars-Peter Clausen *val = be32_to_cpu(st->rx);
228420b0fcbSLars-Peter Clausen
229420b0fcbSLars-Peter Clausen error_ret:
230420b0fcbSLars-Peter Clausen mutex_unlock(&st->buf_lock);
231420b0fcbSLars-Peter Clausen return ret;
232420b0fcbSLars-Peter Clausen }
233420b0fcbSLars-Peter Clausen
234420b0fcbSLars-Peter Clausen /* Recommended Startup Sequence by spec */
adxrs450_initial_setup(struct iio_dev * indio_dev)235420b0fcbSLars-Peter Clausen static int adxrs450_initial_setup(struct iio_dev *indio_dev)
236420b0fcbSLars-Peter Clausen {
237420b0fcbSLars-Peter Clausen u32 t;
238420b0fcbSLars-Peter Clausen u16 data;
239420b0fcbSLars-Peter Clausen int ret;
240420b0fcbSLars-Peter Clausen struct adxrs450_state *st = iio_priv(indio_dev);
241420b0fcbSLars-Peter Clausen
242420b0fcbSLars-Peter Clausen msleep(ADXRS450_STARTUP_DELAY*2);
243420b0fcbSLars-Peter Clausen ret = adxrs450_spi_initial(st, &t, 1);
244420b0fcbSLars-Peter Clausen if (ret)
245420b0fcbSLars-Peter Clausen return ret;
246420b0fcbSLars-Peter Clausen if (t != 0x01)
247420b0fcbSLars-Peter Clausen dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n");
248420b0fcbSLars-Peter Clausen
249420b0fcbSLars-Peter Clausen msleep(ADXRS450_STARTUP_DELAY);
250420b0fcbSLars-Peter Clausen ret = adxrs450_spi_initial(st, &t, 0);
251420b0fcbSLars-Peter Clausen if (ret)
252420b0fcbSLars-Peter Clausen return ret;
253420b0fcbSLars-Peter Clausen
254420b0fcbSLars-Peter Clausen msleep(ADXRS450_STARTUP_DELAY);
255420b0fcbSLars-Peter Clausen ret = adxrs450_spi_initial(st, &t, 0);
256420b0fcbSLars-Peter Clausen if (ret)
257420b0fcbSLars-Peter Clausen return ret;
258420b0fcbSLars-Peter Clausen if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
259420b0fcbSLars-Peter Clausen dev_err(&st->us->dev, "The second response is not correct!\n");
260420b0fcbSLars-Peter Clausen return -EIO;
261420b0fcbSLars-Peter Clausen
262420b0fcbSLars-Peter Clausen }
263420b0fcbSLars-Peter Clausen ret = adxrs450_spi_initial(st, &t, 0);
264420b0fcbSLars-Peter Clausen if (ret)
265420b0fcbSLars-Peter Clausen return ret;
266420b0fcbSLars-Peter Clausen if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
267420b0fcbSLars-Peter Clausen dev_err(&st->us->dev, "The third response is not correct!\n");
268420b0fcbSLars-Peter Clausen return -EIO;
269420b0fcbSLars-Peter Clausen
270420b0fcbSLars-Peter Clausen }
271420b0fcbSLars-Peter Clausen ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data);
272420b0fcbSLars-Peter Clausen if (ret)
273420b0fcbSLars-Peter Clausen return ret;
274420b0fcbSLars-Peter Clausen if (data & 0x0fff) {
275420b0fcbSLars-Peter Clausen dev_err(&st->us->dev, "The device is not in normal status!\n");
276420b0fcbSLars-Peter Clausen return -EINVAL;
277420b0fcbSLars-Peter Clausen }
278420b0fcbSLars-Peter Clausen
279420b0fcbSLars-Peter Clausen return 0;
280420b0fcbSLars-Peter Clausen }
281420b0fcbSLars-Peter Clausen
adxrs450_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)282420b0fcbSLars-Peter Clausen static int adxrs450_write_raw(struct iio_dev *indio_dev,
283420b0fcbSLars-Peter Clausen struct iio_chan_spec const *chan,
284420b0fcbSLars-Peter Clausen int val,
285420b0fcbSLars-Peter Clausen int val2,
286420b0fcbSLars-Peter Clausen long mask)
287420b0fcbSLars-Peter Clausen {
288420b0fcbSLars-Peter Clausen int ret;
289420b0fcbSLars-Peter Clausen switch (mask) {
290420b0fcbSLars-Peter Clausen case IIO_CHAN_INFO_CALIBBIAS:
291420b0fcbSLars-Peter Clausen if (val < -0x400 || val >= 0x400)
292420b0fcbSLars-Peter Clausen return -EINVAL;
293420b0fcbSLars-Peter Clausen ret = adxrs450_spi_write_reg_16(indio_dev,
294420b0fcbSLars-Peter Clausen ADXRS450_DNC1, val);
295420b0fcbSLars-Peter Clausen break;
296420b0fcbSLars-Peter Clausen default:
297420b0fcbSLars-Peter Clausen ret = -EINVAL;
298420b0fcbSLars-Peter Clausen break;
299420b0fcbSLars-Peter Clausen }
300420b0fcbSLars-Peter Clausen return ret;
301420b0fcbSLars-Peter Clausen }
302420b0fcbSLars-Peter Clausen
adxrs450_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)303420b0fcbSLars-Peter Clausen static int adxrs450_read_raw(struct iio_dev *indio_dev,
304420b0fcbSLars-Peter Clausen struct iio_chan_spec const *chan,
305420b0fcbSLars-Peter Clausen int *val,
306420b0fcbSLars-Peter Clausen int *val2,
307420b0fcbSLars-Peter Clausen long mask)
308420b0fcbSLars-Peter Clausen {
309420b0fcbSLars-Peter Clausen int ret;
310420b0fcbSLars-Peter Clausen s16 t;
311420b0fcbSLars-Peter Clausen
312420b0fcbSLars-Peter Clausen switch (mask) {
313420b0fcbSLars-Peter Clausen case IIO_CHAN_INFO_RAW:
314420b0fcbSLars-Peter Clausen switch (chan->type) {
315420b0fcbSLars-Peter Clausen case IIO_ANGL_VEL:
316420b0fcbSLars-Peter Clausen ret = adxrs450_spi_sensor_data(indio_dev, &t);
317420b0fcbSLars-Peter Clausen if (ret)
318420b0fcbSLars-Peter Clausen break;
319420b0fcbSLars-Peter Clausen *val = t;
320420b0fcbSLars-Peter Clausen ret = IIO_VAL_INT;
321420b0fcbSLars-Peter Clausen break;
322420b0fcbSLars-Peter Clausen case IIO_TEMP:
323420b0fcbSLars-Peter Clausen ret = adxrs450_spi_read_reg_16(indio_dev,
324420b0fcbSLars-Peter Clausen ADXRS450_TEMP1, &t);
325420b0fcbSLars-Peter Clausen if (ret)
326420b0fcbSLars-Peter Clausen break;
327420b0fcbSLars-Peter Clausen *val = (t >> 6) + 225;
328420b0fcbSLars-Peter Clausen ret = IIO_VAL_INT;
329420b0fcbSLars-Peter Clausen break;
330420b0fcbSLars-Peter Clausen default:
331420b0fcbSLars-Peter Clausen ret = -EINVAL;
332420b0fcbSLars-Peter Clausen break;
333420b0fcbSLars-Peter Clausen }
334420b0fcbSLars-Peter Clausen break;
335420b0fcbSLars-Peter Clausen case IIO_CHAN_INFO_SCALE:
336420b0fcbSLars-Peter Clausen switch (chan->type) {
337420b0fcbSLars-Peter Clausen case IIO_ANGL_VEL:
338420b0fcbSLars-Peter Clausen *val = 0;
339420b0fcbSLars-Peter Clausen *val2 = 218166;
340420b0fcbSLars-Peter Clausen return IIO_VAL_INT_PLUS_NANO;
341420b0fcbSLars-Peter Clausen case IIO_TEMP:
342420b0fcbSLars-Peter Clausen *val = 200;
343420b0fcbSLars-Peter Clausen *val2 = 0;
344420b0fcbSLars-Peter Clausen return IIO_VAL_INT;
345420b0fcbSLars-Peter Clausen default:
346420b0fcbSLars-Peter Clausen return -EINVAL;
347420b0fcbSLars-Peter Clausen }
348420b0fcbSLars-Peter Clausen case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW:
349420b0fcbSLars-Peter Clausen ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t);
350420b0fcbSLars-Peter Clausen if (ret)
351420b0fcbSLars-Peter Clausen break;
352420b0fcbSLars-Peter Clausen *val = t;
353420b0fcbSLars-Peter Clausen ret = IIO_VAL_INT;
354420b0fcbSLars-Peter Clausen break;
355420b0fcbSLars-Peter Clausen case IIO_CHAN_INFO_CALIBBIAS:
356420b0fcbSLars-Peter Clausen ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t);
357420b0fcbSLars-Peter Clausen if (ret)
358420b0fcbSLars-Peter Clausen break;
359420b0fcbSLars-Peter Clausen *val = sign_extend32(t, 9);
360420b0fcbSLars-Peter Clausen ret = IIO_VAL_INT;
361420b0fcbSLars-Peter Clausen break;
362420b0fcbSLars-Peter Clausen default:
363420b0fcbSLars-Peter Clausen ret = -EINVAL;
364420b0fcbSLars-Peter Clausen break;
365420b0fcbSLars-Peter Clausen }
366420b0fcbSLars-Peter Clausen
367420b0fcbSLars-Peter Clausen return ret;
368420b0fcbSLars-Peter Clausen }
369420b0fcbSLars-Peter Clausen
370420b0fcbSLars-Peter Clausen static const struct iio_chan_spec adxrs450_channels[2][2] = {
371420b0fcbSLars-Peter Clausen [ID_ADXRS450] = {
372420b0fcbSLars-Peter Clausen {
373420b0fcbSLars-Peter Clausen .type = IIO_ANGL_VEL,
374420b0fcbSLars-Peter Clausen .modified = 1,
375420b0fcbSLars-Peter Clausen .channel2 = IIO_MOD_Z,
37698bfb6e3SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
37798bfb6e3SJonathan Cameron BIT(IIO_CHAN_INFO_CALIBBIAS) |
37898bfb6e3SJonathan Cameron BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW) |
37998bfb6e3SJonathan Cameron BIT(IIO_CHAN_INFO_SCALE),
380420b0fcbSLars-Peter Clausen }, {
381420b0fcbSLars-Peter Clausen .type = IIO_TEMP,
382420b0fcbSLars-Peter Clausen .indexed = 1,
383420b0fcbSLars-Peter Clausen .channel = 0,
38498bfb6e3SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
38598bfb6e3SJonathan Cameron BIT(IIO_CHAN_INFO_SCALE),
386420b0fcbSLars-Peter Clausen }
387420b0fcbSLars-Peter Clausen },
388420b0fcbSLars-Peter Clausen [ID_ADXRS453] = {
389420b0fcbSLars-Peter Clausen {
390420b0fcbSLars-Peter Clausen .type = IIO_ANGL_VEL,
391420b0fcbSLars-Peter Clausen .modified = 1,
392420b0fcbSLars-Peter Clausen .channel2 = IIO_MOD_Z,
39398bfb6e3SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
39498bfb6e3SJonathan Cameron BIT(IIO_CHAN_INFO_SCALE) |
39598bfb6e3SJonathan Cameron BIT(IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW),
396420b0fcbSLars-Peter Clausen }, {
397420b0fcbSLars-Peter Clausen .type = IIO_TEMP,
398420b0fcbSLars-Peter Clausen .indexed = 1,
399420b0fcbSLars-Peter Clausen .channel = 0,
40098bfb6e3SJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
40198bfb6e3SJonathan Cameron BIT(IIO_CHAN_INFO_SCALE),
402420b0fcbSLars-Peter Clausen }
403420b0fcbSLars-Peter Clausen },
404420b0fcbSLars-Peter Clausen };
405420b0fcbSLars-Peter Clausen
406420b0fcbSLars-Peter Clausen static const struct iio_info adxrs450_info = {
407420b0fcbSLars-Peter Clausen .read_raw = &adxrs450_read_raw,
408420b0fcbSLars-Peter Clausen .write_raw = &adxrs450_write_raw,
409420b0fcbSLars-Peter Clausen };
410420b0fcbSLars-Peter Clausen
adxrs450_probe(struct spi_device * spi)411420b0fcbSLars-Peter Clausen static int adxrs450_probe(struct spi_device *spi)
412420b0fcbSLars-Peter Clausen {
413420b0fcbSLars-Peter Clausen int ret;
414420b0fcbSLars-Peter Clausen struct adxrs450_state *st;
415420b0fcbSLars-Peter Clausen struct iio_dev *indio_dev;
416420b0fcbSLars-Peter Clausen
417420b0fcbSLars-Peter Clausen /* setup the industrialio driver allocated elements */
4186694cf96SSachin Kamat indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
4196694cf96SSachin Kamat if (!indio_dev)
4206694cf96SSachin Kamat return -ENOMEM;
421420b0fcbSLars-Peter Clausen st = iio_priv(indio_dev);
422420b0fcbSLars-Peter Clausen st->us = spi;
423420b0fcbSLars-Peter Clausen mutex_init(&st->buf_lock);
424420b0fcbSLars-Peter Clausen /* This is only used for removal purposes */
425420b0fcbSLars-Peter Clausen spi_set_drvdata(spi, indio_dev);
426420b0fcbSLars-Peter Clausen
427420b0fcbSLars-Peter Clausen indio_dev->info = &adxrs450_info;
428420b0fcbSLars-Peter Clausen indio_dev->modes = INDIO_DIRECT_MODE;
429420b0fcbSLars-Peter Clausen indio_dev->channels =
430420b0fcbSLars-Peter Clausen adxrs450_channels[spi_get_device_id(spi)->driver_data];
431420b0fcbSLars-Peter Clausen indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels);
432420b0fcbSLars-Peter Clausen indio_dev->name = spi->dev.driver->name;
433420b0fcbSLars-Peter Clausen
4349bcbf02aSSachin Kamat ret = devm_iio_device_register(&spi->dev, indio_dev);
435420b0fcbSLars-Peter Clausen if (ret)
4366694cf96SSachin Kamat return ret;
437420b0fcbSLars-Peter Clausen
438420b0fcbSLars-Peter Clausen /* Get the device into a sane initial state */
439420b0fcbSLars-Peter Clausen ret = adxrs450_initial_setup(indio_dev);
440420b0fcbSLars-Peter Clausen if (ret)
441420b0fcbSLars-Peter Clausen return ret;
442420b0fcbSLars-Peter Clausen
443420b0fcbSLars-Peter Clausen return 0;
444420b0fcbSLars-Peter Clausen }
445420b0fcbSLars-Peter Clausen
446420b0fcbSLars-Peter Clausen static const struct spi_device_id adxrs450_id[] = {
447420b0fcbSLars-Peter Clausen {"adxrs450", ID_ADXRS450},
448420b0fcbSLars-Peter Clausen {"adxrs453", ID_ADXRS453},
449420b0fcbSLars-Peter Clausen {}
450420b0fcbSLars-Peter Clausen };
451420b0fcbSLars-Peter Clausen MODULE_DEVICE_TABLE(spi, adxrs450_id);
452420b0fcbSLars-Peter Clausen
453420b0fcbSLars-Peter Clausen static struct spi_driver adxrs450_driver = {
454420b0fcbSLars-Peter Clausen .driver = {
455420b0fcbSLars-Peter Clausen .name = "adxrs450",
456420b0fcbSLars-Peter Clausen },
457420b0fcbSLars-Peter Clausen .probe = adxrs450_probe,
458420b0fcbSLars-Peter Clausen .id_table = adxrs450_id,
459420b0fcbSLars-Peter Clausen };
460420b0fcbSLars-Peter Clausen module_spi_driver(adxrs450_driver);
461420b0fcbSLars-Peter Clausen
462420b0fcbSLars-Peter Clausen MODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>");
463420b0fcbSLars-Peter Clausen MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver");
464420b0fcbSLars-Peter Clausen MODULE_LICENSE("GPL v2");
465