File Index
Files and directories
Sign in
FILE

inv_icm42600_core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2020 Invensense, Inc.
  4 */
  5
  6#include <linux/kernel.h>
  7#include <linux/device.h>
  8#include <linux/module.h>
  9#include <linux/slab.h>
 10#include <linux/delay.h>
 11#include <linux/mutex.h>
 12#include <linux/interrupt.h>
 13#include <linux/irq.h>
 14#include <linux/regulator/consumer.h>
 15#include <linux/pm_runtime.h>
 16#include <linux/property.h>
 17#include <linux/regmap.h>
 18
 19#include <linux/iio/iio.h>
 20
 21#include "inv_icm42600.h"
 22#include "inv_icm42600_buffer.h"
 23
 24static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = {
 25	{
 26		.name = "user banks",
 27		.range_min = 0x0000,
 28		.range_max = 0x4FFF,
 29		.selector_reg = INV_ICM42600_REG_BANK_SEL,
 30		.selector_mask = INV_ICM42600_BANK_SEL_MASK,
 31		.selector_shift = 0,
 32		.window_start = 0,
 33		.window_len = 0x1000,
 34	},
 35};
 36
 37static const struct regmap_range inv_icm42600_regmap_volatile_yes_ranges[] = {
 38	/* Sensor data registers */
 39	regmap_reg_range(0x001D, 0x002A),
 40	/* INT status, FIFO, APEX data */
 41	regmap_reg_range(0x002D, 0x0038),
 42	/* Signal path reset */
 43	regmap_reg_range(0x004B, 0x004B),
 44	/* FIFO lost packets */
 45	regmap_reg_range(0x006C, 0x006D),
 46	/* Timestamp value */
 47	regmap_reg_range(0x1062, 0x1064),
 48};
 49
 50static const struct regmap_range inv_icm42600_regmap_volatile_no_ranges[] = {
 51	regmap_reg_range(0x0000, 0x001C),
 52	regmap_reg_range(0x006E, 0x1061),
 53	regmap_reg_range(0x1065, 0x4FFF),
 54};
 55
 56static const struct regmap_access_table inv_icm42600_regmap_volatile_accesses[] = {
 57	{
 58		.yes_ranges = inv_icm42600_regmap_volatile_yes_ranges,
 59		.n_yes_ranges = ARRAY_SIZE(inv_icm42600_regmap_volatile_yes_ranges),
 60		.no_ranges = inv_icm42600_regmap_volatile_no_ranges,
 61		.n_no_ranges = ARRAY_SIZE(inv_icm42600_regmap_volatile_no_ranges),
 62	},
 63};
 64
 65static const struct regmap_range inv_icm42600_regmap_rd_noinc_no_ranges[] = {
 66	regmap_reg_range(0x0000, INV_ICM42600_REG_FIFO_DATA - 1),
 67	regmap_reg_range(INV_ICM42600_REG_FIFO_DATA + 1, 0x4FFF),
 68};
 69
 70static const struct regmap_access_table inv_icm42600_regmap_rd_noinc_accesses[] = {
 71	{
 72		.no_ranges = inv_icm42600_regmap_rd_noinc_no_ranges,
 73		.n_no_ranges = ARRAY_SIZE(inv_icm42600_regmap_rd_noinc_no_ranges),
 74	},
 75};
 76
 77const struct regmap_config inv_icm42600_regmap_config = {
 78	.name = "inv_icm42600",
 79	.reg_bits = 8,
 80	.val_bits = 8,
 81	.max_register = 0x4FFF,
 82	.ranges = inv_icm42600_regmap_ranges,
 83	.num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges),
 84	.volatile_table = inv_icm42600_regmap_volatile_accesses,
 85	.rd_noinc_table = inv_icm42600_regmap_rd_noinc_accesses,
 86	.cache_type = REGCACHE_MAPLE,
 87};
 88EXPORT_SYMBOL_NS_GPL(inv_icm42600_regmap_config, "IIO_ICM42600");
 89
 90/* define specific regmap for SPI not supporting burst write */
 91const struct regmap_config inv_icm42600_spi_regmap_config = {
 92	.name = "inv_icm42600",
 93	.reg_bits = 8,
 94	.val_bits = 8,
 95	.max_register = 0x4FFF,
 96	.ranges = inv_icm42600_regmap_ranges,
 97	.num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges),
 98	.volatile_table = inv_icm42600_regmap_volatile_accesses,
 99	.rd_noinc_table = inv_icm42600_regmap_rd_noinc_accesses,
100	.cache_type = REGCACHE_MAPLE,
101	.use_single_write = true,
102};
103EXPORT_SYMBOL_NS_GPL(inv_icm42600_spi_regmap_config, "IIO_ICM42600");
104
105struct inv_icm42600_hw {
106	u8 whoami;
107	const char *name;
108	const struct inv_icm42600_conf *conf;
109};
110
111/* chip initial default configuration */
112static const struct inv_icm42600_conf inv_icm42600_default_conf = {
113	.gyro = {
114		.mode = INV_ICM42600_SENSOR_MODE_OFF,
115		.fs = INV_ICM42600_GYRO_FS_2000DPS,
116		.odr = INV_ICM42600_ODR_50HZ,
117		.filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
118	},
119	.accel = {
120		.mode = INV_ICM42600_SENSOR_MODE_OFF,
121		.fs = INV_ICM42600_ACCEL_FS_16G,
122		.odr = INV_ICM42600_ODR_50HZ,
123		.filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
124	},
125	.temp_en = false,
126};
127
128static const struct inv_icm42600_conf inv_icm42686_default_conf = {
129	.gyro = {
130		.mode = INV_ICM42600_SENSOR_MODE_OFF,
131		.fs = INV_ICM42686_GYRO_FS_4000DPS,
132		.odr = INV_ICM42600_ODR_50HZ,
133		.filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
134	},
135	.accel = {
136		.mode = INV_ICM42600_SENSOR_MODE_OFF,
137		.fs = INV_ICM42686_ACCEL_FS_32G,
138		.odr = INV_ICM42600_ODR_50HZ,
139		.filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
140	},
141	.temp_en = false,
142};
143
144static const struct inv_icm42600_hw inv_icm42600_hw[INV_CHIP_NB] = {
145	[INV_CHIP_ICM42600] = {
146		.whoami = INV_ICM42600_WHOAMI_ICM42600,
147		.name = "icm42600",
148		.conf = &inv_icm42600_default_conf,
149	},
150	[INV_CHIP_ICM42602] = {
151		.whoami = INV_ICM42600_WHOAMI_ICM42602,
152		.name = "icm42602",
153		.conf = &inv_icm42600_default_conf,
154	},
155	[INV_CHIP_ICM42605] = {
156		.whoami = INV_ICM42600_WHOAMI_ICM42605,
157		.name = "icm42605",
158		.conf = &inv_icm42600_default_conf,
159	},
160	[INV_CHIP_ICM42686] = {
161		.whoami = INV_ICM42600_WHOAMI_ICM42686,
162		.name = "icm42686",
163		.conf = &inv_icm42686_default_conf,
164	},
165	[INV_CHIP_ICM42622] = {
166		.whoami = INV_ICM42600_WHOAMI_ICM42622,
167		.name = "icm42622",
168		.conf = &inv_icm42600_default_conf,
169	},
170	[INV_CHIP_ICM42688] = {
171		.whoami = INV_ICM42600_WHOAMI_ICM42688,
172		.name = "icm42688",
173		.conf = &inv_icm42600_default_conf,
174	},
175	[INV_CHIP_ICM42631] = {
176		.whoami = INV_ICM42600_WHOAMI_ICM42631,
177		.name = "icm42631",
178		.conf = &inv_icm42600_default_conf,
179	},
180};
181
182const struct iio_mount_matrix *
183inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev,
184			      const struct iio_chan_spec *chan)
185{
186	const struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
187
188	return &st->orientation;
189}
190
191u32 inv_icm42600_odr_to_period(enum inv_icm42600_odr odr)
192{
193	static u32 odr_periods[INV_ICM42600_ODR_NB] = {
194		/* reserved values */
195		0, 0, 0,
196		/* 8kHz */
197		125000,
198		/* 4kHz */
199		250000,
200		/* 2kHz */
201		500000,
202		/* 1kHz */
203		1000000,
204		/* 200Hz */
205		5000000,
206		/* 100Hz */
207		10000000,
208		/* 50Hz */
209		20000000,
210		/* 25Hz */
211		40000000,
212		/* 12.5Hz */
213		80000000,
214		/* 6.25Hz */
215		160000000,
216		/* 3.125Hz */
217		320000000,
218		/* 1.5625Hz */
219		640000000,
220		/* 500Hz */
221		2000000,
222	};
223
224	return odr_periods[odr];
225}
226
227static int inv_icm42600_set_pwr_mgmt0(struct inv_icm42600_state *st,
228				      enum inv_icm42600_sensor_mode gyro,
229				      enum inv_icm42600_sensor_mode accel,
230				      bool temp, unsigned int *sleep_ms)
231{
232	enum inv_icm42600_sensor_mode oldgyro = st->conf.gyro.mode;
233	enum inv_icm42600_sensor_mode oldaccel = st->conf.accel.mode;
234	bool oldtemp = st->conf.temp_en;
235	unsigned int sleepval;
236	unsigned int val;
237	int ret;
238
239	/* if nothing changed, exit */
240	if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
241		return 0;
242
243	val = INV_ICM42600_PWR_MGMT0_GYRO(gyro) |
244	      INV_ICM42600_PWR_MGMT0_ACCEL(accel);
245	if (!temp)
246		val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
247	ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val);
248	if (ret)
249		return ret;
250
251	st->conf.gyro.mode = gyro;
252	st->conf.accel.mode = accel;
253	st->conf.temp_en = temp;
254
255	/* compute required wait time for sensors to stabilize */
256	sleepval = 0;
257	/* temperature stabilization time */
258	if (temp && !oldtemp) {
259		if (sleepval < INV_ICM42600_TEMP_STARTUP_TIME_MS)
260			sleepval = INV_ICM42600_TEMP_STARTUP_TIME_MS;
261	}
262	/* accel startup time */
263	if (accel != oldaccel && oldaccel == INV_ICM42600_SENSOR_MODE_OFF) {
264		/* block any register write for at least 200 µs */
265		usleep_range(200, 300);
266		if (sleepval < INV_ICM42600_ACCEL_STARTUP_TIME_MS)
267			sleepval = INV_ICM42600_ACCEL_STARTUP_TIME_MS;
268	}
269	if (gyro != oldgyro) {
270		/* gyro startup time */
271		if (oldgyro == INV_ICM42600_SENSOR_MODE_OFF) {
272			/* block any register write for at least 200 µs */
273			usleep_range(200, 300);
274			if (sleepval < INV_ICM42600_GYRO_STARTUP_TIME_MS)
275				sleepval = INV_ICM42600_GYRO_STARTUP_TIME_MS;
276		/* gyro stop time */
277		} else if (gyro == INV_ICM42600_SENSOR_MODE_OFF) {
278			if (sleepval < INV_ICM42600_GYRO_STOP_TIME_MS)
279				sleepval =  INV_ICM42600_GYRO_STOP_TIME_MS;
280		}
281	}
282
283	/* deferred sleep value if sleep pointer is provided or direct sleep */
284	if (sleep_ms)
285		*sleep_ms = sleepval;
286	else if (sleepval)
287		msleep(sleepval);
288
289	return 0;
290}
291
292int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st,
293				struct inv_icm42600_sensor_conf *conf,
294				unsigned int *sleep_ms)
295{
296	struct inv_icm42600_sensor_conf *oldconf = &st->conf.accel;
297	unsigned int val;
298	int ret;
299
300	/* Sanitize missing values with current values */
301	if (conf->mode < 0)
302		conf->mode = oldconf->mode;
303	if (conf->fs < 0)
304		conf->fs = oldconf->fs;
305	if (conf->odr < 0)
306		conf->odr = oldconf->odr;
307	if (conf->filter < 0)
308		conf->filter = oldconf->filter;
309
310	/* force power mode against ODR when sensor is on */
311	switch (conf->mode) {
312	case INV_ICM42600_SENSOR_MODE_LOW_POWER:
313	case INV_ICM42600_SENSOR_MODE_LOW_NOISE:
314		if (conf->odr <= INV_ICM42600_ODR_1KHZ_LN) {
315			conf->mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE;
316			conf->filter = INV_ICM42600_FILTER_BW_ODR_DIV_2;
317		} else if (conf->odr >= INV_ICM42600_ODR_6_25HZ_LP &&
318			   conf->odr <= INV_ICM42600_ODR_1_5625HZ_LP) {
319			conf->mode = INV_ICM42600_SENSOR_MODE_LOW_POWER;
320			conf->filter = INV_ICM42600_FILTER_AVG_16X;
321		}
322		break;
323	default:
324		break;
325	}
326
327	/* set ACCEL_CONFIG0 register (accel fullscale & odr) */
328	if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
329		val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) |
330		      INV_ICM42600_ACCEL_CONFIG0_ODR(conf->odr);
331		ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
332		if (ret)
333			return ret;
334		oldconf->fs = conf->fs;
335		oldconf->odr = conf->odr;
336	}
337
338	/* set GYRO_ACCEL_CONFIG0 register (accel filter) */
339	if (conf->filter != oldconf->filter) {
340		val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->filter) |
341		      INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(st->conf.gyro.filter);
342		ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
343		if (ret)
344			return ret;
345		oldconf->filter = conf->filter;
346	}
347
348	/* set PWR_MGMT0 register (accel sensor mode) */
349	return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode,
350					  st->conf.temp_en, sleep_ms);
351}
352
353int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st,
354			       struct inv_icm42600_sensor_conf *conf,
355			       unsigned int *sleep_ms)
356{
357	struct inv_icm42600_sensor_conf *oldconf = &st->conf.gyro;
358	unsigned int val;
359	int ret;
360
361	/* sanitize missing values with current values */
362	if (conf->mode < 0)
363		conf->mode = oldconf->mode;
364	if (conf->fs < 0)
365		conf->fs = oldconf->fs;
366	if (conf->odr < 0)
367		conf->odr = oldconf->odr;
368	if (conf->filter < 0)
369		conf->filter = oldconf->filter;
370
371	/* set GYRO_CONFIG0 register (gyro fullscale & odr) */
372	if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
373		val = INV_ICM42600_GYRO_CONFIG0_FS(conf->fs) |
374		      INV_ICM42600_GYRO_CONFIG0_ODR(conf->odr);
375		ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
376		if (ret)
377			return ret;
378		oldconf->fs = conf->fs;
379		oldconf->odr = conf->odr;
380	}
381
382	/* set GYRO_ACCEL_CONFIG0 register (gyro filter) */
383	if (conf->filter != oldconf->filter) {
384		val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(st->conf.accel.filter) |
385		      INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->filter);
386		ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
387		if (ret)
388			return ret;
389		oldconf->filter = conf->filter;
390	}
391
392	/* set PWR_MGMT0 register (gyro sensor mode) */
393	return inv_icm42600_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode,
394					  st->conf.temp_en, sleep_ms);
395
396	return 0;
397}
398
399int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable,
400			       unsigned int *sleep_ms)
401{
402	return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode,
403					  st->conf.accel.mode, enable,
404					  sleep_ms);
405}
406
407int inv_icm42600_enable_wom(struct inv_icm42600_state *st)
408{
409	int ret;
410
411	/* enable WoM hardware */
412	ret = regmap_write(st->map, INV_ICM42600_REG_SMD_CONFIG,
413			   INV_ICM42600_SMD_CONFIG_SMD_MODE_WOM |
414			   INV_ICM42600_SMD_CONFIG_WOM_MODE);
415	if (ret)
416		return ret;
417
418	/* enable WoM interrupt */
419	return regmap_set_bits(st->map, INV_ICM42600_REG_INT_SOURCE1,
420			      INV_ICM42600_INT_SOURCE1_WOM_INT1_EN);
421}
422
423int inv_icm42600_disable_wom(struct inv_icm42600_state *st)
424{
425	int ret;
426
427	/* disable WoM interrupt */
428	ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INT_SOURCE1,
429				INV_ICM42600_INT_SOURCE1_WOM_INT1_EN);
430	if (ret)
431		return ret;
432
433	/* disable WoM hardware */
434	return regmap_write(st->map, INV_ICM42600_REG_SMD_CONFIG,
435			    INV_ICM42600_SMD_CONFIG_SMD_MODE_OFF);
436}
437
438int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
439			     unsigned int writeval, unsigned int *readval)
440{
441	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
442
443	guard(mutex)(&st->lock);
444
445	if (readval)
446		return regmap_read(st->map, reg, readval);
447
448	return regmap_write(st->map, reg, writeval);
449}
450
451static int inv_icm42600_set_conf(struct inv_icm42600_state *st,
452				 const struct inv_icm42600_conf *conf)
453{
454	unsigned int val;
455	int ret;
456
457	/* set PWR_MGMT0 register (gyro & accel sensor mode, temp enabled) */
458	val = INV_ICM42600_PWR_MGMT0_GYRO(conf->gyro.mode) |
459	      INV_ICM42600_PWR_MGMT0_ACCEL(conf->accel.mode);
460	if (!conf->temp_en)
461		val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
462	ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val);
463	if (ret)
464		return ret;
465
466	/* set GYRO_CONFIG0 register (gyro fullscale & odr) */
467	val = INV_ICM42600_GYRO_CONFIG0_FS(conf->gyro.fs) |
468	      INV_ICM42600_GYRO_CONFIG0_ODR(conf->gyro.odr);
469	ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
470	if (ret)
471		return ret;
472
473	/* set ACCEL_CONFIG0 register (accel fullscale & odr) */
474	val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->accel.fs) |
475	      INV_ICM42600_ACCEL_CONFIG0_ODR(conf->accel.odr);
476	ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
477	if (ret)
478		return ret;
479
480	/* set GYRO_ACCEL_CONFIG0 register (gyro & accel filters) */
481	val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->accel.filter) |
482	      INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->gyro.filter);
483	ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
484	if (ret)
485		return ret;
486
487	/* update internal conf */
488	st->conf = *conf;
489
490	return 0;
491}
492
493/**
494 *  inv_icm42600_setup() - check and setup chip
495 *  @st:	driver internal state
496 *  @bus_setup:	callback for setting up bus specific registers
497 *
498 *  Returns 0 on success, a negative error code otherwise.
499 */
500static int inv_icm42600_setup(struct inv_icm42600_state *st,
501			      inv_icm42600_bus_setup bus_setup)
502{
503	const struct inv_icm42600_hw *hw = &inv_icm42600_hw[st->chip];
504	const struct device *dev = regmap_get_device(st->map);
505	unsigned int val;
506	int ret;
507
508	/* check chip self-identification value */
509	ret = regmap_read(st->map, INV_ICM42600_REG_WHOAMI, &val);
510	if (ret)
511		return ret;
512	if (val != hw->whoami) {
513		dev_err(dev, "invalid whoami %#02x expected %#02x (%s)\n",
514			val, hw->whoami, hw->name);
515		return -ENODEV;
516	}
517	st->name = hw->name;
518
519	/* reset to make sure previous state are not there */
520	ret = regmap_write(st->map, INV_ICM42600_REG_DEVICE_CONFIG,
521			   INV_ICM42600_DEVICE_CONFIG_SOFT_RESET);
522	if (ret)
523		return ret;
524	msleep(INV_ICM42600_RESET_TIME_MS);
525
526	ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &val);
527	if (ret)
528		return ret;
529	if (!(val & INV_ICM42600_INT_STATUS_RESET_DONE)) {
530		dev_err(dev, "reset error, reset done bit not set\n");
531		return -ENODEV;
532	}
533
534	/* set chip bus configuration */
535	ret = bus_setup(st);
536	if (ret)
537		return ret;
538
539	/* sensor data in big-endian (default) */
540	ret = regmap_set_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
541			      INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN);
542	if (ret)
543		return ret;
544
545	/*
546	 * Use RC clock for accel low-power to fix glitches when switching
547	 * gyro on/off while accel low-power is on.
548	 */
549	ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG1,
550				 INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC,
551				 INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC);
552	if (ret)
553		return ret;
554
555	return inv_icm42600_set_conf(st, hw->conf);
556}
557
558static irqreturn_t inv_icm42600_irq_timestamp(int irq, void *_data)
559{
560	struct inv_icm42600_state *st = _data;
561
562	st->timestamp.gyro = iio_get_time_ns(st->indio_gyro);
563	st->timestamp.accel = iio_get_time_ns(st->indio_accel);
564
565	return IRQ_WAKE_THREAD;
566}
567
568static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
569{
570	struct inv_icm42600_state *st = _data;
571	struct device *dev = regmap_get_device(st->map);
572	unsigned int status;
573	int ret;
574
575	mutex_lock(&st->lock);
576
577	if (st->apex.on) {
578		unsigned int status2, status3;
579
580		/* read INT_STATUS2 and INT_STATUS3 in 1 operation */
581		ret = regmap_bulk_read(st->map, INV_ICM42600_REG_INT_STATUS2, st->buffer, 2);
582		if (ret)
583			goto out_unlock;
584		status2 = st->buffer[0];
585		status3 = st->buffer[1];
586		inv_icm42600_accel_handle_events(st->indio_accel, status2, status3,
587						 st->timestamp.accel);
588	}
589
590	ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status);
591	if (ret)
592		goto out_unlock;
593
594	/* FIFO full */
595	if (status & INV_ICM42600_INT_STATUS_FIFO_FULL)
596		dev_warn(dev, "FIFO full data lost!\n");
597
598	/* FIFO threshold reached */
599	if (status & INV_ICM42600_INT_STATUS_FIFO_THS) {
600		ret = inv_icm42600_buffer_fifo_read(st, 0);
601		if (ret) {
602			dev_err(dev, "FIFO read error %d\n", ret);
603			goto out_unlock;
604		}
605		ret = inv_icm42600_buffer_fifo_parse(st);
606		if (ret)
607			dev_err(dev, "FIFO parsing error %d\n", ret);
608	}
609
610out_unlock:
611	mutex_unlock(&st->lock);
612	return IRQ_HANDLED;
613}
614
615/**
616 * inv_icm42600_irq_init() - initialize int pin and interrupt handler
617 * @st:		driver internal state
618 * @irq:	irq number
619 * @irq_type:	irq trigger type
620 * @open_drain:	true if irq is open drain, false for push-pull
621 *
622 * Returns 0 on success, a negative error code otherwise.
623 */
624static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
625				 int irq_type, bool open_drain)
626{
627	struct device *dev = regmap_get_device(st->map);
628	unsigned int val;
629	int ret;
630
631	/* configure INT1 interrupt: default is active low on edge */
632	switch (irq_type) {
633	case IRQF_TRIGGER_RISING:
634	case IRQF_TRIGGER_HIGH:
635		val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH;
636		break;
637	default:
638		val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW;
639		break;
640	}
641
642	switch (irq_type) {
643	case IRQF_TRIGGER_LOW:
644	case IRQF_TRIGGER_HIGH:
645		val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED;
646		break;
647	default:
648		break;
649	}
650
651	if (!open_drain)
652		val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL;
653
654	ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val);
655	if (ret)
656		return ret;
657
658	/* Deassert async reset for proper INT pin operation (cf datasheet) */
659	ret = regmap_clear_bits(st->map, INV_ICM42600_REG_INT_CONFIG1,
660				INV_ICM42600_INT_CONFIG1_ASYNC_RESET);
661	if (ret)
662		return ret;
663
664	irq_type |= IRQF_ONESHOT;
665	return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp,
666					 inv_icm42600_irq_handler, irq_type,
667					 "inv_icm42600", st);
668}
669
670static int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st)
671{
672	unsigned int val;
673
674	/* enable timestamp register */
675	val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN |
676	      INV_ICM42600_TMST_CONFIG_TMST_EN;
677	return regmap_update_bits(st->map, INV_ICM42600_REG_TMST_CONFIG,
678				  INV_ICM42600_TMST_CONFIG_MASK, val);
679}
680
681static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st)
682{
683	int ret;
684
685	ret = regulator_enable(st->vddio_supply);
686	if (ret)
687		return ret;
688
689	/* wait a little for supply ramp */
690	usleep_range(3000, 4000);
691
692	return 0;
693}
694
695static void inv_icm42600_disable_vddio_reg(void *_data)
696{
697	struct inv_icm42600_state *st = _data;
698	struct device *dev = regmap_get_device(st->map);
699
700	if (pm_runtime_status_suspended(dev))
701		return;
702
703	regulator_disable(st->vddio_supply);
704}
705
706int inv_icm42600_core_probe(struct regmap *regmap, int chip,
707			    inv_icm42600_bus_setup bus_setup)
708{
709	struct device *dev = regmap_get_device(regmap);
710	struct fwnode_handle *fwnode = dev_fwnode(dev);
711	struct inv_icm42600_state *st;
712	int irq, irq_type;
713	bool open_drain;
714	int ret;
715
716	if (chip <= INV_CHIP_INVALID || chip >= INV_CHIP_NB) {
717		dev_err(dev, "invalid chip = %d\n", chip);
718		return -ENODEV;
719	}
720
721	/* get INT1 only supported interrupt or fallback to first interrupt */
722	irq = fwnode_irq_get_byname(fwnode, "INT1");
723	if (irq < 0 && irq != -EPROBE_DEFER) {
724		dev_info(dev, "no INT1 interrupt defined, fallback to first interrupt\n");
725		irq = fwnode_irq_get(fwnode, 0);
726	}
727	if (irq < 0)
728		return dev_err_probe(dev, irq, "error missing INT1 interrupt\n");
729
730	irq_type = irq_get_trigger_type(irq);
731	if (!irq_type)
732		irq_type = IRQF_TRIGGER_FALLING;
733
734	open_drain = device_property_read_bool(dev, "drive-open-drain");
735
736	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
737	if (!st)
738		return -ENOMEM;
739
740	dev_set_drvdata(dev, st);
741	mutex_init(&st->lock);
742	st->chip = chip;
743	st->map = regmap;
744	st->irq = irq;
745
746	ret = iio_read_mount_matrix(dev, &st->orientation);
747	if (ret) {
748		dev_err(dev, "failed to retrieve mounting matrix %d\n", ret);
749		return ret;
750	}
751
752	ret = devm_regulator_get_enable(dev, "vdd");
753	if (ret)
754		return dev_err_probe(dev, ret,
755				     "Failed to get vdd regulator\n");
756
757	msleep(INV_ICM42600_POWER_UP_TIME_MS);
758
759	st->vddio_supply = devm_regulator_get(dev, "vddio");
760	if (IS_ERR(st->vddio_supply))
761		return PTR_ERR(st->vddio_supply);
762
763	ret = inv_icm42600_enable_regulator_vddio(st);
764	if (ret)
765		return ret;
766
767	ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vddio_reg, st);
768	if (ret)
769		return ret;
770
771	/* setup chip registers */
772	ret = inv_icm42600_setup(st, bus_setup);
773	if (ret)
774		return ret;
775
776	ret = inv_icm42600_timestamp_setup(st);
777	if (ret)
778		return ret;
779
780	ret = inv_icm42600_buffer_init(st);
781	if (ret)
782		return ret;
783
784	st->indio_gyro = inv_icm42600_gyro_init(st);
785	if (IS_ERR(st->indio_gyro))
786		return PTR_ERR(st->indio_gyro);
787
788	st->indio_accel = inv_icm42600_accel_init(st);
789	if (IS_ERR(st->indio_accel))
790		return PTR_ERR(st->indio_accel);
791
792	ret = inv_icm42600_irq_init(st, irq, irq_type, open_drain);
793	if (ret)
794		return ret;
795
796	/* setup runtime power management */
797	ret = devm_pm_runtime_set_active_enabled(dev);
798	if (ret)
799		return ret;
800
801	pm_runtime_set_autosuspend_delay(dev, INV_ICM42600_SUSPEND_DELAY_MS);
802	pm_runtime_use_autosuspend(dev);
803
804	return ret;
805}
806EXPORT_SYMBOL_NS_GPL(inv_icm42600_core_probe, "IIO_ICM42600");
807
808/*
809 * Suspend saves sensors state and turns everything off.
810 * Check first if runtime suspend has not already done the job.
811 */
812static int inv_icm42600_suspend(struct device *dev)
813{
814	struct inv_icm42600_state *st = dev_get_drvdata(dev);
815	struct device *accel_dev;
816	bool wakeup;
817	int accel_conf;
818	int ret;
819
820	guard(mutex)(&st->lock);
821
822	st->suspended.gyro = st->conf.gyro.mode;
823	st->suspended.accel = st->conf.accel.mode;
824	st->suspended.temp = st->conf.temp_en;
825	if (pm_runtime_suspended(dev))
826		return 0;
827
828	/* disable FIFO data streaming */
829	if (st->fifo.on) {
830		ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
831				   INV_ICM42600_FIFO_CONFIG_BYPASS);
832		if (ret)
833			return ret;
834	}
835
836	/* keep chip on and wake-up capable if APEX and wakeup on */
837	accel_dev = &st->indio_accel->dev;
838	wakeup = st->apex.on && device_may_wakeup(accel_dev);
839	if (wakeup) {
840		/* keep accel on and setup irq for wakeup */
841		accel_conf = st->conf.accel.mode;
842		enable_irq_wake(st->irq);
843		disable_irq(st->irq);
844	} else {
845		/* disable APEX features and accel if wakeup disabled */
846		if (st->apex.wom.enable) {
847			ret = inv_icm42600_disable_wom(st);
848			if (ret)
849				return ret;
850		}
851		accel_conf = INV_ICM42600_SENSOR_MODE_OFF;
852	}
853
854	ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
855					 accel_conf, false, NULL);
856	if (ret)
857		return ret;
858
859	/* disable vddio regulator if chip is sleeping */
860	if (!wakeup)
861		regulator_disable(st->vddio_supply);
862
863	return 0;
864}
865
866/*
867 * System resume gets the system back on and restores the sensors state.
868 * Manually put runtime power management in system active state.
869 */
870static int inv_icm42600_resume(struct device *dev)
871{
872	struct inv_icm42600_state *st = dev_get_drvdata(dev);
873	struct inv_icm42600_sensor_state *gyro_st = iio_priv(st->indio_gyro);
874	struct inv_icm42600_sensor_state *accel_st = iio_priv(st->indio_accel);
875	struct device *accel_dev;
876	bool wakeup;
877	int ret;
878
879	guard(mutex)(&st->lock);
880
881	if (pm_runtime_suspended(dev))
882		return 0;
883
884	/* check wakeup capability */
885	accel_dev = &st->indio_accel->dev;
886	wakeup = st->apex.on && device_may_wakeup(accel_dev);
887	/* restore irq state or vddio if cut off */
888	if (wakeup) {
889		enable_irq(st->irq);
890		disable_irq_wake(st->irq);
891	} else {
892		ret = inv_icm42600_enable_regulator_vddio(st);
893		if (ret)
894			return ret;
895	}
896
897	/* restore sensors state */
898	ret = inv_icm42600_set_pwr_mgmt0(st, st->suspended.gyro,
899					 st->suspended.accel,
900					 st->suspended.temp, NULL);
901	if (ret)
902		return ret;
903
904	/* restore APEX features if disabled */
905	if (!wakeup && st->apex.wom.enable) {
906		ret = inv_icm42600_enable_wom(st);
907		if (ret)
908			return ret;
909	}
910
911	/* restore FIFO data streaming */
912	if (st->fifo.on) {
913		inv_sensors_timestamp_reset(&gyro_st->ts);
914		inv_sensors_timestamp_reset(&accel_st->ts);
915		ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
916				   INV_ICM42600_FIFO_CONFIG_STREAM);
917	}
918
919	return 0;
920}
921
922/* Runtime suspend will turn off sensors that are enabled by iio devices. */
923static int inv_icm42600_runtime_suspend(struct device *dev)
924{
925	struct inv_icm42600_state *st = dev_get_drvdata(dev);
926	int ret;
927
928	guard(mutex)(&st->lock);
929
930	/* disable all sensors */
931	ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
932					 INV_ICM42600_SENSOR_MODE_OFF, false,
933					 NULL);
934	if (ret)
935		return ret;
936
937	regulator_disable(st->vddio_supply);
938
939	return 0;
940}
941
942/* Sensors are enabled by iio devices, no need to turn them back on here. */
943static int inv_icm42600_runtime_resume(struct device *dev)
944{
945	struct inv_icm42600_state *st = dev_get_drvdata(dev);
946
947	guard(mutex)(&st->lock);
948
949	return inv_icm42600_enable_regulator_vddio(st);
950}
951
952EXPORT_NS_GPL_DEV_PM_OPS(inv_icm42600_pm_ops, IIO_ICM42600) = {
953	SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume)
954	RUNTIME_PM_OPS(inv_icm42600_runtime_suspend,
955		       inv_icm42600_runtime_resume, NULL)
956};
957
958MODULE_AUTHOR("InvenSense, Inc.");
959MODULE_DESCRIPTION("InvenSense ICM-426xx device driver");
960MODULE_LICENSE("GPL");
961MODULE_IMPORT_NS("IIO_INV_SENSORS_TIMESTAMP");
~/ Read-only file preview.