GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / iio / imu / fxos8700_core.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * FXOS8700 - NXP IMU (accelerometer plus magnetometer)
4  *
5  * IIO core driver for FXOS8700, with support for I2C/SPI busses
6  *
7  * TODO: Buffer, trigger, and IRQ support
8  */
9 #include <linux/module.h>
10 #include <linux/regmap.h>
11 #include <linux/acpi.h>
12 #include <linux/bitops.h>
13 #include <linux/bitfield.h>
14
15 #include <linux/iio/iio.h>
16 #include <linux/iio/sysfs.h>
17
18 #include "fxos8700.h"
19
20 /* Register Definitions */
21 #define FXOS8700_STATUS             0x00
22 #define FXOS8700_OUT_X_MSB          0x01
23 #define FXOS8700_OUT_X_LSB          0x02
24 #define FXOS8700_OUT_Y_MSB          0x03
25 #define FXOS8700_OUT_Y_LSB          0x04
26 #define FXOS8700_OUT_Z_MSB          0x05
27 #define FXOS8700_OUT_Z_LSB          0x06
28 #define FXOS8700_F_SETUP            0x09
29 #define FXOS8700_TRIG_CFG           0x0a
30 #define FXOS8700_SYSMOD             0x0b
31 #define FXOS8700_INT_SOURCE         0x0c
32 #define FXOS8700_WHO_AM_I           0x0d
33 #define FXOS8700_XYZ_DATA_CFG       0x0e
34 #define FXOS8700_HP_FILTER_CUTOFF   0x0f
35 #define FXOS8700_PL_STATUS          0x10
36 #define FXOS8700_PL_CFG             0x11
37 #define FXOS8700_PL_COUNT           0x12
38 #define FXOS8700_PL_BF_ZCOMP        0x13
39 #define FXOS8700_PL_THS_REG         0x14
40 #define FXOS8700_A_FFMT_CFG         0x15
41 #define FXOS8700_A_FFMT_SRC         0x16
42 #define FXOS8700_A_FFMT_THS         0x17
43 #define FXOS8700_A_FFMT_COUNT       0x18
44 #define FXOS8700_TRANSIENT_CFG      0x1d
45 #define FXOS8700_TRANSIENT_SRC      0x1e
46 #define FXOS8700_TRANSIENT_THS      0x1f
47 #define FXOS8700_TRANSIENT_COUNT    0x20
48 #define FXOS8700_PULSE_CFG          0x21
49 #define FXOS8700_PULSE_SRC          0x22
50 #define FXOS8700_PULSE_THSX         0x23
51 #define FXOS8700_PULSE_THSY         0x24
52 #define FXOS8700_PULSE_THSZ         0x25
53 #define FXOS8700_PULSE_TMLT         0x26
54 #define FXOS8700_PULSE_LTCY         0x27
55 #define FXOS8700_PULSE_WIND         0x28
56 #define FXOS8700_ASLP_COUNT         0x29
57 #define FXOS8700_CTRL_REG1          0x2a
58 #define FXOS8700_CTRL_REG2          0x2b
59 #define FXOS8700_CTRL_REG3          0x2c
60 #define FXOS8700_CTRL_REG4          0x2d
61 #define FXOS8700_CTRL_REG5          0x2e
62 #define FXOS8700_OFF_X              0x2f
63 #define FXOS8700_OFF_Y              0x30
64 #define FXOS8700_OFF_Z              0x31
65 #define FXOS8700_M_DR_STATUS        0x32
66 #define FXOS8700_M_OUT_X_MSB        0x33
67 #define FXOS8700_M_OUT_X_LSB        0x34
68 #define FXOS8700_M_OUT_Y_MSB        0x35
69 #define FXOS8700_M_OUT_Y_LSB        0x36
70 #define FXOS8700_M_OUT_Z_MSB        0x37
71 #define FXOS8700_M_OUT_Z_LSB        0x38
72 #define FXOS8700_CMP_X_MSB          0x39
73 #define FXOS8700_CMP_X_LSB          0x3a
74 #define FXOS8700_CMP_Y_MSB          0x3b
75 #define FXOS8700_CMP_Y_LSB          0x3c
76 #define FXOS8700_CMP_Z_MSB          0x3d
77 #define FXOS8700_CMP_Z_LSB          0x3e
78 #define FXOS8700_M_OFF_X_MSB        0x3f
79 #define FXOS8700_M_OFF_X_LSB        0x40
80 #define FXOS8700_M_OFF_Y_MSB        0x41
81 #define FXOS8700_M_OFF_Y_LSB        0x42
82 #define FXOS8700_M_OFF_Z_MSB        0x43
83 #define FXOS8700_M_OFF_Z_LSB        0x44
84 #define FXOS8700_MAX_X_MSB          0x45
85 #define FXOS8700_MAX_X_LSB          0x46
86 #define FXOS8700_MAX_Y_MSB          0x47
87 #define FXOS8700_MAX_Y_LSB          0x48
88 #define FXOS8700_MAX_Z_MSB          0x49
89 #define FXOS8700_MAX_Z_LSB          0x4a
90 #define FXOS8700_MIN_X_MSB          0x4b
91 #define FXOS8700_MIN_X_LSB          0x4c
92 #define FXOS8700_MIN_Y_MSB          0x4d
93 #define FXOS8700_MIN_Y_LSB          0x4e
94 #define FXOS8700_MIN_Z_MSB          0x4f
95 #define FXOS8700_MIN_Z_LSB          0x50
96 #define FXOS8700_TEMP               0x51
97 #define FXOS8700_M_THS_CFG          0x52
98 #define FXOS8700_M_THS_SRC          0x53
99 #define FXOS8700_M_THS_X_MSB        0x54
100 #define FXOS8700_M_THS_X_LSB        0x55
101 #define FXOS8700_M_THS_Y_MSB        0x56
102 #define FXOS8700_M_THS_Y_LSB        0x57
103 #define FXOS8700_M_THS_Z_MSB        0x58
104 #define FXOS8700_M_THS_Z_LSB        0x59
105 #define FXOS8700_M_THS_COUNT        0x5a
106 #define FXOS8700_M_CTRL_REG1        0x5b
107 #define FXOS8700_M_CTRL_REG2        0x5c
108 #define FXOS8700_M_CTRL_REG3        0x5d
109 #define FXOS8700_M_INT_SRC          0x5e
110 #define FXOS8700_A_VECM_CFG         0x5f
111 #define FXOS8700_A_VECM_THS_MSB     0x60
112 #define FXOS8700_A_VECM_THS_LSB     0x61
113 #define FXOS8700_A_VECM_CNT         0x62
114 #define FXOS8700_A_VECM_INITX_MSB   0x63
115 #define FXOS8700_A_VECM_INITX_LSB   0x64
116 #define FXOS8700_A_VECM_INITY_MSB   0x65
117 #define FXOS8700_A_VECM_INITY_LSB   0x66
118 #define FXOS8700_A_VECM_INITZ_MSB   0x67
119 #define FXOS8700_A_VECM_INITZ_LSB   0x68
120 #define FXOS8700_M_VECM_CFG         0x69
121 #define FXOS8700_M_VECM_THS_MSB     0x6a
122 #define FXOS8700_M_VECM_THS_LSB     0x6b
123 #define FXOS8700_M_VECM_CNT         0x6c
124 #define FXOS8700_M_VECM_INITX_MSB   0x6d
125 #define FXOS8700_M_VECM_INITX_LSB   0x6e
126 #define FXOS8700_M_VECM_INITY_MSB   0x6f
127 #define FXOS8700_M_VECM_INITY_LSB   0x70
128 #define FXOS8700_M_VECM_INITZ_MSB   0x71
129 #define FXOS8700_M_VECM_INITZ_LSB   0x72
130 #define FXOS8700_A_FFMT_THS_X_MSB   0x73
131 #define FXOS8700_A_FFMT_THS_X_LSB   0x74
132 #define FXOS8700_A_FFMT_THS_Y_MSB   0x75
133 #define FXOS8700_A_FFMT_THS_Y_LSB   0x76
134 #define FXOS8700_A_FFMT_THS_Z_MSB   0x77
135 #define FXOS8700_A_FFMT_THS_Z_LSB   0x78
136 #define FXOS8700_A_TRAN_INIT_MSB    0x79
137 #define FXOS8700_A_TRAN_INIT_LSB_X  0x7a
138 #define FXOS8700_A_TRAN_INIT_LSB_Y  0x7b
139 #define FXOS8700_A_TRAN_INIT_LSB_Z  0x7d
140 #define FXOS8700_TM_NVM_LOCK        0x7e
141 #define FXOS8700_NVM_DATA0_35       0x80
142 #define FXOS8700_NVM_DATA_BNK3      0xa4
143 #define FXOS8700_NVM_DATA_BNK2      0xa5
144 #define FXOS8700_NVM_DATA_BNK1      0xa6
145 #define FXOS8700_NVM_DATA_BNK0      0xa7
146
147 /* Bit definitions for FXOS8700_CTRL_REG1 */
148 #define FXOS8700_CTRL_ODR_MAX       0x00
149 #define FXOS8700_CTRL_ODR_MSK       GENMASK(5, 3)
150
151 /* Bit definitions for FXOS8700_M_CTRL_REG1 */
152 #define FXOS8700_HMS_MASK           GENMASK(1, 0)
153 #define FXOS8700_OS_MASK            GENMASK(4, 2)
154
155 /* Bit definitions for FXOS8700_M_CTRL_REG2 */
156 #define FXOS8700_MAXMIN_RST         BIT(2)
157 #define FXOS8700_MAXMIN_DIS_THS     BIT(3)
158 #define FXOS8700_MAXMIN_DIS         BIT(4)
159
160 #define FXOS8700_ACTIVE             0x01
161 #define FXOS8700_ACTIVE_MIN_USLEEP  4000 /* from table 6 in datasheet */
162
163 #define FXOS8700_DEVICE_ID          0xC7
164 #define FXOS8700_PRE_DEVICE_ID      0xC4
165 #define FXOS8700_DATA_BUF_SIZE      3
166
167 struct fxos8700_data {
168         struct regmap *regmap;
169         struct iio_trigger *trig;
170         __be16 buf[FXOS8700_DATA_BUF_SIZE] __aligned(IIO_DMA_MINALIGN);
171 };
172
173 /* Regmap info */
174 static const struct regmap_range read_range[] = {
175         {
176                 .range_min = FXOS8700_STATUS,
177                 .range_max = FXOS8700_A_FFMT_COUNT,
178         }, {
179                 .range_min = FXOS8700_TRANSIENT_CFG,
180                 .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
181         },
182 };
183
184 static const struct regmap_range write_range[] = {
185         {
186                 .range_min = FXOS8700_F_SETUP,
187                 .range_max = FXOS8700_TRIG_CFG,
188         }, {
189                 .range_min = FXOS8700_XYZ_DATA_CFG,
190                 .range_max = FXOS8700_HP_FILTER_CUTOFF,
191         }, {
192                 .range_min = FXOS8700_PL_CFG,
193                 .range_max = FXOS8700_A_FFMT_CFG,
194         }, {
195                 .range_min = FXOS8700_A_FFMT_THS,
196                 .range_max = FXOS8700_TRANSIENT_CFG,
197         }, {
198                 .range_min = FXOS8700_TRANSIENT_THS,
199                 .range_max = FXOS8700_PULSE_CFG,
200         }, {
201                 .range_min = FXOS8700_PULSE_THSX,
202                 .range_max = FXOS8700_OFF_Z,
203         }, {
204                 .range_min = FXOS8700_M_OFF_X_MSB,
205                 .range_max = FXOS8700_M_OFF_Z_LSB,
206         }, {
207                 .range_min = FXOS8700_M_THS_CFG,
208                 .range_max = FXOS8700_M_THS_CFG,
209         }, {
210                 .range_min = FXOS8700_M_THS_X_MSB,
211                 .range_max = FXOS8700_M_CTRL_REG3,
212         }, {
213                 .range_min = FXOS8700_A_VECM_CFG,
214                 .range_max = FXOS8700_A_FFMT_THS_Z_LSB,
215         },
216 };
217
218 static const struct regmap_access_table driver_read_table = {
219         .yes_ranges =   read_range,
220         .n_yes_ranges = ARRAY_SIZE(read_range),
221 };
222
223 static const struct regmap_access_table driver_write_table = {
224         .yes_ranges =   write_range,
225         .n_yes_ranges = ARRAY_SIZE(write_range),
226 };
227
228 const struct regmap_config fxos8700_regmap_config = {
229         .reg_bits = 8,
230         .val_bits = 8,
231         .max_register = FXOS8700_NVM_DATA_BNK0,
232         .rd_table = &driver_read_table,
233         .wr_table = &driver_write_table,
234 };
235 EXPORT_SYMBOL(fxos8700_regmap_config);
236
237 #define FXOS8700_CHANNEL(_type, _axis) {                        \
238         .type = _type,                                          \
239         .modified = 1,                                          \
240         .channel2 = IIO_MOD_##_axis,                            \
241         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
242         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
243                 BIT(IIO_CHAN_INFO_SAMP_FREQ),                   \
244 }
245
246 enum fxos8700_accel_scale_bits {
247         MODE_2G = 0,
248         MODE_4G,
249         MODE_8G,
250 };
251
252 /* scan indexes follow DATA register order */
253 enum fxos8700_scan_axis {
254         FXOS8700_SCAN_ACCEL_X = 0,
255         FXOS8700_SCAN_ACCEL_Y,
256         FXOS8700_SCAN_ACCEL_Z,
257         FXOS8700_SCAN_MAGN_X,
258         FXOS8700_SCAN_MAGN_Y,
259         FXOS8700_SCAN_MAGN_Z,
260         FXOS8700_SCAN_RHALL,
261         FXOS8700_SCAN_TIMESTAMP,
262 };
263
264 enum fxos8700_sensor {
265         FXOS8700_ACCEL  = 0,
266         FXOS8700_MAGN,
267         FXOS8700_NUM_SENSORS /* must be last */
268 };
269
270 enum fxos8700_int_pin {
271         FXOS8700_PIN_INT1,
272         FXOS8700_PIN_INT2
273 };
274
275 struct fxos8700_scale {
276         u8 bits;
277         int uscale;
278 };
279
280 struct fxos8700_odr {
281         u8 bits;
282         int odr;
283         int uodr;
284 };
285
286 static const struct fxos8700_scale fxos8700_accel_scale[] = {
287         { MODE_2G, 244},
288         { MODE_4G, 488},
289         { MODE_8G, 976},
290 };
291
292 /*
293  * Accellerometer and magnetometer have the same ODR options, set in the
294  * CTRL_REG1 register. ODR is halved when using both sensors at once in
295  * hybrid mode.
296  */
297 static const struct fxos8700_odr fxos8700_odr[] = {
298         {0x00, 800, 0},
299         {0x01, 400, 0},
300         {0x02, 200, 0},
301         {0x03, 100, 0},
302         {0x04, 50, 0},
303         {0x05, 12, 500000},
304         {0x06, 6, 250000},
305         {0x07, 1, 562500},
306 };
307
308 static const struct iio_chan_spec fxos8700_channels[] = {
309         FXOS8700_CHANNEL(IIO_ACCEL, X),
310         FXOS8700_CHANNEL(IIO_ACCEL, Y),
311         FXOS8700_CHANNEL(IIO_ACCEL, Z),
312         FXOS8700_CHANNEL(IIO_MAGN, X),
313         FXOS8700_CHANNEL(IIO_MAGN, Y),
314         FXOS8700_CHANNEL(IIO_MAGN, Z),
315         IIO_CHAN_SOFT_TIMESTAMP(FXOS8700_SCAN_TIMESTAMP),
316 };
317
318 static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
319 {
320         switch (iio_type) {
321         case IIO_ACCEL:
322                 return FXOS8700_ACCEL;
323         case IIO_MAGN:
324                 return FXOS8700_MAGN;
325         default:
326                 return -EINVAL;
327         }
328 }
329
330 static int fxos8700_set_active_mode(struct fxos8700_data *data,
331                                     enum fxos8700_sensor t, bool mode)
332 {
333         int ret;
334
335         ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, mode);
336         if (ret)
337                 return ret;
338
339         usleep_range(FXOS8700_ACTIVE_MIN_USLEEP,
340                      FXOS8700_ACTIVE_MIN_USLEEP + 1000);
341
342         return 0;
343 }
344
345 static int fxos8700_set_scale(struct fxos8700_data *data,
346                               enum fxos8700_sensor t, int uscale)
347 {
348         int i, ret, val;
349         bool active_mode;
350         static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
351         struct device *dev = regmap_get_device(data->regmap);
352
353         if (t == FXOS8700_MAGN) {
354                 dev_err(dev, "Magnetometer scale is locked at 0.001Gs\n");
355                 return -EINVAL;
356         }
357
358         /*
359          * When device is in active mode, it failed to set an ACCEL
360          * full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG.
361          * This is not align with the datasheet, but it is a fxos8700
362          * chip behavier. Set the device in standby mode before setting
363          * an ACCEL full-scale range.
364          */
365         ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
366         if (ret)
367                 return ret;
368
369         active_mode = val & FXOS8700_ACTIVE;
370         if (active_mode) {
371                 ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
372                                    val & ~FXOS8700_ACTIVE);
373                 if (ret)
374                         return ret;
375         }
376
377         for (i = 0; i < scale_num; i++)
378                 if (fxos8700_accel_scale[i].uscale == uscale)
379                         break;
380
381         if (i == scale_num)
382                 return -EINVAL;
383
384         ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
385                             fxos8700_accel_scale[i].bits);
386         if (ret)
387                 return ret;
388         return regmap_write(data->regmap, FXOS8700_CTRL_REG1,
389                                   active_mode);
390 }
391
392 static int fxos8700_get_scale(struct fxos8700_data *data,
393                               enum fxos8700_sensor t, int *uscale)
394 {
395         int i, ret, val;
396         static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
397
398         if (t == FXOS8700_MAGN) {
399                 *uscale = 1000; /* Magnetometer is locked at 0.001Gs */
400                 return 0;
401         }
402
403         ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);
404         if (ret)
405                 return ret;
406
407         for (i = 0; i < scale_num; i++) {
408                 if (fxos8700_accel_scale[i].bits == (val & 0x3)) {
409                         *uscale = fxos8700_accel_scale[i].uscale;
410                         return 0;
411                 }
412         }
413
414         return -EINVAL;
415 }
416
417 static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
418                              int axis, int *val)
419 {
420         u8 base, reg;
421         s16 tmp;
422         int ret;
423
424         /*
425          * Different register base addresses varies with channel types.
426          * This bug hasn't been noticed before because using an enum is
427          * really hard to read. Use an a switch statement to take over that.
428          */
429         switch (chan_type) {
430         case IIO_ACCEL:
431                 base = FXOS8700_OUT_X_MSB;
432                 break;
433         case IIO_MAGN:
434                 base = FXOS8700_M_OUT_X_MSB;
435                 break;
436         default:
437                 return -EINVAL;
438         }
439
440         /* Block read 6 bytes of device output registers to avoid data loss */
441         ret = regmap_bulk_read(data->regmap, base, data->buf,
442                                sizeof(data->buf));
443         if (ret)
444                 return ret;
445
446         /* Convert axis to buffer index */
447         reg = axis - IIO_MOD_X;
448
449         /*
450          * Convert to native endianness. The accel data and magn data
451          * are signed, so a forced type conversion is needed.
452          */
453         tmp = be16_to_cpu(data->buf[reg]);
454
455         /*
456          * ACCEL output data registers contain the X-axis, Y-axis, and Z-axis
457          * 14-bit left-justified sample data and MAGN output data registers
458          * contain the X-axis, Y-axis, and Z-axis 16-bit sample data. Apply
459          * a signed 2 bits right shift to the readback raw data from ACCEL
460          * output data register and keep that from MAGN sensor as the origin.
461          * Value should be extended to 32 bit.
462          */
463         switch (chan_type) {
464         case IIO_ACCEL:
465                 tmp = tmp >> 2;
466                 break;
467         case IIO_MAGN:
468                 /* Nothing to do */
469                 break;
470         default:
471                 return -EINVAL;
472         }
473
474         /* Convert to native endianness */
475         *val = sign_extend32(tmp, 15);
476
477         return 0;
478 }
479
480 static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
481                             int odr, int uodr)
482 {
483         int i, ret, val;
484         bool active_mode;
485         static const int odr_num = ARRAY_SIZE(fxos8700_odr);
486
487         ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
488         if (ret)
489                 return ret;
490
491         active_mode = val & FXOS8700_ACTIVE;
492
493         if (active_mode) {
494                 /*
495                  * The device must be in standby mode to change any of the
496                  * other fields within CTRL_REG1
497                  */
498                 ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
499                                    val & ~FXOS8700_ACTIVE);
500                 if (ret)
501                         return ret;
502         }
503
504         for (i = 0; i < odr_num; i++)
505                 if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)
506                         break;
507
508         if (i >= odr_num)
509                 return -EINVAL;
510
511         val &= ~FXOS8700_CTRL_ODR_MSK;
512         val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE;
513         return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val);
514 }
515
516 static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
517                             int *odr, int *uodr)
518 {
519         int i, val, ret;
520         static const int odr_num = ARRAY_SIZE(fxos8700_odr);
521
522         ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
523         if (ret)
524                 return ret;
525
526         val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val);
527
528         for (i = 0; i < odr_num; i++)
529                 if (val == fxos8700_odr[i].bits)
530                         break;
531
532         if (i >= odr_num)
533                 return -EINVAL;
534
535         *odr = fxos8700_odr[i].odr;
536         *uodr = fxos8700_odr[i].uodr;
537
538         return 0;
539 }
540
541 static int fxos8700_read_raw(struct iio_dev *indio_dev,
542                              struct iio_chan_spec const *chan,
543                              int *val, int *val2, long mask)
544 {
545         int ret;
546         struct fxos8700_data *data = iio_priv(indio_dev);
547
548         switch (mask) {
549         case IIO_CHAN_INFO_RAW:
550                 ret = fxos8700_get_data(data, chan->type, chan->channel2, val);
551                 if (ret)
552                         return ret;
553                 return IIO_VAL_INT;
554         case IIO_CHAN_INFO_SCALE:
555                 *val = 0;
556                 ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),
557                                          val2);
558                 return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
559         case IIO_CHAN_INFO_SAMP_FREQ:
560                 ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),
561                                        val, val2);
562                 return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
563         default:
564                 return -EINVAL;
565         }
566 }
567
568 static int fxos8700_write_raw(struct iio_dev *indio_dev,
569                               struct iio_chan_spec const *chan,
570                               int val, int val2, long mask)
571 {
572         struct fxos8700_data *data = iio_priv(indio_dev);
573
574         switch (mask) {
575         case IIO_CHAN_INFO_SCALE:
576                 return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),
577                                           val2);
578         case IIO_CHAN_INFO_SAMP_FREQ:
579                 return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),
580                                         val, val2);
581         default:
582                 return -EINVAL;
583         }
584 }
585
586 static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
587                       "1.5625 6.25 12.5 50 100 200 400 800");
588 static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
589                       "1.5625 6.25 12.5 50 100 200 400 800");
590 static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
591 static IIO_CONST_ATTR(in_magn_scale_available, "0.001000");
592
593 static struct attribute *fxos8700_attrs[] = {
594         &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
595         &iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,
596         &iio_const_attr_in_accel_scale_available.dev_attr.attr,
597         &iio_const_attr_in_magn_scale_available.dev_attr.attr,
598         NULL,
599 };
600
601 static const struct attribute_group fxos8700_attrs_group = {
602         .attrs = fxos8700_attrs,
603 };
604
605 static const struct iio_info fxos8700_info = {
606         .read_raw = fxos8700_read_raw,
607         .write_raw = fxos8700_write_raw,
608         .attrs = &fxos8700_attrs_group,
609 };
610
611 static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
612 {
613         int ret;
614         unsigned int val;
615         struct device *dev = regmap_get_device(data->regmap);
616
617         ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);
618         if (ret) {
619                 dev_err(dev, "Error reading chip id\n");
620                 return ret;
621         }
622         if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {
623                 dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",
624                         val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
625                 return -ENODEV;
626         }
627
628         ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);
629         if (ret)
630                 return ret;
631
632         ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);
633         if (ret)
634                 return ret;
635
636         /*
637          * The device must be in standby mode to change any of the other fields
638          * within CTRL_REG1
639          */
640         ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);
641         if (ret)
642                 return ret;
643
644         /* Set max oversample ratio (OSR) and both devices active */
645         ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,
646                            FXOS8700_HMS_MASK | FXOS8700_OS_MASK);
647         if (ret)
648                 return ret;
649
650         /* Disable and rst min/max measurements & threshold */
651         ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,
652                            FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
653                            FXOS8700_MAXMIN_DIS);
654         if (ret)
655                 return ret;
656
657         /*
658          * Set max full-scale range (+/-8G) for ACCEL sensor in chip
659          * initialization then activate the device.
660          */
661         ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
662         if (ret)
663                 return ret;
664
665         /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
666         return regmap_update_bits(data->regmap, FXOS8700_CTRL_REG1,
667                                 FXOS8700_CTRL_ODR_MSK | FXOS8700_ACTIVE,
668                                 FIELD_PREP(FXOS8700_CTRL_ODR_MSK, FXOS8700_CTRL_ODR_MAX) |
669                                 FXOS8700_ACTIVE);
670 }
671
672 static void fxos8700_chip_uninit(void *data)
673 {
674         struct fxos8700_data *fxos8700_data = data;
675
676         fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);
677         fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);
678 }
679
680 int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
681                         const char *name, bool use_spi)
682 {
683         struct iio_dev *indio_dev;
684         struct fxos8700_data *data;
685         int ret;
686
687         indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
688         if (!indio_dev)
689                 return -ENOMEM;
690
691         data = iio_priv(indio_dev);
692         dev_set_drvdata(dev, indio_dev);
693         data->regmap = regmap;
694
695         ret = fxos8700_chip_init(data, use_spi);
696         if (ret)
697                 return ret;
698
699         ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);
700         if (ret)
701                 return ret;
702
703         indio_dev->channels = fxos8700_channels;
704         indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
705         indio_dev->name = name ? name : "fxos8700";
706         indio_dev->modes = INDIO_DIRECT_MODE;
707         indio_dev->info = &fxos8700_info;
708
709         return devm_iio_device_register(dev, indio_dev);
710 }
711 EXPORT_SYMBOL_GPL(fxos8700_core_probe);
712
713 MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
714 MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
715 MODULE_LICENSE("GPL v2");