Merge tag 'kgdb-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt...
[linux-2.6-microblaze.git] / drivers / iio / gyro / adis16080.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * ADIS16080/100 Yaw Rate Gyroscope with SPI driver
4  *
5  * Copyright 2010 Analog Devices Inc.
6  */
7 #include <linux/delay.h>
8 #include <linux/mutex.h>
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/spi/spi.h>
12 #include <linux/slab.h>
13 #include <linux/sysfs.h>
14 #include <linux/module.h>
15
16 #include <linux/iio/iio.h>
17 #include <linux/iio/sysfs.h>
18
19 #define ADIS16080_DIN_GYRO   (0 << 10) /* Gyroscope output */
20 #define ADIS16080_DIN_TEMP   (1 << 10) /* Temperature output */
21 #define ADIS16080_DIN_AIN1   (2 << 10)
22 #define ADIS16080_DIN_AIN2   (3 << 10)
23
24 /*
25  * 1: Write contents on DIN to control register.
26  * 0: No changes to control register.
27  */
28
29 #define ADIS16080_DIN_WRITE  (1 << 15)
30
31 struct adis16080_chip_info {
32         int scale_val;
33         int scale_val2;
34 };
35
36 /**
37  * struct adis16080_state - device instance specific data
38  * @us:                 actual spi_device to write data
39  * @info:               chip specific parameters
40  * @buf:                transmit or receive buffer
41  * @lock:               lock to protect buffer during reads
42  **/
43 struct adis16080_state {
44         struct spi_device               *us;
45         const struct adis16080_chip_info *info;
46         struct mutex                    lock;
47
48         __be16 buf ____cacheline_aligned;
49 };
50
51 static int adis16080_read_sample(struct iio_dev *indio_dev,
52                 u16 addr, int *val)
53 {
54         struct adis16080_state *st = iio_priv(indio_dev);
55         int ret;
56         struct spi_transfer     t[] = {
57                 {
58                         .tx_buf         = &st->buf,
59                         .len            = 2,
60                         .cs_change      = 1,
61                 }, {
62                         .rx_buf         = &st->buf,
63                         .len            = 2,
64                 },
65         };
66
67         st->buf = cpu_to_be16(addr | ADIS16080_DIN_WRITE);
68
69         ret = spi_sync_transfer(st->us, t, ARRAY_SIZE(t));
70         if (ret == 0)
71                 *val = sign_extend32(be16_to_cpu(st->buf), 11);
72
73         return ret;
74 }
75
76 static int adis16080_read_raw(struct iio_dev *indio_dev,
77                              struct iio_chan_spec const *chan,
78                              int *val,
79                              int *val2,
80                              long mask)
81 {
82         struct adis16080_state *st = iio_priv(indio_dev);
83         int ret;
84
85         switch (mask) {
86         case IIO_CHAN_INFO_RAW:
87                 mutex_lock(&st->lock);
88                 ret = adis16080_read_sample(indio_dev, chan->address, val);
89                 mutex_unlock(&st->lock);
90                 return ret ? ret : IIO_VAL_INT;
91         case IIO_CHAN_INFO_SCALE:
92                 switch (chan->type) {
93                 case IIO_ANGL_VEL:
94                         *val = st->info->scale_val;
95                         *val2 = st->info->scale_val2;
96                         return IIO_VAL_FRACTIONAL;
97                 case IIO_VOLTAGE:
98                         /* VREF = 5V, 12 bits */
99                         *val = 5000;
100                         *val2 = 12;
101                         return IIO_VAL_FRACTIONAL_LOG2;
102                 case IIO_TEMP:
103                         /* 85 C = 585, 25 C = 0 */
104                         *val = 85000 - 25000;
105                         *val2 = 585;
106                         return IIO_VAL_FRACTIONAL;
107                 default:
108                         return -EINVAL;
109                 }
110         case IIO_CHAN_INFO_OFFSET:
111                 switch (chan->type) {
112                 case IIO_VOLTAGE:
113                         /* 2.5 V = 0 */
114                         *val = 2048;
115                         return IIO_VAL_INT;
116                 case IIO_TEMP:
117                         /* 85 C = 585, 25 C = 0 */
118                         *val = DIV_ROUND_CLOSEST(25 * 585, 85 - 25);
119                         return IIO_VAL_INT;
120                 default:
121                         return -EINVAL;
122                 }
123         default:
124                 break;
125         }
126
127         return -EINVAL;
128 }
129
130 static const struct iio_chan_spec adis16080_channels[] = {
131         {
132                 .type = IIO_ANGL_VEL,
133                 .modified = 1,
134                 .channel2 = IIO_MOD_Z,
135                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
136                         BIT(IIO_CHAN_INFO_SCALE),
137                 .address = ADIS16080_DIN_GYRO,
138         }, {
139                 .type = IIO_VOLTAGE,
140                 .indexed = 1,
141                 .channel = 0,
142                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
143                         BIT(IIO_CHAN_INFO_SCALE) |
144                         BIT(IIO_CHAN_INFO_OFFSET),
145                 .address = ADIS16080_DIN_AIN1,
146         }, {
147                 .type = IIO_VOLTAGE,
148                 .indexed = 1,
149                 .channel = 1,
150                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
151                         BIT(IIO_CHAN_INFO_SCALE) |
152                         BIT(IIO_CHAN_INFO_OFFSET),
153                 .address = ADIS16080_DIN_AIN2,
154         }, {
155                 .type = IIO_TEMP,
156                 .indexed = 1,
157                 .channel = 0,
158                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
159                         BIT(IIO_CHAN_INFO_SCALE) |
160                         BIT(IIO_CHAN_INFO_OFFSET),
161                 .address = ADIS16080_DIN_TEMP,
162         }
163 };
164
165 static const struct iio_info adis16080_info = {
166         .read_raw = &adis16080_read_raw,
167 };
168
169 enum {
170         ID_ADIS16080,
171         ID_ADIS16100,
172 };
173
174 static const struct adis16080_chip_info adis16080_chip_info[] = {
175         [ID_ADIS16080] = {
176                 /* 80 degree = 819, 819 rad = 46925 degree */
177                 .scale_val = 80,
178                 .scale_val2 = 46925,
179         },
180         [ID_ADIS16100] = {
181                 /* 300 degree = 1230, 1230 rad = 70474 degree */
182                 .scale_val = 300,
183                 .scale_val2 = 70474,
184         },
185 };
186
187 static int adis16080_probe(struct spi_device *spi)
188 {
189         const struct spi_device_id *id = spi_get_device_id(spi);
190         struct adis16080_state *st;
191         struct iio_dev *indio_dev;
192
193         /* setup the industrialio driver allocated elements */
194         indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
195         if (!indio_dev)
196                 return -ENOMEM;
197         st = iio_priv(indio_dev);
198         /* this is only used for removal purposes */
199         spi_set_drvdata(spi, indio_dev);
200
201         mutex_init(&st->lock);
202
203         /* Allocate the comms buffers */
204         st->us = spi;
205         st->info = &adis16080_chip_info[id->driver_data];
206
207         indio_dev->name = spi->dev.driver->name;
208         indio_dev->channels = adis16080_channels;
209         indio_dev->num_channels = ARRAY_SIZE(adis16080_channels);
210         indio_dev->info = &adis16080_info;
211         indio_dev->modes = INDIO_DIRECT_MODE;
212
213         return iio_device_register(indio_dev);
214 }
215
216 static int adis16080_remove(struct spi_device *spi)
217 {
218         iio_device_unregister(spi_get_drvdata(spi));
219         return 0;
220 }
221
222 static const struct spi_device_id adis16080_ids[] = {
223         { "adis16080", ID_ADIS16080 },
224         { "adis16100", ID_ADIS16100 },
225         {},
226 };
227 MODULE_DEVICE_TABLE(spi, adis16080_ids);
228
229 static struct spi_driver adis16080_driver = {
230         .driver = {
231                 .name = "adis16080",
232         },
233         .probe = adis16080_probe,
234         .remove = adis16080_remove,
235         .id_table = adis16080_ids,
236 };
237 module_spi_driver(adis16080_driver);
238
239 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
240 MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver");
241 MODULE_LICENSE("GPL v2");