GNU Linux-libre 5.16.19-gnu
[releases.git] / drivers / iio / accel / adxl345_core.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ADXL345 3-Axis Digital Accelerometer IIO core driver
4  *
5  * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
6  *
7  * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf
8  */
9
10 #include <linux/module.h>
11 #include <linux/regmap.h>
12
13 #include <linux/iio/iio.h>
14 #include <linux/iio/sysfs.h>
15
16 #include "adxl345.h"
17
18 #define ADXL345_REG_DEVID               0x00
19 #define ADXL345_REG_OFSX                0x1e
20 #define ADXL345_REG_OFSY                0x1f
21 #define ADXL345_REG_OFSZ                0x20
22 #define ADXL345_REG_OFS_AXIS(index)     (ADXL345_REG_OFSX + (index))
23 #define ADXL345_REG_BW_RATE             0x2C
24 #define ADXL345_REG_POWER_CTL           0x2D
25 #define ADXL345_REG_DATA_FORMAT         0x31
26 #define ADXL345_REG_DATAX0              0x32
27 #define ADXL345_REG_DATAY0              0x34
28 #define ADXL345_REG_DATAZ0              0x36
29 #define ADXL345_REG_DATA_AXIS(index)    \
30         (ADXL345_REG_DATAX0 + (index) * sizeof(__le16))
31
32 #define ADXL345_BW_RATE                 GENMASK(3, 0)
33 #define ADXL345_BASE_RATE_NANO_HZ       97656250LL
34 #define NHZ_PER_HZ                      1000000000LL
35
36 #define ADXL345_POWER_CTL_MEASURE       BIT(3)
37 #define ADXL345_POWER_CTL_STANDBY       0x00
38
39 #define ADXL345_DATA_FORMAT_FULL_RES    BIT(3) /* Up to 13-bits resolution */
40 #define ADXL345_DATA_FORMAT_2G          0
41 #define ADXL345_DATA_FORMAT_4G          1
42 #define ADXL345_DATA_FORMAT_8G          2
43 #define ADXL345_DATA_FORMAT_16G         3
44
45 #define ADXL345_DEVID                   0xE5
46
47 /*
48  * In full-resolution mode, scale factor is maintained at ~4 mg/LSB
49  * in all g ranges.
50  *
51  * At +/- 16g with 13-bit resolution, scale is computed as:
52  * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
53  */
54 static const int adxl345_uscale = 38300;
55
56 /*
57  * The Datasheet lists a resolution of Resolution is ~49 mg per LSB. That's
58  * ~480mm/s**2 per LSB.
59  */
60 static const int adxl375_uscale = 480000;
61
62 struct adxl345_data {
63         struct regmap *regmap;
64         u8 data_range;
65         enum adxl345_device_type type;
66 };
67
68 #define ADXL345_CHANNEL(index, axis) {                                  \
69         .type = IIO_ACCEL,                                              \
70         .modified = 1,                                                  \
71         .channel2 = IIO_MOD_##axis,                                     \
72         .address = index,                                               \
73         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |                  \
74                 BIT(IIO_CHAN_INFO_CALIBBIAS),                           \
75         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |          \
76                 BIT(IIO_CHAN_INFO_SAMP_FREQ),                           \
77 }
78
79 static const struct iio_chan_spec adxl345_channels[] = {
80         ADXL345_CHANNEL(0, X),
81         ADXL345_CHANNEL(1, Y),
82         ADXL345_CHANNEL(2, Z),
83 };
84
85 static int adxl345_read_raw(struct iio_dev *indio_dev,
86                             struct iio_chan_spec const *chan,
87                             int *val, int *val2, long mask)
88 {
89         struct adxl345_data *data = iio_priv(indio_dev);
90         __le16 accel;
91         long long samp_freq_nhz;
92         unsigned int regval;
93         int ret;
94
95         switch (mask) {
96         case IIO_CHAN_INFO_RAW:
97                 /*
98                  * Data is stored in adjacent registers:
99                  * ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
100                  * and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
101                  */
102                 ret = regmap_bulk_read(data->regmap,
103                                        ADXL345_REG_DATA_AXIS(chan->address),
104                                        &accel, sizeof(accel));
105                 if (ret < 0)
106                         return ret;
107
108                 *val = sign_extend32(le16_to_cpu(accel), 12);
109                 return IIO_VAL_INT;
110         case IIO_CHAN_INFO_SCALE:
111                 *val = 0;
112                 switch (data->type) {
113                 case ADXL345:
114                         *val2 = adxl345_uscale;
115                         break;
116                 case ADXL375:
117                         *val2 = adxl375_uscale;
118                         break;
119                 }
120
121                 return IIO_VAL_INT_PLUS_MICRO;
122         case IIO_CHAN_INFO_CALIBBIAS:
123                 ret = regmap_read(data->regmap,
124                                   ADXL345_REG_OFS_AXIS(chan->address), &regval);
125                 if (ret < 0)
126                         return ret;
127                 /*
128                  * 8-bit resolution at +/- 2g, that is 4x accel data scale
129                  * factor
130                  */
131                 *val = sign_extend32(regval, 7) * 4;
132
133                 return IIO_VAL_INT;
134         case IIO_CHAN_INFO_SAMP_FREQ:
135                 ret = regmap_read(data->regmap, ADXL345_REG_BW_RATE, &regval);
136                 if (ret < 0)
137                         return ret;
138
139                 samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ <<
140                                 (regval & ADXL345_BW_RATE);
141                 *val = div_s64_rem(samp_freq_nhz, NHZ_PER_HZ, val2);
142
143                 return IIO_VAL_INT_PLUS_NANO;
144         }
145
146         return -EINVAL;
147 }
148
149 static int adxl345_write_raw(struct iio_dev *indio_dev,
150                              struct iio_chan_spec const *chan,
151                              int val, int val2, long mask)
152 {
153         struct adxl345_data *data = iio_priv(indio_dev);
154         s64 n;
155
156         switch (mask) {
157         case IIO_CHAN_INFO_CALIBBIAS:
158                 /*
159                  * 8-bit resolution at +/- 2g, that is 4x accel data scale
160                  * factor
161                  */
162                 return regmap_write(data->regmap,
163                                     ADXL345_REG_OFS_AXIS(chan->address),
164                                     val / 4);
165         case IIO_CHAN_INFO_SAMP_FREQ:
166                 n = div_s64(val * NHZ_PER_HZ + val2, ADXL345_BASE_RATE_NANO_HZ);
167
168                 return regmap_update_bits(data->regmap, ADXL345_REG_BW_RATE,
169                                           ADXL345_BW_RATE,
170                                           clamp_val(ilog2(n), 0,
171                                                     ADXL345_BW_RATE));
172         }
173
174         return -EINVAL;
175 }
176
177 static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev,
178                                      struct iio_chan_spec const *chan,
179                                      long mask)
180 {
181         switch (mask) {
182         case IIO_CHAN_INFO_CALIBBIAS:
183                 return IIO_VAL_INT;
184         case IIO_CHAN_INFO_SAMP_FREQ:
185                 return IIO_VAL_INT_PLUS_NANO;
186         default:
187                 return -EINVAL;
188         }
189 }
190
191 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
192 "0.09765625 0.1953125 0.390625 0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600 3200"
193 );
194
195 static struct attribute *adxl345_attrs[] = {
196         &iio_const_attr_sampling_frequency_available.dev_attr.attr,
197         NULL,
198 };
199
200 static const struct attribute_group adxl345_attrs_group = {
201         .attrs = adxl345_attrs,
202 };
203
204 static const struct iio_info adxl345_info = {
205         .attrs          = &adxl345_attrs_group,
206         .read_raw       = adxl345_read_raw,
207         .write_raw      = adxl345_write_raw,
208         .write_raw_get_fmt      = adxl345_write_raw_get_fmt,
209 };
210
211 static void adxl345_powerdown(void *regmap)
212 {
213         regmap_write(regmap, ADXL345_REG_POWER_CTL, ADXL345_POWER_CTL_STANDBY);
214 }
215
216 int adxl345_core_probe(struct device *dev, struct regmap *regmap,
217                        enum adxl345_device_type type, const char *name)
218 {
219         struct adxl345_data *data;
220         struct iio_dev *indio_dev;
221         u32 regval;
222         int ret;
223
224         ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
225         if (ret < 0) {
226                 dev_err(dev, "Error reading device ID: %d\n", ret);
227                 return ret;
228         }
229
230         if (regval != ADXL345_DEVID) {
231                 dev_err(dev, "Invalid device ID: %x, expected %x\n",
232                         regval, ADXL345_DEVID);
233                 return -ENODEV;
234         }
235
236         indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
237         if (!indio_dev)
238                 return -ENOMEM;
239
240         data = iio_priv(indio_dev);
241         data->regmap = regmap;
242         data->type = type;
243         /* Enable full-resolution mode */
244         data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
245
246         ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
247                            data->data_range);
248         if (ret < 0) {
249                 dev_err(dev, "Failed to set data range: %d\n", ret);
250                 return ret;
251         }
252
253         indio_dev->name = name;
254         indio_dev->info = &adxl345_info;
255         indio_dev->modes = INDIO_DIRECT_MODE;
256         indio_dev->channels = adxl345_channels;
257         indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
258
259         /* Enable measurement mode */
260         ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
261                            ADXL345_POWER_CTL_MEASURE);
262         if (ret < 0) {
263                 dev_err(dev, "Failed to enable measurement mode: %d\n", ret);
264                 return ret;
265         }
266
267         ret = devm_add_action_or_reset(dev, adxl345_powerdown, data->regmap);
268         if (ret < 0)
269                 return ret;
270
271         return devm_iio_device_register(dev, indio_dev);
272 }
273 EXPORT_SYMBOL_GPL(adxl345_core_probe);
274
275 MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
276 MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
277 MODULE_LICENSE("GPL v2");