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/module.h>
12 #include <linux/regmap.h>
13
14 #include "adxl313.h"
15
16 static const struct regmap_range adxl312_readable_reg_range[] = {
17 regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_DEVID0),
18 regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
19 regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
20 regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_FIFO_STATUS),
21 };
22
23 static const struct regmap_range adxl313_readable_reg_range[] = {
24 regmap_reg_range(ADXL313_REG_DEVID0, ADXL313_REG_XID),
25 regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
26 regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
27 regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
28 regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_FIFO_STATUS),
29 };
30
31 const struct regmap_access_table adxl312_readable_regs_table = {
32 .yes_ranges = adxl312_readable_reg_range,
33 .n_yes_ranges = ARRAY_SIZE(adxl312_readable_reg_range),
34 };
35 EXPORT_SYMBOL_NS_GPL(adxl312_readable_regs_table, "IIO_ADXL313");
36
37 const struct regmap_access_table adxl313_readable_regs_table = {
38 .yes_ranges = adxl313_readable_reg_range,
39 .n_yes_ranges = ARRAY_SIZE(adxl313_readable_reg_range),
40 };
41 EXPORT_SYMBOL_NS_GPL(adxl313_readable_regs_table, "IIO_ADXL313");
42
43 const struct regmap_access_table adxl314_readable_regs_table = {
44 .yes_ranges = adxl312_readable_reg_range,
45 .n_yes_ranges = ARRAY_SIZE(adxl312_readable_reg_range),
46 };
47 EXPORT_SYMBOL_NS_GPL(adxl314_readable_regs_table, "IIO_ADXL313");
48
adxl312_check_id(struct device * dev,struct adxl313_data * data)49 static int adxl312_check_id(struct device *dev,
50 struct adxl313_data *data)
51 {
52 unsigned int regval;
53 int ret;
54
55 ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, ®val);
56 if (ret)
57 return ret;
58
59 if (regval != ADXL313_DEVID0_ADXL312_314)
60 dev_warn(dev, "Invalid manufacturer ID: %#02x\n", regval);
61
62 return 0;
63 }
64
adxl313_check_id(struct device * dev,struct adxl313_data * data)65 static int adxl313_check_id(struct device *dev,
66 struct adxl313_data *data)
67 {
68 unsigned int regval;
69 int ret;
70
71 ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, ®val);
72 if (ret)
73 return ret;
74
75 if (regval != ADXL313_DEVID0)
76 dev_warn(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
77
78 /* Check DEVID1 and PARTID */
79 if (regval == ADXL313_DEVID0) {
80 ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, ®val);
81 if (ret)
82 return ret;
83
84 if (regval != ADXL313_DEVID1)
85 dev_warn(dev, "Invalid mems ID: 0x%02x\n", regval);
86
87 ret = regmap_read(data->regmap, ADXL313_REG_PARTID, ®val);
88 if (ret)
89 return ret;
90
91 if (regval != ADXL313_PARTID)
92 dev_warn(dev, "Invalid device ID: 0x%02x\n", regval);
93 }
94
95 return 0;
96 }
97
98 const struct adxl313_chip_info adxl31x_chip_info[] = {
99 [ADXL312] = {
100 .name = "adxl312",
101 .type = ADXL312,
102 .scale_factor = 28425072,
103 .variable_range = true,
104 .soft_reset = false,
105 .check_id = &adxl312_check_id,
106 },
107 [ADXL313] = {
108 .name = "adxl313",
109 .type = ADXL313,
110 .scale_factor = 9576806,
111 .variable_range = true,
112 .soft_reset = true,
113 .check_id = &adxl313_check_id,
114 },
115 [ADXL314] = {
116 .name = "adxl314",
117 .type = ADXL314,
118 .scale_factor = 478858719,
119 .variable_range = false,
120 .soft_reset = false,
121 .check_id = &adxl312_check_id,
122 },
123 };
124 EXPORT_SYMBOL_NS_GPL(adxl31x_chip_info, "IIO_ADXL313");
125
126 static const struct regmap_range adxl312_writable_reg_range[] = {
127 regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
128 regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
129 regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_INT_MAP),
130 regmap_reg_range(ADXL313_REG_DATA_FORMAT, ADXL313_REG_DATA_FORMAT),
131 regmap_reg_range(ADXL313_REG_FIFO_CTL, ADXL313_REG_FIFO_CTL),
132 };
133
134 static const struct regmap_range adxl313_writable_reg_range[] = {
135 regmap_reg_range(ADXL313_REG_SOFT_RESET, ADXL313_REG_SOFT_RESET),
136 regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
137 regmap_reg_range(ADXL313_REG_THRESH_ACT, ADXL313_REG_ACT_INACT_CTL),
138 regmap_reg_range(ADXL313_REG_BW_RATE, ADXL313_REG_INT_MAP),
139 regmap_reg_range(ADXL313_REG_DATA_FORMAT, ADXL313_REG_DATA_FORMAT),
140 regmap_reg_range(ADXL313_REG_FIFO_CTL, ADXL313_REG_FIFO_CTL),
141 };
142
143 const struct regmap_access_table adxl312_writable_regs_table = {
144 .yes_ranges = adxl312_writable_reg_range,
145 .n_yes_ranges = ARRAY_SIZE(adxl312_writable_reg_range),
146 };
147 EXPORT_SYMBOL_NS_GPL(adxl312_writable_regs_table, "IIO_ADXL313");
148
149 const struct regmap_access_table adxl313_writable_regs_table = {
150 .yes_ranges = adxl313_writable_reg_range,
151 .n_yes_ranges = ARRAY_SIZE(adxl313_writable_reg_range),
152 };
153 EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, "IIO_ADXL313");
154
155 const struct regmap_access_table adxl314_writable_regs_table = {
156 .yes_ranges = adxl312_writable_reg_range,
157 .n_yes_ranges = ARRAY_SIZE(adxl312_writable_reg_range),
158 };
159 EXPORT_SYMBOL_NS_GPL(adxl314_writable_regs_table, "IIO_ADXL313");
160
161 static const int adxl313_odr_freqs[][2] = {
162 [0] = { 6, 250000 },
163 [1] = { 12, 500000 },
164 [2] = { 25, 0 },
165 [3] = { 50, 0 },
166 [4] = { 100, 0 },
167 [5] = { 200, 0 },
168 [6] = { 400, 0 },
169 [7] = { 800, 0 },
170 [8] = { 1600, 0 },
171 [9] = { 3200, 0 },
172 };
173
174 #define ADXL313_ACCEL_CHANNEL(index, axis) { \
175 .type = IIO_ACCEL, \
176 .address = index, \
177 .modified = 1, \
178 .channel2 = IIO_MOD_##axis, \
179 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
180 BIT(IIO_CHAN_INFO_CALIBBIAS), \
181 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
182 BIT(IIO_CHAN_INFO_SAMP_FREQ), \
183 .info_mask_shared_by_type_available = \
184 BIT(IIO_CHAN_INFO_SAMP_FREQ), \
185 .scan_type = { \
186 .realbits = 13, \
187 }, \
188 }
189
190 static const struct iio_chan_spec adxl313_channels[] = {
191 ADXL313_ACCEL_CHANNEL(0, X),
192 ADXL313_ACCEL_CHANNEL(1, Y),
193 ADXL313_ACCEL_CHANNEL(2, Z),
194 };
195
adxl313_set_odr(struct adxl313_data * data,unsigned int freq1,unsigned int freq2)196 static int adxl313_set_odr(struct adxl313_data *data,
197 unsigned int freq1, unsigned int freq2)
198 {
199 unsigned int i;
200
201 for (i = 0; i < ARRAY_SIZE(adxl313_odr_freqs); i++) {
202 if (adxl313_odr_freqs[i][0] == freq1 &&
203 adxl313_odr_freqs[i][1] == freq2)
204 break;
205 }
206
207 if (i == ARRAY_SIZE(adxl313_odr_freqs))
208 return -EINVAL;
209
210 return regmap_update_bits(data->regmap, ADXL313_REG_BW_RATE,
211 ADXL313_RATE_MSK,
212 FIELD_PREP(ADXL313_RATE_MSK, ADXL313_RATE_BASE + i));
213 }
214
adxl313_read_axis(struct adxl313_data * data,struct iio_chan_spec const * chan)215 static int adxl313_read_axis(struct adxl313_data *data,
216 struct iio_chan_spec const *chan)
217 {
218 int ret;
219
220 mutex_lock(&data->lock);
221
222 ret = regmap_bulk_read(data->regmap,
223 ADXL313_REG_DATA_AXIS(chan->address),
224 &data->transf_buf, sizeof(data->transf_buf));
225 if (ret)
226 goto unlock_ret;
227
228 ret = le16_to_cpu(data->transf_buf);
229
230 unlock_ret:
231 mutex_unlock(&data->lock);
232 return ret;
233 }
234
adxl313_read_freq_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)235 static int adxl313_read_freq_avail(struct iio_dev *indio_dev,
236 struct iio_chan_spec const *chan,
237 const int **vals, int *type, int *length,
238 long mask)
239 {
240 switch (mask) {
241 case IIO_CHAN_INFO_SAMP_FREQ:
242 *vals = (const int *)adxl313_odr_freqs;
243 *length = ARRAY_SIZE(adxl313_odr_freqs) * 2;
244 *type = IIO_VAL_INT_PLUS_MICRO;
245 return IIO_AVAIL_LIST;
246 default:
247 return -EINVAL;
248 }
249 }
250
adxl313_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)251 static int adxl313_read_raw(struct iio_dev *indio_dev,
252 struct iio_chan_spec const *chan,
253 int *val, int *val2, long mask)
254 {
255 struct adxl313_data *data = iio_priv(indio_dev);
256 unsigned int regval;
257 int ret;
258
259 switch (mask) {
260 case IIO_CHAN_INFO_RAW:
261 ret = adxl313_read_axis(data, chan);
262 if (ret < 0)
263 return ret;
264
265 *val = sign_extend32(ret, chan->scan_type.realbits - 1);
266 return IIO_VAL_INT;
267 case IIO_CHAN_INFO_SCALE:
268 *val = 0;
269
270 *val2 = data->chip_info->scale_factor;
271
272 return IIO_VAL_INT_PLUS_NANO;
273 case IIO_CHAN_INFO_CALIBBIAS:
274 ret = regmap_read(data->regmap,
275 ADXL313_REG_OFS_AXIS(chan->address), ®val);
276 if (ret)
277 return ret;
278
279 /*
280 * 8-bit resolution at minimum range, that is 4x accel data scale
281 * factor at full resolution
282 */
283 *val = sign_extend32(regval, 7) * 4;
284 return IIO_VAL_INT;
285 case IIO_CHAN_INFO_SAMP_FREQ:
286 ret = regmap_read(data->regmap, ADXL313_REG_BW_RATE, ®val);
287 if (ret)
288 return ret;
289
290 ret = FIELD_GET(ADXL313_RATE_MSK, regval) - ADXL313_RATE_BASE;
291 *val = adxl313_odr_freqs[ret][0];
292 *val2 = adxl313_odr_freqs[ret][1];
293 return IIO_VAL_INT_PLUS_MICRO;
294 default:
295 return -EINVAL;
296 }
297 }
298
adxl313_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)299 static int adxl313_write_raw(struct iio_dev *indio_dev,
300 struct iio_chan_spec const *chan,
301 int val, int val2, long mask)
302 {
303 struct adxl313_data *data = iio_priv(indio_dev);
304
305 switch (mask) {
306 case IIO_CHAN_INFO_CALIBBIAS:
307 /*
308 * 8-bit resolution at minimum range, that is 4x accel data scale
309 * factor at full resolution
310 */
311 if (clamp_val(val, -128 * 4, 127 * 4) != val)
312 return -EINVAL;
313
314 return regmap_write(data->regmap,
315 ADXL313_REG_OFS_AXIS(chan->address),
316 val / 4);
317 case IIO_CHAN_INFO_SAMP_FREQ:
318 return adxl313_set_odr(data, val, val2);
319 default:
320 return -EINVAL;
321 }
322 }
323
324 static const struct iio_info adxl313_info = {
325 .read_raw = adxl313_read_raw,
326 .write_raw = adxl313_write_raw,
327 .read_avail = adxl313_read_freq_avail,
328 };
329
adxl313_setup(struct device * dev,struct adxl313_data * data,int (* setup)(struct device *,struct regmap *))330 static int adxl313_setup(struct device *dev, struct adxl313_data *data,
331 int (*setup)(struct device *, struct regmap *))
332 {
333 int ret;
334
335 /*
336 * If sw reset available, ensures the device is in a consistent
337 * state after start up
338 */
339 if (data->chip_info->soft_reset) {
340 ret = regmap_write(data->regmap, ADXL313_REG_SOFT_RESET,
341 ADXL313_SOFT_RESET);
342 if (ret)
343 return ret;
344 }
345
346 if (setup) {
347 ret = setup(dev, data->regmap);
348 if (ret)
349 return ret;
350 }
351
352 ret = data->chip_info->check_id(dev, data);
353 if (ret)
354 return ret;
355
356 /* Sets the range to maximum, full resolution, if applicable */
357 if (data->chip_info->variable_range) {
358 ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
359 ADXL313_RANGE_MSK,
360 FIELD_PREP(ADXL313_RANGE_MSK, ADXL313_RANGE_MAX));
361 if (ret)
362 return ret;
363
364 /* Enables full resolution */
365 ret = regmap_update_bits(data->regmap, ADXL313_REG_DATA_FORMAT,
366 ADXL313_FULL_RES, ADXL313_FULL_RES);
367 if (ret)
368 return ret;
369 }
370
371 /* Enables measurement mode */
372 return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL,
373 ADXL313_POWER_CTL_MSK,
374 ADXL313_MEASUREMENT_MODE);
375 }
376
377 /**
378 * adxl313_core_probe() - probe and setup for adxl313 accelerometer
379 * @dev: Driver model representation of the device
380 * @regmap: Register map of the device
381 * @chip_info: Structure containing device specific data
382 * @setup: Setup routine to be executed right before the standard device
383 * setup, can also be set to NULL if not required
384 *
385 * Return: 0 on success, negative errno on error cases
386 */
adxl313_core_probe(struct device * dev,struct regmap * regmap,const struct adxl313_chip_info * chip_info,int (* setup)(struct device *,struct regmap *))387 int adxl313_core_probe(struct device *dev,
388 struct regmap *regmap,
389 const struct adxl313_chip_info *chip_info,
390 int (*setup)(struct device *, struct regmap *))
391 {
392 struct adxl313_data *data;
393 struct iio_dev *indio_dev;
394 int ret;
395
396 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
397 if (!indio_dev)
398 return -ENOMEM;
399
400 data = iio_priv(indio_dev);
401 data->regmap = regmap;
402 data->chip_info = chip_info;
403
404 mutex_init(&data->lock);
405
406 indio_dev->name = chip_info->name;
407 indio_dev->info = &adxl313_info;
408 indio_dev->modes = INDIO_DIRECT_MODE;
409 indio_dev->channels = adxl313_channels;
410 indio_dev->num_channels = ARRAY_SIZE(adxl313_channels);
411
412 ret = adxl313_setup(dev, data, setup);
413 if (ret) {
414 dev_err(dev, "ADXL313 setup failed\n");
415 return ret;
416 }
417
418 return devm_iio_device_register(dev, indio_dev);
419 }
420 EXPORT_SYMBOL_NS_GPL(adxl313_core_probe, "IIO_ADXL313");
421
422 MODULE_AUTHOR("Lucas Stankus <lucas.p.stankus@gmail.com>");
423 MODULE_DESCRIPTION("ADXL313 3-Axis Digital Accelerometer core driver");
424 MODULE_LICENSE("GPL v2");
425