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