proc: Fix proc_sys_prune_dcache to hold a sb reference
[cris-mirror.git] / drivers / iio / accel / adxl345_core.c
blob9ccb5828db986def7c1531b5196457995b909190
1 /*
2 * ADXL345 3-Axis Digital Accelerometer IIO core driver
4 * Copyright (c) 2017 Eva Rachel Retuya <eraretuya@gmail.com>
6 * This file is subject to the terms and conditions of version 2 of
7 * the GNU General Public License. See the file COPYING in the main
8 * directory of this archive for more details.
9 */
11 #include <linux/module.h>
12 #include <linux/regmap.h>
14 #include <linux/iio/iio.h>
16 #include "adxl345.h"
18 #define ADXL345_REG_DEVID 0x00
19 #define ADXL345_REG_POWER_CTL 0x2D
20 #define ADXL345_REG_DATA_FORMAT 0x31
21 #define ADXL345_REG_DATAX0 0x32
22 #define ADXL345_REG_DATAY0 0x34
23 #define ADXL345_REG_DATAZ0 0x36
25 #define ADXL345_POWER_CTL_MEASURE BIT(3)
26 #define ADXL345_POWER_CTL_STANDBY 0x00
28 #define ADXL345_DATA_FORMAT_FULL_RES BIT(3) /* Up to 13-bits resolution */
29 #define ADXL345_DATA_FORMAT_2G 0
30 #define ADXL345_DATA_FORMAT_4G 1
31 #define ADXL345_DATA_FORMAT_8G 2
32 #define ADXL345_DATA_FORMAT_16G 3
34 #define ADXL345_DEVID 0xE5
37 * In full-resolution mode, scale factor is maintained at ~4 mg/LSB
38 * in all g ranges.
40 * At +/- 16g with 13-bit resolution, scale is computed as:
41 * (16 + 16) * 9.81 / (2^13 - 1) = 0.0383
43 static const int adxl345_uscale = 38300;
45 struct adxl345_data {
46 struct regmap *regmap;
47 u8 data_range;
50 #define ADXL345_CHANNEL(reg, axis) { \
51 .type = IIO_ACCEL, \
52 .modified = 1, \
53 .channel2 = IIO_MOD_##axis, \
54 .address = reg, \
55 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
56 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
59 static const struct iio_chan_spec adxl345_channels[] = {
60 ADXL345_CHANNEL(ADXL345_REG_DATAX0, X),
61 ADXL345_CHANNEL(ADXL345_REG_DATAY0, Y),
62 ADXL345_CHANNEL(ADXL345_REG_DATAZ0, Z),
65 static int adxl345_read_raw(struct iio_dev *indio_dev,
66 struct iio_chan_spec const *chan,
67 int *val, int *val2, long mask)
69 struct adxl345_data *data = iio_priv(indio_dev);
70 __le16 regval;
71 int ret;
73 switch (mask) {
74 case IIO_CHAN_INFO_RAW:
76 * Data is stored in adjacent registers:
77 * ADXL345_REG_DATA(X0/Y0/Z0) contain the least significant byte
78 * and ADXL345_REG_DATA(X0/Y0/Z0) + 1 the most significant byte
80 ret = regmap_bulk_read(data->regmap, chan->address, &regval,
81 sizeof(regval));
82 if (ret < 0)
83 return ret;
85 *val = sign_extend32(le16_to_cpu(regval), 12);
86 return IIO_VAL_INT;
87 case IIO_CHAN_INFO_SCALE:
88 *val = 0;
89 *val2 = adxl345_uscale;
91 return IIO_VAL_INT_PLUS_MICRO;
94 return -EINVAL;
97 static const struct iio_info adxl345_info = {
98 .driver_module = THIS_MODULE,
99 .read_raw = adxl345_read_raw,
102 int adxl345_core_probe(struct device *dev, struct regmap *regmap,
103 const char *name)
105 struct adxl345_data *data;
106 struct iio_dev *indio_dev;
107 u32 regval;
108 int ret;
110 ret = regmap_read(regmap, ADXL345_REG_DEVID, &regval);
111 if (ret < 0) {
112 dev_err(dev, "Error reading device ID: %d\n", ret);
113 return ret;
116 if (regval != ADXL345_DEVID) {
117 dev_err(dev, "Invalid device ID: %x, expected %x\n",
118 regval, ADXL345_DEVID);
119 return -ENODEV;
122 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
123 if (!indio_dev)
124 return -ENOMEM;
126 data = iio_priv(indio_dev);
127 dev_set_drvdata(dev, indio_dev);
128 data->regmap = regmap;
129 /* Enable full-resolution mode */
130 data->data_range = ADXL345_DATA_FORMAT_FULL_RES;
132 ret = regmap_write(data->regmap, ADXL345_REG_DATA_FORMAT,
133 data->data_range);
134 if (ret < 0) {
135 dev_err(dev, "Failed to set data range: %d\n", ret);
136 return ret;
139 indio_dev->dev.parent = dev;
140 indio_dev->name = name;
141 indio_dev->info = &adxl345_info;
142 indio_dev->modes = INDIO_DIRECT_MODE;
143 indio_dev->channels = adxl345_channels;
144 indio_dev->num_channels = ARRAY_SIZE(adxl345_channels);
146 /* Enable measurement mode */
147 ret = regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
148 ADXL345_POWER_CTL_MEASURE);
149 if (ret < 0) {
150 dev_err(dev, "Failed to enable measurement mode: %d\n", ret);
151 return ret;
154 ret = iio_device_register(indio_dev);
155 if (ret < 0) {
156 dev_err(dev, "iio_device_register failed: %d\n", ret);
157 regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
158 ADXL345_POWER_CTL_STANDBY);
161 return ret;
163 EXPORT_SYMBOL_GPL(adxl345_core_probe);
165 int adxl345_core_remove(struct device *dev)
167 struct iio_dev *indio_dev = dev_get_drvdata(dev);
168 struct adxl345_data *data = iio_priv(indio_dev);
170 iio_device_unregister(indio_dev);
172 return regmap_write(data->regmap, ADXL345_REG_POWER_CTL,
173 ADXL345_POWER_CTL_STANDBY);
175 EXPORT_SYMBOL_GPL(adxl345_core_remove);
177 MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
178 MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
179 MODULE_LICENSE("GPL v2");