iio: accel: add support for mxc4005 accelerometer
[firefly-linux-kernel-4.4.55.git] / drivers / iio / accel / mxc4005.c
1 /*
2  * 3-axis accelerometer driver for MXC4005XC Memsic sensor
3  *
4  * Copyright (c) 2014, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  */
15
16 #include <linux/module.h>
17 #include <linux/i2c.h>
18 #include <linux/iio/iio.h>
19 #include <linux/acpi.h>
20 #include <linux/regmap.h>
21 #include <linux/iio/sysfs.h>
22
23 #define MXC4005_DRV_NAME                "mxc4005"
24 #define MXC4005_REGMAP_NAME             "mxc4005_regmap"
25
26 #define MXC4005_REG_XOUT_UPPER          0x03
27 #define MXC4005_REG_XOUT_LOWER          0x04
28 #define MXC4005_REG_YOUT_UPPER          0x05
29 #define MXC4005_REG_YOUT_LOWER          0x06
30 #define MXC4005_REG_ZOUT_UPPER          0x07
31 #define MXC4005_REG_ZOUT_LOWER          0x08
32
33 #define MXC4005_REG_CONTROL             0x0D
34 #define MXC4005_REG_CONTROL_MASK_FSR    GENMASK(6, 5)
35 #define MXC4005_CONTROL_FSR_SHIFT       5
36
37 #define MXC4005_REG_DEVICE_ID           0x0E
38
39 enum mxc4005_axis {
40         AXIS_X,
41         AXIS_Y,
42         AXIS_Z,
43 };
44
45 enum mxc4005_range {
46         MXC4005_RANGE_2G,
47         MXC4005_RANGE_4G,
48         MXC4005_RANGE_8G,
49 };
50
51 struct mxc4005_data {
52         struct device *dev;
53         struct mutex mutex;
54         struct regmap *regmap;
55 };
56
57 /*
58  * MXC4005 can operate in the following ranges:
59  * +/- 2G, 4G, 8G (the default +/-2G)
60  *
61  * (2 + 2) * 9.81 / (2^12 - 1) = 0.009582
62  * (4 + 4) * 9.81 / (2^12 - 1) = 0.019164
63  * (8 + 8) * 9.81 / (2^12 - 1) = 0.038329
64  */
65 static const struct {
66         u8 range;
67         int scale;
68 } mxc4005_scale_table[] = {
69         {MXC4005_RANGE_2G, 9582},
70         {MXC4005_RANGE_4G, 19164},
71         {MXC4005_RANGE_8G, 38329},
72 };
73
74
75 static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019164 0.038329");
76
77 static struct attribute *mxc4005_attributes[] = {
78         &iio_const_attr_in_accel_scale_available.dev_attr.attr,
79         NULL,
80 };
81
82 static const struct attribute_group mxc4005_attrs_group = {
83         .attrs = mxc4005_attributes,
84 };
85
86 static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg)
87 {
88         switch (reg) {
89         case MXC4005_REG_XOUT_UPPER:
90         case MXC4005_REG_XOUT_LOWER:
91         case MXC4005_REG_YOUT_UPPER:
92         case MXC4005_REG_YOUT_LOWER:
93         case MXC4005_REG_ZOUT_UPPER:
94         case MXC4005_REG_ZOUT_LOWER:
95         case MXC4005_REG_DEVICE_ID:
96         case MXC4005_REG_CONTROL:
97                 return true;
98         default:
99                 return false;
100         }
101 }
102
103 static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg)
104 {
105         switch (reg) {
106         case MXC4005_REG_CONTROL:
107                 return true;
108         default:
109                 return false;
110         }
111 }
112
113 static const struct regmap_config mxc4005_regmap_config = {
114         .name = MXC4005_REGMAP_NAME,
115
116         .reg_bits = 8,
117         .val_bits = 8,
118
119         .max_register = MXC4005_REG_DEVICE_ID,
120
121         .readable_reg = mxc4005_is_readable_reg,
122         .writeable_reg = mxc4005_is_writeable_reg,
123 };
124
125 static int mxc4005_read_axis(struct mxc4005_data *data,
126                              unsigned int addr)
127 {
128         __be16 reg;
129         int ret;
130
131         ret = regmap_bulk_read(data->regmap, addr, (u8 *) &reg, sizeof(reg));
132         if (ret < 0) {
133                 dev_err(data->dev, "failed to read reg %02x\n", addr);
134                 return ret;
135         }
136
137         return be16_to_cpu(reg);
138 }
139
140 static int mxc4005_read_scale(struct mxc4005_data *data)
141 {
142         unsigned int reg;
143         int ret;
144         int i;
145
146         ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &reg);
147         if (ret < 0) {
148                 dev_err(data->dev, "failed to read reg_control\n");
149                 return ret;
150         }
151
152         i = reg >> MXC4005_CONTROL_FSR_SHIFT;
153
154         if (i < 0 || i >= ARRAY_SIZE(mxc4005_scale_table))
155                 return -EINVAL;
156
157         return mxc4005_scale_table[i].scale;
158 }
159
160 static int mxc4005_set_scale(struct mxc4005_data *data, int val)
161 {
162         unsigned int reg;
163         int i;
164         int ret;
165
166         for (i = 0; i < ARRAY_SIZE(mxc4005_scale_table); i++) {
167                 if (mxc4005_scale_table[i].scale == val) {
168                         reg = i << MXC4005_CONTROL_FSR_SHIFT;
169                         ret = regmap_update_bits(data->regmap,
170                                                  MXC4005_REG_CONTROL,
171                                                  MXC4005_REG_CONTROL_MASK_FSR,
172                                                  reg);
173                         if (ret < 0)
174                                 dev_err(data->dev,
175                                         "failed to write reg_control\n");
176                         return ret;
177                 }
178         }
179
180         return -EINVAL;
181 }
182
183 static int mxc4005_read_raw(struct iio_dev *indio_dev,
184                             struct iio_chan_spec const *chan,
185                             int *val, int *val2, long mask)
186 {
187         struct mxc4005_data *data = iio_priv(indio_dev);
188         int ret;
189
190         switch (mask) {
191         case IIO_CHAN_INFO_RAW:
192                 switch (chan->type) {
193                 case IIO_ACCEL:
194                         if (iio_buffer_enabled(indio_dev))
195                                 return -EBUSY;
196
197                         ret = mxc4005_read_axis(data, chan->address);
198                         if (ret < 0)
199                                 return ret;
200                         *val = sign_extend32(ret >> 4, 11);
201                         return IIO_VAL_INT;
202                 default:
203                         return -EINVAL;
204                 }
205         case IIO_CHAN_INFO_SCALE:
206                 ret = mxc4005_read_scale(data);
207                 if (ret < 0)
208                         return ret;
209
210                 *val = 0;
211                 *val2 = ret;
212                 return IIO_VAL_INT_PLUS_MICRO;
213         default:
214                 return -EINVAL;
215         }
216 }
217
218 static int mxc4005_write_raw(struct iio_dev *indio_dev,
219                              struct iio_chan_spec const *chan,
220                              int val, int val2, long mask)
221 {
222         struct mxc4005_data *data = iio_priv(indio_dev);
223
224         switch (mask) {
225         case IIO_CHAN_INFO_SCALE:
226                 if (val != 0)
227                         return -EINVAL;
228
229                 return mxc4005_set_scale(data, val2);
230         default:
231                 return -EINVAL;
232         }
233 }
234
235 static const struct iio_info mxc4005_info = {
236         .driver_module  = THIS_MODULE,
237         .read_raw       = mxc4005_read_raw,
238         .write_raw      = mxc4005_write_raw,
239         .attrs          = &mxc4005_attrs_group,
240 };
241
242 #define MXC4005_CHANNEL(_axis, _addr) {                         \
243         .type = IIO_ACCEL,                                      \
244         .modified = 1,                                          \
245         .channel2 = IIO_MOD_##_axis,                            \
246         .address = _addr,                                       \
247         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
248         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
249 }
250
251 static const struct iio_chan_spec mxc4005_channels[] = {
252         MXC4005_CHANNEL(X, MXC4005_REG_XOUT_UPPER),
253         MXC4005_CHANNEL(Y, MXC4005_REG_YOUT_UPPER),
254         MXC4005_CHANNEL(Z, MXC4005_REG_ZOUT_UPPER),
255 };
256
257 static int mxc4005_chip_init(struct mxc4005_data *data)
258 {
259         int ret;
260         unsigned int reg;
261
262         ret = regmap_read(data->regmap, MXC4005_REG_DEVICE_ID, &reg);
263         if (ret < 0) {
264                 dev_err(data->dev, "failed to read chip id\n");
265                 return ret;
266         }
267
268         dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
269
270         return 0;
271 }
272
273 static int mxc4005_probe(struct i2c_client *client,
274                          const struct i2c_device_id *id)
275 {
276         struct mxc4005_data *data;
277         struct iio_dev *indio_dev;
278         struct regmap *regmap;
279         int ret;
280
281         indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
282         if (!indio_dev)
283                 return -ENOMEM;
284
285         regmap = devm_regmap_init_i2c(client, &mxc4005_regmap_config);
286         if (IS_ERR(regmap)) {
287                 dev_err(&client->dev, "failed to initialize regmap\n");
288                 return PTR_ERR(regmap);
289         }
290
291         data = iio_priv(indio_dev);
292         i2c_set_clientdata(client, indio_dev);
293         data->dev = &client->dev;
294         data->regmap = regmap;
295
296         ret = mxc4005_chip_init(data);
297         if (ret < 0) {
298                 dev_err(&client->dev, "failed to initialize chip\n");
299                 return ret;
300         }
301
302         mutex_init(&data->mutex);
303
304         indio_dev->dev.parent = &client->dev;
305         indio_dev->channels = mxc4005_channels;
306         indio_dev->num_channels = ARRAY_SIZE(mxc4005_channels);
307         indio_dev->name = MXC4005_DRV_NAME;
308         indio_dev->modes = INDIO_DIRECT_MODE;
309         indio_dev->info = &mxc4005_info;
310
311         ret = iio_device_register(indio_dev);
312         if (ret < 0) {
313                 dev_err(&client->dev,
314                         "unable to register iio device %d\n", ret);
315                 return ret;
316         }
317
318         return 0;
319 }
320
321 static int mxc4005_remove(struct i2c_client *client)
322 {
323         iio_device_unregister(i2c_get_clientdata(client));
324
325         return 0;
326 }
327
328 static const struct acpi_device_id mxc4005_acpi_match[] = {
329         {"MXC4005",     0},
330         { },
331 };
332 MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
333
334 static const struct i2c_device_id mxc4005_id[] = {
335         {"mxc4005",     0},
336         { },
337 };
338 MODULE_DEVICE_TABLE(i2c, mxc4005_id);
339
340 static struct i2c_driver mxc4005_driver = {
341         .driver = {
342                 .name = MXC4005_DRV_NAME,
343                 .acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
344         },
345         .probe          = mxc4005_probe,
346         .remove         = mxc4005_remove,
347         .id_table       = mxc4005_id,
348 };
349
350 module_i2c_driver(mxc4005_driver);
351
352 MODULE_AUTHOR("Teodora Baluta <teodora.baluta@intel.com>");
353 MODULE_LICENSE("GPL v2");
354 MODULE_DESCRIPTION("MXC4005 3-axis accelerometer driver");