drm/tests: hdmi: Fix memory leaks in drm_display_mode_from_cea_vic()
[drm/drm-misc.git] / drivers / iio / accel / adxl313_core.c
blob4de0a41bd679674dfff8ffa2940635675fdff2ce
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * ADXL313 3-Axis Digital Accelerometer
5 * Copyright (c) 2021 Lucas Stankus <lucas.p.stankus@gmail.com>
7 * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL313.pdf
8 */
10 #include <linux/bitfield.h>
11 #include <linux/module.h>
12 #include <linux/regmap.h>
14 #include "adxl313.h"
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),
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),
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),
35 EXPORT_SYMBOL_NS_GPL(adxl312_readable_regs_table, IIO_ADXL313);
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),
41 EXPORT_SYMBOL_NS_GPL(adxl313_readable_regs_table, IIO_ADXL313);
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),
47 EXPORT_SYMBOL_NS_GPL(adxl314_readable_regs_table, IIO_ADXL313);
49 static int adxl312_check_id(struct device *dev,
50 struct adxl313_data *data)
52 unsigned int regval;
53 int ret;
55 ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, &regval);
56 if (ret)
57 return ret;
59 if (regval != ADXL313_DEVID0_ADXL312_314)
60 dev_warn(dev, "Invalid manufacturer ID: %#02x\n", regval);
62 return 0;
65 static int adxl313_check_id(struct device *dev,
66 struct adxl313_data *data)
68 unsigned int regval;
69 int ret;
71 ret = regmap_read(data->regmap, ADXL313_REG_DEVID0, &regval);
72 if (ret)
73 return ret;
75 if (regval != ADXL313_DEVID0)
76 dev_warn(dev, "Invalid manufacturer ID: 0x%02x\n", regval);
78 /* Check DEVID1 and PARTID */
79 if (regval == ADXL313_DEVID0) {
80 ret = regmap_read(data->regmap, ADXL313_REG_DEVID1, &regval);
81 if (ret)
82 return ret;
84 if (regval != ADXL313_DEVID1)
85 dev_warn(dev, "Invalid mems ID: 0x%02x\n", regval);
87 ret = regmap_read(data->regmap, ADXL313_REG_PARTID, &regval);
88 if (ret)
89 return ret;
91 if (regval != ADXL313_PARTID)
92 dev_warn(dev, "Invalid device ID: 0x%02x\n", regval);
95 return 0;
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,
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,
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,
124 EXPORT_SYMBOL_NS_GPL(adxl31x_chip_info, IIO_ADXL313);
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),
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),
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),
147 EXPORT_SYMBOL_NS_GPL(adxl312_writable_regs_table, IIO_ADXL313);
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),
153 EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, IIO_ADXL313);
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),
159 EXPORT_SYMBOL_NS_GPL(adxl314_writable_regs_table, IIO_ADXL313);
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 },
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 }, \
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),
196 static int adxl313_set_odr(struct adxl313_data *data,
197 unsigned int freq1, unsigned int freq2)
199 unsigned int i;
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;
207 if (i == ARRAY_SIZE(adxl313_odr_freqs))
208 return -EINVAL;
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));
215 static int adxl313_read_axis(struct adxl313_data *data,
216 struct iio_chan_spec const *chan)
218 int ret;
220 mutex_lock(&data->lock);
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;
228 ret = le16_to_cpu(data->transf_buf);
230 unlock_ret:
231 mutex_unlock(&data->lock);
232 return ret;
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)
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;
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)
255 struct adxl313_data *data = iio_priv(indio_dev);
256 unsigned int regval;
257 int ret;
259 switch (mask) {
260 case IIO_CHAN_INFO_RAW:
261 ret = adxl313_read_axis(data, chan);
262 if (ret < 0)
263 return ret;
265 *val = sign_extend32(ret, chan->scan_type.realbits - 1);
266 return IIO_VAL_INT;
267 case IIO_CHAN_INFO_SCALE:
268 *val = 0;
270 *val2 = data->chip_info->scale_factor;
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), &regval);
276 if (ret)
277 return ret;
280 * 8-bit resolution at minimum range, that is 4x accel data scale
281 * factor at full resolution
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, &regval);
287 if (ret)
288 return ret;
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;
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)
303 struct adxl313_data *data = iio_priv(indio_dev);
305 switch (mask) {
306 case IIO_CHAN_INFO_CALIBBIAS:
308 * 8-bit resolution at minimum range, that is 4x accel data scale
309 * factor at full resolution
311 if (clamp_val(val, -128 * 4, 127 * 4) != val)
312 return -EINVAL;
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;
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,
330 static int adxl313_setup(struct device *dev, struct adxl313_data *data,
331 int (*setup)(struct device *, struct regmap *))
333 int ret;
336 * If sw reset available, ensures the device is in a consistent
337 * state after start up
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;
346 if (setup) {
347 ret = setup(dev, data->regmap);
348 if (ret)
349 return ret;
352 ret = data->chip_info->check_id(dev, data);
353 if (ret)
354 return ret;
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;
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;
371 /* Enables measurement mode */
372 return regmap_update_bits(data->regmap, ADXL313_REG_POWER_CTL,
373 ADXL313_POWER_CTL_MSK,
374 ADXL313_MEASUREMENT_MODE);
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
385 * Return: 0 on success, negative errno on error cases
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 *))
392 struct adxl313_data *data;
393 struct iio_dev *indio_dev;
394 int ret;
396 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
397 if (!indio_dev)
398 return -ENOMEM;
400 data = iio_priv(indio_dev);
401 data->regmap = regmap;
402 data->chip_info = chip_info;
404 mutex_init(&data->lock);
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);
412 ret = adxl313_setup(dev, data, setup);
413 if (ret) {
414 dev_err(dev, "ADXL313 setup failed\n");
415 return ret;
418 return devm_iio_device_register(dev, indio_dev);
420 EXPORT_SYMBOL_NS_GPL(adxl313_core_probe, IIO_ADXL313);
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");