xref: /linux/drivers/iio/imu/fxos8700_core.c (revision eb6d8f8705bc19141bac81d8161461f9e256948a)
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_MIN       GENMASK(4, 3)
150 #define FXOS8700_CTRL_ODR_MSK       GENMASK(5, 3)
151 
152 /* Bit definitions for FXOS8700_M_CTRL_REG1 */
153 #define FXOS8700_HMS_MASK           GENMASK(1, 0)
154 #define FXOS8700_OS_MASK            GENMASK(4, 2)
155 
156 /* Bit definitions for FXOS8700_M_CTRL_REG2 */
157 #define FXOS8700_MAXMIN_RST         BIT(2)
158 #define FXOS8700_MAXMIN_DIS_THS     BIT(3)
159 #define FXOS8700_MAXMIN_DIS         BIT(4)
160 
161 #define FXOS8700_ACTIVE             0x01
162 #define FXOS8700_ACTIVE_MIN_USLEEP  4000 /* from table 6 in datasheet */
163 
164 #define FXOS8700_DEVICE_ID          0xC7
165 #define FXOS8700_PRE_DEVICE_ID      0xC4
166 #define FXOS8700_DATA_BUF_SIZE      3
167 
168 struct fxos8700_data {
169 	struct regmap *regmap;
170 	struct iio_trigger *trig;
171 	__be16 buf[FXOS8700_DATA_BUF_SIZE] __aligned(IIO_DMA_MINALIGN);
172 };
173 
174 /* Regmap info */
175 static const struct regmap_range read_range[] = {
176 	{
177 		.range_min = FXOS8700_STATUS,
178 		.range_max = FXOS8700_A_FFMT_COUNT,
179 	}, {
180 		.range_min = FXOS8700_TRANSIENT_CFG,
181 		.range_max = FXOS8700_A_FFMT_THS_Z_LSB,
182 	},
183 };
184 
185 static const struct regmap_range write_range[] = {
186 	{
187 		.range_min = FXOS8700_F_SETUP,
188 		.range_max = FXOS8700_TRIG_CFG,
189 	}, {
190 		.range_min = FXOS8700_XYZ_DATA_CFG,
191 		.range_max = FXOS8700_HP_FILTER_CUTOFF,
192 	}, {
193 		.range_min = FXOS8700_PL_CFG,
194 		.range_max = FXOS8700_A_FFMT_CFG,
195 	}, {
196 		.range_min = FXOS8700_A_FFMT_THS,
197 		.range_max = FXOS8700_TRANSIENT_CFG,
198 	}, {
199 		.range_min = FXOS8700_TRANSIENT_THS,
200 		.range_max = FXOS8700_PULSE_CFG,
201 	}, {
202 		.range_min = FXOS8700_PULSE_THSX,
203 		.range_max = FXOS8700_OFF_Z,
204 	}, {
205 		.range_min = FXOS8700_M_OFF_X_MSB,
206 		.range_max = FXOS8700_M_OFF_Z_LSB,
207 	}, {
208 		.range_min = FXOS8700_M_THS_CFG,
209 		.range_max = FXOS8700_M_THS_CFG,
210 	}, {
211 		.range_min = FXOS8700_M_THS_X_MSB,
212 		.range_max = FXOS8700_M_CTRL_REG3,
213 	}, {
214 		.range_min = FXOS8700_A_VECM_CFG,
215 		.range_max = FXOS8700_A_FFMT_THS_Z_LSB,
216 	},
217 };
218 
219 static const struct regmap_access_table driver_read_table = {
220 	.yes_ranges =   read_range,
221 	.n_yes_ranges = ARRAY_SIZE(read_range),
222 };
223 
224 static const struct regmap_access_table driver_write_table = {
225 	.yes_ranges =   write_range,
226 	.n_yes_ranges = ARRAY_SIZE(write_range),
227 };
228 
229 const struct regmap_config fxos8700_regmap_config = {
230 	.reg_bits = 8,
231 	.val_bits = 8,
232 	.max_register = FXOS8700_NVM_DATA_BNK0,
233 	.rd_table = &driver_read_table,
234 	.wr_table = &driver_write_table,
235 };
236 EXPORT_SYMBOL(fxos8700_regmap_config);
237 
238 #define FXOS8700_CHANNEL(_type, _axis) {			\
239 	.type = _type,						\
240 	.modified = 1,						\
241 	.channel2 = IIO_MOD_##_axis,				\
242 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
243 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
244 		BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
245 }
246 
247 enum fxos8700_accel_scale_bits {
248 	MODE_2G = 0,
249 	MODE_4G,
250 	MODE_8G,
251 };
252 
253 /* scan indexes follow DATA register order */
254 enum fxos8700_scan_axis {
255 	FXOS8700_SCAN_ACCEL_X = 0,
256 	FXOS8700_SCAN_ACCEL_Y,
257 	FXOS8700_SCAN_ACCEL_Z,
258 	FXOS8700_SCAN_MAGN_X,
259 	FXOS8700_SCAN_MAGN_Y,
260 	FXOS8700_SCAN_MAGN_Z,
261 	FXOS8700_SCAN_RHALL,
262 	FXOS8700_SCAN_TIMESTAMP,
263 };
264 
265 enum fxos8700_sensor {
266 	FXOS8700_ACCEL	= 0,
267 	FXOS8700_MAGN,
268 	FXOS8700_NUM_SENSORS /* must be last */
269 };
270 
271 enum fxos8700_int_pin {
272 	FXOS8700_PIN_INT1,
273 	FXOS8700_PIN_INT2
274 };
275 
276 struct fxos8700_scale {
277 	u8 bits;
278 	int uscale;
279 };
280 
281 struct fxos8700_odr {
282 	u8 bits;
283 	int odr;
284 	int uodr;
285 };
286 
287 static const struct fxos8700_scale fxos8700_accel_scale[] = {
288 	{ MODE_2G, 244},
289 	{ MODE_4G, 488},
290 	{ MODE_8G, 976},
291 };
292 
293 /*
294  * Accellerometer and magnetometer have the same ODR options, set in the
295  * CTRL_REG1 register. ODR is halved when using both sensors at once in
296  * hybrid mode.
297  */
298 static const struct fxos8700_odr fxos8700_odr[] = {
299 	{0x00, 800, 0},
300 	{0x01, 400, 0},
301 	{0x02, 200, 0},
302 	{0x03, 100, 0},
303 	{0x04, 50, 0},
304 	{0x05, 12, 500000},
305 	{0x06, 6, 250000},
306 	{0x07, 1, 562500},
307 };
308 
309 static const struct iio_chan_spec fxos8700_channels[] = {
310 	FXOS8700_CHANNEL(IIO_ACCEL, X),
311 	FXOS8700_CHANNEL(IIO_ACCEL, Y),
312 	FXOS8700_CHANNEL(IIO_ACCEL, Z),
313 	FXOS8700_CHANNEL(IIO_MAGN, X),
314 	FXOS8700_CHANNEL(IIO_MAGN, Y),
315 	FXOS8700_CHANNEL(IIO_MAGN, Z),
316 	IIO_CHAN_SOFT_TIMESTAMP(FXOS8700_SCAN_TIMESTAMP),
317 };
318 
319 static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
320 {
321 	switch (iio_type) {
322 	case IIO_ACCEL:
323 		return FXOS8700_ACCEL;
324 	case IIO_MAGN:
325 		return FXOS8700_MAGN;
326 	default:
327 		return -EINVAL;
328 	}
329 }
330 
331 static int fxos8700_set_active_mode(struct fxos8700_data *data,
332 				    enum fxos8700_sensor t, bool mode)
333 {
334 	int ret;
335 
336 	ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, mode);
337 	if (ret)
338 		return ret;
339 
340 	usleep_range(FXOS8700_ACTIVE_MIN_USLEEP,
341 		     FXOS8700_ACTIVE_MIN_USLEEP + 1000);
342 
343 	return 0;
344 }
345 
346 static int fxos8700_set_scale(struct fxos8700_data *data,
347 			      enum fxos8700_sensor t, int uscale)
348 {
349 	int i, ret, val;
350 	bool active_mode;
351 	static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
352 	struct device *dev = regmap_get_device(data->regmap);
353 
354 	if (t == FXOS8700_MAGN) {
355 		dev_err(dev, "Magnetometer scale is locked at 1200uT\n");
356 		return -EINVAL;
357 	}
358 
359 	/*
360 	 * When device is in active mode, it failed to set an ACCEL
361 	 * full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG.
362 	 * This is not align with the datasheet, but it is a fxos8700
363 	 * chip behavier. Set the device in standby mode before setting
364 	 * an ACCEL full-scale range.
365 	 */
366 	ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
367 	if (ret)
368 		return ret;
369 
370 	active_mode = val & FXOS8700_ACTIVE;
371 	if (active_mode) {
372 		ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
373 				   val & ~FXOS8700_ACTIVE);
374 		if (ret)
375 			return ret;
376 	}
377 
378 	for (i = 0; i < scale_num; i++)
379 		if (fxos8700_accel_scale[i].uscale == uscale)
380 			break;
381 
382 	if (i == scale_num)
383 		return -EINVAL;
384 
385 	ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
386 			    fxos8700_accel_scale[i].bits);
387 	if (ret)
388 		return ret;
389 	return regmap_write(data->regmap, FXOS8700_CTRL_REG1,
390 				  active_mode);
391 }
392 
393 static int fxos8700_get_scale(struct fxos8700_data *data,
394 			      enum fxos8700_sensor t, int *uscale)
395 {
396 	int i, ret, val;
397 	static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
398 
399 	if (t == FXOS8700_MAGN) {
400 		*uscale = 1200; /* Magnetometer is locked at 1200uT */
401 		return 0;
402 	}
403 
404 	ret = regmap_read(data->regmap, FXOS8700_XYZ_DATA_CFG, &val);
405 	if (ret)
406 		return ret;
407 
408 	for (i = 0; i < scale_num; i++) {
409 		if (fxos8700_accel_scale[i].bits == (val & 0x3)) {
410 			*uscale = fxos8700_accel_scale[i].uscale;
411 			return 0;
412 		}
413 	}
414 
415 	return -EINVAL;
416 }
417 
418 static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
419 			     int axis, int *val)
420 {
421 	u8 base, reg;
422 	s16 tmp;
423 	int ret;
424 
425 	/*
426 	 * Different register base addresses varies with channel types.
427 	 * This bug hasn't been noticed before because using an enum is
428 	 * really hard to read. Use an a switch statement to take over that.
429 	 */
430 	switch (chan_type) {
431 	case IIO_ACCEL:
432 		base = FXOS8700_OUT_X_MSB;
433 		break;
434 	case IIO_MAGN:
435 		base = FXOS8700_M_OUT_X_MSB;
436 		break;
437 	default:
438 		return -EINVAL;
439 	}
440 
441 	/* Block read 6 bytes of device output registers to avoid data loss */
442 	ret = regmap_bulk_read(data->regmap, base, data->buf,
443 			       sizeof(data->buf));
444 	if (ret)
445 		return ret;
446 
447 	/* Convert axis to buffer index */
448 	reg = axis - IIO_MOD_X;
449 
450 	/*
451 	 * Convert to native endianness. The accel data and magn data
452 	 * are signed, so a forced type conversion is needed.
453 	 */
454 	tmp = be16_to_cpu(data->buf[reg]);
455 
456 	/*
457 	 * ACCEL output data registers contain the X-axis, Y-axis, and Z-axis
458 	 * 14-bit left-justified sample data and MAGN output data registers
459 	 * contain the X-axis, Y-axis, and Z-axis 16-bit sample data. Apply
460 	 * a signed 2 bits right shift to the readback raw data from ACCEL
461 	 * output data register and keep that from MAGN sensor as the origin.
462 	 * Value should be extended to 32 bit.
463 	 */
464 	switch (chan_type) {
465 	case IIO_ACCEL:
466 		tmp = tmp >> 2;
467 		break;
468 	case IIO_MAGN:
469 		/* Nothing to do */
470 		break;
471 	default:
472 		return -EINVAL;
473 	}
474 
475 	/* Convert to native endianness */
476 	*val = sign_extend32(tmp, 15);
477 
478 	return 0;
479 }
480 
481 static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
482 			    int odr, int uodr)
483 {
484 	int i, ret, val;
485 	bool active_mode;
486 	static const int odr_num = ARRAY_SIZE(fxos8700_odr);
487 
488 	ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
489 	if (ret)
490 		return ret;
491 
492 	active_mode = val & FXOS8700_ACTIVE;
493 
494 	if (active_mode) {
495 		/*
496 		 * The device must be in standby mode to change any of the
497 		 * other fields within CTRL_REG1
498 		 */
499 		ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
500 				   val & ~FXOS8700_ACTIVE);
501 		if (ret)
502 			return ret;
503 	}
504 
505 	for (i = 0; i < odr_num; i++)
506 		if (fxos8700_odr[i].odr == odr && fxos8700_odr[i].uodr == uodr)
507 			break;
508 
509 	if (i >= odr_num)
510 		return -EINVAL;
511 
512 	val &= ~FXOS8700_CTRL_ODR_MSK;
513 	val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE;
514 	return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val);
515 }
516 
517 static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
518 			    int *odr, int *uodr)
519 {
520 	int i, val, ret;
521 	static const int odr_num = ARRAY_SIZE(fxos8700_odr);
522 
523 	ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
524 	if (ret)
525 		return ret;
526 
527 	val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val);
528 
529 	for (i = 0; i < odr_num; i++)
530 		if (val == fxos8700_odr[i].bits)
531 			break;
532 
533 	if (i >= odr_num)
534 		return -EINVAL;
535 
536 	*odr = fxos8700_odr[i].odr;
537 	*uodr = fxos8700_odr[i].uodr;
538 
539 	return 0;
540 }
541 
542 static int fxos8700_read_raw(struct iio_dev *indio_dev,
543 			     struct iio_chan_spec const *chan,
544 			     int *val, int *val2, long mask)
545 {
546 	int ret;
547 	struct fxos8700_data *data = iio_priv(indio_dev);
548 
549 	switch (mask) {
550 	case IIO_CHAN_INFO_RAW:
551 		ret = fxos8700_get_data(data, chan->type, chan->channel2, val);
552 		if (ret)
553 			return ret;
554 		return IIO_VAL_INT;
555 	case IIO_CHAN_INFO_SCALE:
556 		*val = 0;
557 		ret = fxos8700_get_scale(data, fxos8700_to_sensor(chan->type),
558 					 val2);
559 		return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
560 	case IIO_CHAN_INFO_SAMP_FREQ:
561 		ret = fxos8700_get_odr(data, fxos8700_to_sensor(chan->type),
562 				       val, val2);
563 		return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
564 	default:
565 		return -EINVAL;
566 	}
567 }
568 
569 static int fxos8700_write_raw(struct iio_dev *indio_dev,
570 			      struct iio_chan_spec const *chan,
571 			      int val, int val2, long mask)
572 {
573 	struct fxos8700_data *data = iio_priv(indio_dev);
574 
575 	switch (mask) {
576 	case IIO_CHAN_INFO_SCALE:
577 		return fxos8700_set_scale(data, fxos8700_to_sensor(chan->type),
578 					  val2);
579 	case IIO_CHAN_INFO_SAMP_FREQ:
580 		return fxos8700_set_odr(data, fxos8700_to_sensor(chan->type),
581 					val, val2);
582 	default:
583 		return -EINVAL;
584 	}
585 }
586 
587 static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
588 		      "1.5625 6.25 12.5 50 100 200 400 800");
589 static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
590 		      "1.5625 6.25 12.5 50 100 200 400 800");
591 static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
592 static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200");
593 
594 static struct attribute *fxos8700_attrs[] = {
595 	&iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
596 	&iio_const_attr_in_magn_sampling_frequency_available.dev_attr.attr,
597 	&iio_const_attr_in_accel_scale_available.dev_attr.attr,
598 	&iio_const_attr_in_magn_scale_available.dev_attr.attr,
599 	NULL,
600 };
601 
602 static const struct attribute_group fxos8700_attrs_group = {
603 	.attrs = fxos8700_attrs,
604 };
605 
606 static const struct iio_info fxos8700_info = {
607 	.read_raw = fxos8700_read_raw,
608 	.write_raw = fxos8700_write_raw,
609 	.attrs = &fxos8700_attrs_group,
610 };
611 
612 static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
613 {
614 	int ret;
615 	unsigned int val;
616 	struct device *dev = regmap_get_device(data->regmap);
617 
618 	ret = regmap_read(data->regmap, FXOS8700_WHO_AM_I, &val);
619 	if (ret) {
620 		dev_err(dev, "Error reading chip id\n");
621 		return ret;
622 	}
623 	if (val != FXOS8700_DEVICE_ID && val != FXOS8700_PRE_DEVICE_ID) {
624 		dev_err(dev, "Wrong chip id, got %x expected %x or %x\n",
625 			val, FXOS8700_DEVICE_ID, FXOS8700_PRE_DEVICE_ID);
626 		return -ENODEV;
627 	}
628 
629 	ret = fxos8700_set_active_mode(data, FXOS8700_ACCEL, true);
630 	if (ret)
631 		return ret;
632 
633 	ret = fxos8700_set_active_mode(data, FXOS8700_MAGN, true);
634 	if (ret)
635 		return ret;
636 
637 	/*
638 	 * The device must be in standby mode to change any of the other fields
639 	 * within CTRL_REG1
640 	 */
641 	ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1, 0x00);
642 	if (ret)
643 		return ret;
644 
645 	/* Set max oversample ratio (OSR) and both devices active */
646 	ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG1,
647 			   FXOS8700_HMS_MASK | FXOS8700_OS_MASK);
648 	if (ret)
649 		return ret;
650 
651 	/* Disable and rst min/max measurements & threshold */
652 	ret = regmap_write(data->regmap, FXOS8700_M_CTRL_REG2,
653 			   FXOS8700_MAXMIN_RST | FXOS8700_MAXMIN_DIS_THS |
654 			   FXOS8700_MAXMIN_DIS);
655 	if (ret)
656 		return ret;
657 
658 	/*
659 	 * Set max full-scale range (+/-8G) for ACCEL sensor in chip
660 	 * initialization then activate the device.
661 	 */
662 	ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
663 	if (ret)
664 		return ret;
665 
666 	/* Max ODR (800Hz individual or 400Hz hybrid), active mode */
667 	return regmap_update_bits(data->regmap, FXOS8700_CTRL_REG1,
668 				FXOS8700_CTRL_ODR_MSK | FXOS8700_ACTIVE,
669 				FIELD_PREP(FXOS8700_CTRL_ODR_MSK, FXOS8700_CTRL_ODR_MAX) |
670 				FXOS8700_ACTIVE);
671 }
672 
673 static void fxos8700_chip_uninit(void *data)
674 {
675 	struct fxos8700_data *fxos8700_data = data;
676 
677 	fxos8700_set_active_mode(fxos8700_data, FXOS8700_ACCEL, false);
678 	fxos8700_set_active_mode(fxos8700_data, FXOS8700_MAGN, false);
679 }
680 
681 int fxos8700_core_probe(struct device *dev, struct regmap *regmap,
682 			const char *name, bool use_spi)
683 {
684 	struct iio_dev *indio_dev;
685 	struct fxos8700_data *data;
686 	int ret;
687 
688 	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
689 	if (!indio_dev)
690 		return -ENOMEM;
691 
692 	data = iio_priv(indio_dev);
693 	dev_set_drvdata(dev, indio_dev);
694 	data->regmap = regmap;
695 
696 	ret = fxos8700_chip_init(data, use_spi);
697 	if (ret)
698 		return ret;
699 
700 	ret = devm_add_action_or_reset(dev, fxos8700_chip_uninit, data);
701 	if (ret)
702 		return ret;
703 
704 	indio_dev->channels = fxos8700_channels;
705 	indio_dev->num_channels = ARRAY_SIZE(fxos8700_channels);
706 	indio_dev->name = name ? name : "fxos8700";
707 	indio_dev->modes = INDIO_DIRECT_MODE;
708 	indio_dev->info = &fxos8700_info;
709 
710 	return devm_iio_device_register(dev, indio_dev);
711 }
712 EXPORT_SYMBOL_GPL(fxos8700_core_probe);
713 
714 MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
715 MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
716 MODULE_LICENSE("GPL v2");
717