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