Merge tag 'spi-fix-v5.16-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/brooni...
[linux-2.6-microblaze.git] / drivers / iio / accel / adxl313_core.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ADXL313 3-Axis Digital Accelerometer
4  *
5  * Copyright (c) 2021 Lucas Stankus <lucas.p.stankus@gmail.com>
6  *
7  * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL313.pdf
8  */
9
10 #include <linux/bitfield.h>
11 #include <linux/iio/iio.h>
12 #include <linux/module.h>
13 #include <linux/regmap.h>
14
15 #include "adxl313.h"
16
17 static const struct regmap_range adxl313_readable_reg_range[] = {
18         regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_XID),
19         regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
20         regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
21         regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
22         regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_FIFO_STATUS),
23 };
24
25 const struct regmap_access_table adxl313_readable_regs_table = {
26         .yes_ranges = adxl313_readable_reg_range,
27         .n_yes_ranges = ARRAY_SIZE(adxl313_readable_reg_range),
28 };
29 EXPORT_SYMBOL_GPL(adxl313_readable_regs_table);
30
31 static const struct regmap_range adxl313_writable_reg_range[] = {
32         regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
33         regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
34         regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
35         regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_INT_MAP),
36         regmap_reg_range(ADXL313_REG_DATA_FORMAT, ADXL313_REG_DATA_FORMAT),
37         regmap_reg_range(ADXL313_REG_FIFO_CTL, ADXL313_REG_FIFO_CTL),
38 };
39
40 const struct regmap_access_table adxl313_writable_regs_table = {
41         .yes_ranges = adxl313_writable_reg_range,
42         .n_yes_ranges = ARRAY_SIZE(adxl313_writable_reg_range),
43 };
44 EXPORT_SYMBOL_GPL(adxl313_writable_regs_table);
45
46 struct adxl313_data {
47         struct regmap   *regmap;
48         struct mutex    lock; /* lock to protect transf_buf */
49         __le16          transf_buf ____cacheline_aligned;
50 };
51
52 static const int adxl313_odr_freqs[][2] = {
53         [0] = { 6, 250000 },
54         [1] = { 12, 500000 },
55         [2] = { 25, 0 },
56         [3] = { 50, 0 },
57         [4] = { 100, 0 },
58         [5] = { 200, 0 },
59         [6] = { 400, 0 },
60         [7] = { 800, 0 },
61         [8] = { 1600, 0 },
62         [9] = { 3200, 0 },
63 };
64
65 #define ADXL313_ACCEL_CHANNEL(index, axis) {                            \
66         .type = IIO_ACCEL,                                              \
67         .address = index,                                               \
68         .modified = 1,                                                  \
69         .channel2 = IIO_MOD_##axis,                                     \
70         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                  \
71                               BIT(IIO_CHAN_INFO_CALIBBIAS),             \
72         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |          \
73                                     BIT(IIO_CHAN_INFO_SAMP_FREQ),       \
74         .info_mask_shared_by_type_available =                           \
75                 BIT(IIO_CHAN_INFO_SAMP_FREQ),                           \
76         .scan_type = {                                                  \
77                 .realbits = 13,                                         \
78         },                                                              \
79 }
80
81 static const struct iio_chan_spec adxl313_channels[] = {
82         ADXL313_ACCEL_CHANNEL(0, X),
83         ADXL313_ACCEL_CHANNEL(1, Y),
84         ADXL313_ACCEL_CHANNEL(2, Z),
85 };
86
87 static int adxl313_set_odr(struct adxl313_data *data,
88                            unsigned int freq1, unsigned int freq2)
89 {
90         unsigned int i;
91
92         for (i = 0; i < ARRAY_SIZE(adxl313_odr_freqs); i++) {
93                 if (adxl313_odr_freqs[i][0] == freq1 &&
94                     adxl313_odr_freqs[i][1] == freq2)
95                         break;
96         }
97
98         if (i == ARRAY_SIZE(adxl313_odr_freqs))
99                 return -EINVAL;
100
101         return regmap_update_bits(data->regmap, ADXL313_REG_BW_RATE,
102                                   ADXL313_RATE_MSK,
103                                   FIELD_PREP(ADXL313_RATE_MSK, ADXL313_RATE_BASE + i));
104 }
105
106 static int adxl313_read_axis(struct adxl313_data *data,
107                              struct iio_chan_spec const *chan)
108 {
109         int ret;
110
111         mutex_lock(&data->lock);
112
113         ret = regmap_bulk_read(data->regmap,
114                                ADXL313_REG_DATA_AXIS(chan->address),
115                                &data->transf_buf, sizeof(data->transf_buf));
116         if (ret)
117                 goto unlock_ret;
118
119         ret = le16_to_cpu(data->transf_buf);
120
121 unlock_ret:
122         mutex_unlock(&data->lock);
123         return ret;
124 }
125
126 static int adxl313_read_freq_avail(struct iio_dev *indio_dev,
127                                    struct iio_chan_spec const *chan,
128                                    const int **vals, int *type, int *length,
129                                    long mask)
130 {
131         switch (mask) {
132         case IIO_CHAN_INFO_SAMP_FREQ:
133                 *vals = (const int *)adxl313_odr_freqs;
134                 *length = ARRAY_SIZE(adxl313_odr_freqs) * 2;
135                 *type = IIO_VAL_INT_PLUS_MICRO;
136                 return IIO_AVAIL_LIST;
137         default:
138                 return -EINVAL;
139         }
140 }
141
142 static int adxl313_read_raw(struct iio_dev *indio_dev,
143                             struct iio_chan_spec const *chan,
144                             int *val, int *val2, long mask)
145 {
146         struct adxl313_data *data = iio_priv(indio_dev);
147         unsigned int regval;
148         int ret;
149
150         switch (mask) {
151         case IIO_CHAN_INFO_RAW:
152                 ret = adxl313_read_axis(data, chan);
153                 if (ret < 0)
154                         return ret;
155
156                 *val = sign_extend32(ret, chan->scan_type.realbits - 1);
157                 return IIO_VAL_INT;
158         case IIO_CHAN_INFO_SCALE:
159                 /*
160                  * Scale for any g range is given in datasheet as
161                  * 1024 LSB/g = 0.0009765625 * 9.80665 = 0.009576806640625 m/s^2
162                  */
163                 *val = 0;
164                 *val2 = 9576806;
165                 return IIO_VAL_INT_PLUS_NANO;
166         case IIO_CHAN_INFO_CALIBBIAS:
167                 ret = regmap_read(data->regmap,
168                                   ADXL313_REG_OFS_AXIS(chan->address), &regval);
169                 if (ret)
170                         return ret;
171
172                 /*
173                  * 8-bit resolution at +/- 0.5g, that is 4x accel data scale
174                  * factor at full resolution
175                  */
176                 *val = sign_extend32(regval, 7) * 4;
177                 return IIO_VAL_INT;
178         case IIO_CHAN_INFO_SAMP_FREQ:
179                 ret = regmap_read(data->regmap, ADXL313_REG_BW_RATE, &regval);
180                 if (ret)
181                         return ret;
182
183                 ret = FIELD_GET(ADXL313_RATE_MSK, regval) - ADXL313_RATE_BASE;
184                 *val = adxl313_odr_freqs[ret][0];
185                 *val2 = adxl313_odr_freqs[ret][1];
186                 return IIO_VAL_INT_PLUS_MICRO;
187         default:
188                 return -EINVAL;
189         }
190 }
191
192 static int adxl313_write_raw(struct iio_dev *indio_dev,
193                              struct iio_chan_spec const *chan,
194                              int val, int val2, long mask)
195 {
196         struct adxl313_data *data = iio_priv(indio_dev);
197
198         switch (mask) {
199         case IIO_CHAN_INFO_CALIBBIAS:
200                 /*
201                  * 8-bit resolution at +/- 0.5g, that is 4x accel data scale
202                  * factor at full resolution
203                  */
204                 if (clamp_val(val, -128 * 4, 127 * 4) != val)
205                         return -EINVAL;
206
207                 return regmap_write(data->regmap,
208                                     ADXL313_REG_OFS_AXIS(chan->address),
209                                     val / 4);
210         case IIO_CHAN_INFO_SAMP_FREQ:
211                 return adxl313_set_odr(data, val, val2);
212         default:
213                 return -EINVAL;
214         }
215 }
216
217 static const struct iio_info adxl313_info = {
218         .read_raw       = adxl313_read_raw,
219         .write_raw      = adxl313_write_raw,
220         .read_avail     = adxl313_read_freq_avail,
221 };
222
223 static int adxl313_setup(struct device *dev, struct adxl313_data *data,
224                          int (*setup)(struct device *, struct regmap *))
225 {
226         unsigned int regval;
227         int ret;
228
229         /* Ensures the device is in a consistent state after start up */
230         ret = regmap_write(data->regmap, ADXL313_REG_SOFT_RESET,
231                            ADXL313_SOFT_RESET);
232         if (ret)
233                 return ret;
234
235         if (setup) {
236                 ret = setup(dev, data->regmap);
237                 if (ret)
238                         return ret;
239         }
240
241         ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, &regval);
242         if (ret)
243                 return ret;
244
245         if (regval != ADXL313_DEVID0) {
246                 dev_err(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
247                 return -ENODEV;
248         }
249
250         ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, &regval);
251         if (ret)
252                 return ret;
253
254         if (regval != ADXL313_DEVID1) {
255                 dev_err(dev, "Invalid mems ID: 0x%02x\n", regval);
256                 return -ENODEV;
257         }
258
259         ret = regmap_read(data->regmap, ADXL313_REG_PARTID, &regval);
260         if (ret)
261                 return ret;
262
263         if (regval != ADXL313_PARTID) {
264                 dev_err(dev, "Invalid device ID: 0x%02x\n", regval);
265                 return -ENODEV;
266         }
267
268         /* Sets the range to +/- 4g */
269         ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
270                                  ADXL313_RANGE_MSK,
271                                  FIELD_PREP(ADXL313_RANGE_MSK, ADXL313_RANGE_4G));
272         if (ret)
273                 return ret;
274
275         /* Enables full resolution */
276         ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
277                                  ADXL313_FULL_RES, ADXL313_FULL_RES);
278         if (ret)
279                 return ret;
280
281         /* Enables measurement mode */
282         return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL,
283                                   ADXL313_POWER_CTL_MSK,
284                                   ADXL313_MEASUREMENT_MODE);
285 }
286
287 /**
288  * adxl313_core_probe() - probe and setup for adxl313 accelerometer
289  * @dev:        Driver model representation of the device
290  * @regmap:     Register map of the device
291  * @name:       Device name buffer reference
292  * @setup:      Setup routine to be executed right before the standard device
293  *              setup, can also be set to NULL if not required
294  *
295  * Return: 0 on success, negative errno on error cases
296  */
297 int adxl313_core_probe(struct device *dev,
298                        struct regmap *regmap,
299                        const char *name,
300                        int (*setup)(struct device *, struct regmap *))
301 {
302         struct adxl313_data *data;
303         struct iio_dev *indio_dev;
304         int ret;
305
306         indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
307         if (!indio_dev)
308                 return -ENOMEM;
309
310         data = iio_priv(indio_dev);
311         data->regmap = regmap;
312         mutex_init(&data->lock);
313
314         indio_dev->name = name;
315         indio_dev->info = &adxl313_info;
316         indio_dev->modes = INDIO_DIRECT_MODE;
317         indio_dev->channels = adxl313_channels;
318         indio_dev->num_channels = ARRAY_SIZE(adxl313_channels);
319
320         ret = adxl313_setup(dev, data, setup);
321         if (ret) {
322                 dev_err(dev, "ADXL313 setup failed\n");
323                 return ret;
324         }
325
326         return devm_iio_device_register(dev, indio_dev);
327 }
328 EXPORT_SYMBOL_GPL(adxl313_core_probe);
329
330 MODULE_AUTHOR("Lucas Stankus <lucas.p.stankus@gmail.com>");
331 MODULE_DESCRIPTION("ADXL313 3-Axis Digital Accelerometer core driver");
332 MODULE_LICENSE("GPL v2");