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
167struct 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 */
174static 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
184static 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
218static const struct regmap_access_table driver_read_table = {
219 .yes_ranges = read_range,
220 .n_yes_ranges = ARRAY_SIZE(read_range),
221};
222
223static const struct regmap_access_table driver_write_table = {
224 .yes_ranges = write_range,
225 .n_yes_ranges = ARRAY_SIZE(write_range),
226};
227
228const 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};
235EXPORT_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
246enum fxos8700_accel_scale_bits {
247 MODE_2G = 0,
248 MODE_4G,
249 MODE_8G,
250};
251
252/* scan indexes follow DATA register order */
253enum 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
264enum fxos8700_sensor {
265 FXOS8700_ACCEL = 0,
266 FXOS8700_MAGN,
267 FXOS8700_NUM_SENSORS /* must be last */
268};
269
270enum fxos8700_int_pin {
271 FXOS8700_PIN_INT1,
272 FXOS8700_PIN_INT2
273};
274
275struct fxos8700_scale {
276 u8 bits;
277 int uscale;
278};
279
280struct fxos8700_odr {
281 u8 bits;
282 int odr;
283 int uodr;
284};
285
286static 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 */
297static 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
308static 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
318static 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
330static 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(map: data->regmap, FXOS8700_CTRL_REG1, val: 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
345static 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(map: 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(map: data->regmap, FXOS8700_CTRL_REG1, val: &val);
366 if (ret)
367 return ret;
368
369 active_mode = val & FXOS8700_ACTIVE;
370 if (active_mode) {
371 ret = regmap_write(map: data->regmap, FXOS8700_CTRL_REG1,
372 val: 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(map: data->regmap, FXOS8700_XYZ_DATA_CFG,
385 val: fxos8700_accel_scale[i].bits);
386 if (ret)
387 return ret;
388 return regmap_write(map: data->regmap, FXOS8700_CTRL_REG1,
389 val: active_mode);
390}
391
392static 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(map: data->regmap, FXOS8700_XYZ_DATA_CFG, val: &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
417static 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(map: data->regmap, reg: base, val: data->buf,
442 val_count: 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(value: tmp, index: 15);
476
477 return 0;
478}
479
480static 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(map: data->regmap, FXOS8700_CTRL_REG1, val: &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(map: data->regmap, FXOS8700_CTRL_REG1,
499 val: 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(map: data->regmap, FXOS8700_CTRL_REG1, val);
514}
515
516static 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(map: data->regmap, FXOS8700_CTRL_REG1, val: &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
541static 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->type, axis: 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, t: fxos8700_to_sensor(iio_type: chan->type),
557 uscale: val2);
558 return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
559 case IIO_CHAN_INFO_SAMP_FREQ:
560 ret = fxos8700_get_odr(data, t: fxos8700_to_sensor(iio_type: chan->type),
561 odr: val, uodr: val2);
562 return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
563 default:
564 return -EINVAL;
565 }
566}
567
568static 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, t: fxos8700_to_sensor(iio_type: chan->type),
577 uscale: val2);
578 case IIO_CHAN_INFO_SAMP_FREQ:
579 return fxos8700_set_odr(data, t: fxos8700_to_sensor(iio_type: chan->type),
580 odr: val, uodr: val2);
581 default:
582 return -EINVAL;
583 }
584}
585
586static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
587 "1.5625 6.25 12.5 50 100 200 400 800");
588static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
589 "1.5625 6.25 12.5 50 100 200 400 800");
590static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
591static IIO_CONST_ATTR(in_magn_scale_available, "0.001000");
592
593static 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
601static const struct attribute_group fxos8700_attrs_group = {
602 .attrs = fxos8700_attrs,
603};
604
605static 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
611static 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(map: data->regmap);
616
617 ret = regmap_read(map: data->regmap, FXOS8700_WHO_AM_I, val: &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, t: FXOS8700_ACCEL, mode: true);
629 if (ret)
630 return ret;
631
632 ret = fxos8700_set_active_mode(data, t: FXOS8700_MAGN, mode: 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(map: data->regmap, FXOS8700_CTRL_REG1, val: 0x00);
641 if (ret)
642 return ret;
643
644 /* Set max oversample ratio (OSR) and both devices active */
645 ret = regmap_write(map: 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(map: 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(map: data->regmap, FXOS8700_XYZ_DATA_CFG, val: MODE_8G);
662 if (ret)
663 return ret;
664
665 /* Max ODR (800Hz individual or 400Hz hybrid), active mode */
666 return regmap_update_bits(map: 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
672static void fxos8700_chip_uninit(void *data)
673{
674 struct fxos8700_data *fxos8700_data = data;
675
676 fxos8700_set_active_mode(data: fxos8700_data, t: FXOS8700_ACCEL, mode: false);
677 fxos8700_set_active_mode(data: fxos8700_data, t: FXOS8700_MAGN, mode: false);
678}
679
680int 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(parent: dev, sizeof_priv: sizeof(*data));
688 if (!indio_dev)
689 return -ENOMEM;
690
691 data = iio_priv(indio_dev);
692 dev_set_drvdata(dev, data: 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}
711EXPORT_SYMBOL_GPL(fxos8700_core_probe);
712
713MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
714MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
715MODULE_LICENSE("GPL v2");
716

source code of linux/drivers/iio/imu/fxos8700_core.c