File Index
Files and directories
Sign in
FILE

fxos8700_core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/imu/fxos8700_core.c 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/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
166struct 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 */
173static 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
183static 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
217static const struct regmap_access_table driver_read_table = {
218	.yes_ranges =   read_range,
219	.n_yes_ranges = ARRAY_SIZE(read_range),
220};
221
222static const struct regmap_access_table driver_write_table = {
223	.yes_ranges =   write_range,
224	.n_yes_ranges = ARRAY_SIZE(write_range),
225};
226
227const 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};
234EXPORT_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
245enum fxos8700_accel_scale_bits {
246	MODE_2G = 0,
247	MODE_4G,
248	MODE_8G,
249};
250
251/* scan indexes follow DATA register order */
252enum 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
263enum fxos8700_sensor {
264	FXOS8700_ACCEL	= 0,
265	FXOS8700_MAGN,
266	FXOS8700_NUM_SENSORS /* must be last */
267};
268
269enum fxos8700_int_pin {
270	FXOS8700_PIN_INT1,
271	FXOS8700_PIN_INT2
272};
273
274struct fxos8700_scale {
275	u8 bits;
276	int uscale;
277};
278
279struct fxos8700_odr {
280	u8 bits;
281	int odr;
282	int uodr;
283};
284
285static 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 */
296static 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
307static 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
317static 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
329static 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
344static 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
391static 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
416static 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
479static 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
515static 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
540static 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
567static 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
585static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
586		      "1.5625 6.25 12.5 50 100 200 400 800");
587static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
588		      "1.5625 6.25 12.5 50 100 200 400 800");
589static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
590static IIO_CONST_ATTR(in_magn_scale_available, "0.001000");
591
592static 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
600static const struct attribute_group fxos8700_attrs_group = {
601	.attrs = fxos8700_attrs,
602};
603
604static 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
610static 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
671static 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
679int 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}
710EXPORT_SYMBOL_GPL(fxos8700_core_probe);
711
712MODULE_AUTHOR("Robert Jones <rjones@gateworks.com>");
713MODULE_DESCRIPTION("FXOS8700 6-Axis Acc and Mag Combo Sensor driver");
714MODULE_LICENSE("GPL v2");
~/ Read-only file preview.