1 // SPDX-License-Identifier: GPL-2.0-only
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
10 #include <linux/bitfield.h>
11 #include <linux/module.h>
12 #include <linux/regmap.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
)
55 ret
= regmap_read(data
->regmap
, ADXL313_REG_DEVID0
, ®val
);
59 if (regval
!= ADXL313_DEVID0_ADXL312_314
)
60 dev_warn(dev
, "Invalid manufacturer ID: %#02x\n", regval
);
65 static int adxl313_check_id(struct device
*dev
,
66 struct adxl313_data
*data
)
71 ret
= regmap_read(data
->regmap
, ADXL313_REG_DEVID0
, ®val
);
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
, ®val
);
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
, ®val
);
91 if (regval
!= ADXL313_PARTID
)
92 dev_warn(dev
, "Invalid device ID: 0x%02x\n", regval
);
98 const struct adxl313_chip_info adxl31x_chip_info
[] = {
102 .scale_factor
= 28425072,
103 .variable_range
= true,
105 .check_id
= &adxl312_check_id
,
110 .scale_factor
= 9576806,
111 .variable_range
= true,
113 .check_id
= &adxl313_check_id
,
118 .scale_factor
= 478858719,
119 .variable_range
= 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] = {
163 [1] = { 12, 500000 },
174 #define ADXL313_ACCEL_CHANNEL(index, axis) { \
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), \
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
)
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
)
207 if (i
== ARRAY_SIZE(adxl313_odr_freqs
))
210 return regmap_update_bits(data
->regmap
, ADXL313_REG_BW_RATE
,
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
)
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
));
228 ret
= le16_to_cpu(data
->transf_buf
);
231 mutex_unlock(&data
->lock
);
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
,
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
;
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
);
260 case IIO_CHAN_INFO_RAW
:
261 ret
= adxl313_read_axis(data
, chan
);
265 *val
= sign_extend32(ret
, chan
->scan_type
.realbits
- 1);
267 case IIO_CHAN_INFO_SCALE
:
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
), ®val
);
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;
285 case IIO_CHAN_INFO_SAMP_FREQ
:
286 ret
= regmap_read(data
->regmap
, ADXL313_REG_BW_RATE
, ®val
);
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
;
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
);
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
)
314 return regmap_write(data
->regmap
,
315 ADXL313_REG_OFS_AXIS(chan
->address
),
317 case IIO_CHAN_INFO_SAMP_FREQ
:
318 return adxl313_set_odr(data
, val
, val2
);
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
*))
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
,
347 ret
= setup(dev
, data
->regmap
);
352 ret
= data
->chip_info
->check_id(dev
, data
);
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
,
360 FIELD_PREP(ADXL313_RANGE_MSK
, ADXL313_RANGE_MAX
));
364 /* Enables full resolution */
365 ret
= regmap_update_bits(data
->regmap
, ADXL313_REG_DATA_FORMAT
,
366 ADXL313_FULL_RES
, ADXL313_FULL_RES
);
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
;
396 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
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
);
414 dev_err(dev
, "ADXL313 setup failed\n");
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");