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
37const struct regmap_config inv_icm42600_regmap_config = {
38 .reg_bits = 8,
39 .val_bits = 8,
40 .max_register = 0x4FFF,
41 .ranges = inv_icm42600_regmap_ranges,
42 .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges),
43};
44EXPORT_SYMBOL_NS_GPL(inv_icm42600_regmap_config, IIO_ICM42600);
45
46struct inv_icm42600_hw {
47 uint8_t whoami;
48 const char *name;
49 const struct inv_icm42600_conf *conf;
50};
51
52/* chip initial default configuration */
53static const struct inv_icm42600_conf inv_icm42600_default_conf = {
54 .gyro = {
55 .mode = INV_ICM42600_SENSOR_MODE_OFF,
56 .fs = INV_ICM42600_GYRO_FS_2000DPS,
57 .odr = INV_ICM42600_ODR_50HZ,
58 .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
59 },
60 .accel = {
61 .mode = INV_ICM42600_SENSOR_MODE_OFF,
62 .fs = INV_ICM42600_ACCEL_FS_16G,
63 .odr = INV_ICM42600_ODR_50HZ,
64 .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2,
65 },
66 .temp_en = false,
67};
68
69static const struct inv_icm42600_hw inv_icm42600_hw[INV_CHIP_NB] = {
70 [INV_CHIP_ICM42600] = {
71 .whoami = INV_ICM42600_WHOAMI_ICM42600,
72 .name = "icm42600",
73 .conf = &inv_icm42600_default_conf,
74 },
75 [INV_CHIP_ICM42602] = {
76 .whoami = INV_ICM42600_WHOAMI_ICM42602,
77 .name = "icm42602",
78 .conf = &inv_icm42600_default_conf,
79 },
80 [INV_CHIP_ICM42605] = {
81 .whoami = INV_ICM42600_WHOAMI_ICM42605,
82 .name = "icm42605",
83 .conf = &inv_icm42600_default_conf,
84 },
85 [INV_CHIP_ICM42622] = {
86 .whoami = INV_ICM42600_WHOAMI_ICM42622,
87 .name = "icm42622",
88 .conf = &inv_icm42600_default_conf,
89 },
90 [INV_CHIP_ICM42631] = {
91 .whoami = INV_ICM42600_WHOAMI_ICM42631,
92 .name = "icm42631",
93 .conf = &inv_icm42600_default_conf,
94 },
95};
96
97const struct iio_mount_matrix *
98inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev,
99 const struct iio_chan_spec *chan)
100{
101 const struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
102
103 return &st->orientation;
104}
105
106uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr)
107{
108 static uint32_t odr_periods[INV_ICM42600_ODR_NB] = {
109 /* reserved values */
110 0, 0, 0,
111 /* 8kHz */
112 125000,
113 /* 4kHz */
114 250000,
115 /* 2kHz */
116 500000,
117 /* 1kHz */
118 1000000,
119 /* 200Hz */
120 5000000,
121 /* 100Hz */
122 10000000,
123 /* 50Hz */
124 20000000,
125 /* 25Hz */
126 40000000,
127 /* 12.5Hz */
128 80000000,
129 /* 6.25Hz */
130 160000000,
131 /* 3.125Hz */
132 320000000,
133 /* 1.5625Hz */
134 640000000,
135 /* 500Hz */
136 2000000,
137 };
138
139 return odr_periods[odr];
140}
141
142static int inv_icm42600_set_pwr_mgmt0(struct inv_icm42600_state *st,
143 enum inv_icm42600_sensor_mode gyro,
144 enum inv_icm42600_sensor_mode accel,
145 bool temp, unsigned int *sleep_ms)
146{
147 enum inv_icm42600_sensor_mode oldgyro = st->conf.gyro.mode;
148 enum inv_icm42600_sensor_mode oldaccel = st->conf.accel.mode;
149 bool oldtemp = st->conf.temp_en;
150 unsigned int sleepval;
151 unsigned int val;
152 int ret;
153
154 /* if nothing changed, exit */
155 if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
156 return 0;
157
158 val = INV_ICM42600_PWR_MGMT0_GYRO(gyro) |
159 INV_ICM42600_PWR_MGMT0_ACCEL(accel);
160 if (!temp)
161 val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
162 ret = regmap_write(map: st->map, INV_ICM42600_REG_PWR_MGMT0, val);
163 if (ret)
164 return ret;
165
166 st->conf.gyro.mode = gyro;
167 st->conf.accel.mode = accel;
168 st->conf.temp_en = temp;
169
170 /* compute required wait time for sensors to stabilize */
171 sleepval = 0;
172 /* temperature stabilization time */
173 if (temp && !oldtemp) {
174 if (sleepval < INV_ICM42600_TEMP_STARTUP_TIME_MS)
175 sleepval = INV_ICM42600_TEMP_STARTUP_TIME_MS;
176 }
177 /* accel startup time */
178 if (accel != oldaccel && oldaccel == INV_ICM42600_SENSOR_MODE_OFF) {
179 /* block any register write for at least 200 µs */
180 usleep_range(min: 200, max: 300);
181 if (sleepval < INV_ICM42600_ACCEL_STARTUP_TIME_MS)
182 sleepval = INV_ICM42600_ACCEL_STARTUP_TIME_MS;
183 }
184 if (gyro != oldgyro) {
185 /* gyro startup time */
186 if (oldgyro == INV_ICM42600_SENSOR_MODE_OFF) {
187 /* block any register write for at least 200 µs */
188 usleep_range(min: 200, max: 300);
189 if (sleepval < INV_ICM42600_GYRO_STARTUP_TIME_MS)
190 sleepval = INV_ICM42600_GYRO_STARTUP_TIME_MS;
191 /* gyro stop time */
192 } else if (gyro == INV_ICM42600_SENSOR_MODE_OFF) {
193 if (sleepval < INV_ICM42600_GYRO_STOP_TIME_MS)
194 sleepval = INV_ICM42600_GYRO_STOP_TIME_MS;
195 }
196 }
197
198 /* deferred sleep value if sleep pointer is provided or direct sleep */
199 if (sleep_ms)
200 *sleep_ms = sleepval;
201 else if (sleepval)
202 msleep(msecs: sleepval);
203
204 return 0;
205}
206
207int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st,
208 struct inv_icm42600_sensor_conf *conf,
209 unsigned int *sleep_ms)
210{
211 struct inv_icm42600_sensor_conf *oldconf = &st->conf.accel;
212 unsigned int val;
213 int ret;
214
215 /* Sanitize missing values with current values */
216 if (conf->mode < 0)
217 conf->mode = oldconf->mode;
218 if (conf->fs < 0)
219 conf->fs = oldconf->fs;
220 if (conf->odr < 0)
221 conf->odr = oldconf->odr;
222 if (conf->filter < 0)
223 conf->filter = oldconf->filter;
224
225 /* set ACCEL_CONFIG0 register (accel fullscale & odr) */
226 if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
227 val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) |
228 INV_ICM42600_ACCEL_CONFIG0_ODR(conf->odr);
229 ret = regmap_write(map: st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
230 if (ret)
231 return ret;
232 oldconf->fs = conf->fs;
233 oldconf->odr = conf->odr;
234 }
235
236 /* set GYRO_ACCEL_CONFIG0 register (accel filter) */
237 if (conf->filter != oldconf->filter) {
238 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->filter) |
239 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(st->conf.gyro.filter);
240 ret = regmap_write(map: st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
241 if (ret)
242 return ret;
243 oldconf->filter = conf->filter;
244 }
245
246 /* set PWR_MGMT0 register (accel sensor mode) */
247 return inv_icm42600_set_pwr_mgmt0(st, gyro: st->conf.gyro.mode, accel: conf->mode,
248 temp: st->conf.temp_en, sleep_ms);
249}
250
251int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st,
252 struct inv_icm42600_sensor_conf *conf,
253 unsigned int *sleep_ms)
254{
255 struct inv_icm42600_sensor_conf *oldconf = &st->conf.gyro;
256 unsigned int val;
257 int ret;
258
259 /* sanitize missing values with current values */
260 if (conf->mode < 0)
261 conf->mode = oldconf->mode;
262 if (conf->fs < 0)
263 conf->fs = oldconf->fs;
264 if (conf->odr < 0)
265 conf->odr = oldconf->odr;
266 if (conf->filter < 0)
267 conf->filter = oldconf->filter;
268
269 /* set GYRO_CONFIG0 register (gyro fullscale & odr) */
270 if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
271 val = INV_ICM42600_GYRO_CONFIG0_FS(conf->fs) |
272 INV_ICM42600_GYRO_CONFIG0_ODR(conf->odr);
273 ret = regmap_write(map: st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
274 if (ret)
275 return ret;
276 oldconf->fs = conf->fs;
277 oldconf->odr = conf->odr;
278 }
279
280 /* set GYRO_ACCEL_CONFIG0 register (gyro filter) */
281 if (conf->filter != oldconf->filter) {
282 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(st->conf.accel.filter) |
283 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->filter);
284 ret = regmap_write(map: st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
285 if (ret)
286 return ret;
287 oldconf->filter = conf->filter;
288 }
289
290 /* set PWR_MGMT0 register (gyro sensor mode) */
291 return inv_icm42600_set_pwr_mgmt0(st, gyro: conf->mode, accel: st->conf.accel.mode,
292 temp: st->conf.temp_en, sleep_ms);
293
294 return 0;
295}
296
297int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable,
298 unsigned int *sleep_ms)
299{
300 return inv_icm42600_set_pwr_mgmt0(st, gyro: st->conf.gyro.mode,
301 accel: st->conf.accel.mode, temp: enable,
302 sleep_ms);
303}
304
305int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
306 unsigned int writeval, unsigned int *readval)
307{
308 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
309 int ret;
310
311 mutex_lock(&st->lock);
312
313 if (readval)
314 ret = regmap_read(map: st->map, reg, val: readval);
315 else
316 ret = regmap_write(map: st->map, reg, val: writeval);
317
318 mutex_unlock(lock: &st->lock);
319
320 return ret;
321}
322
323static int inv_icm42600_set_conf(struct inv_icm42600_state *st,
324 const struct inv_icm42600_conf *conf)
325{
326 unsigned int val;
327 int ret;
328
329 /* set PWR_MGMT0 register (gyro & accel sensor mode, temp enabled) */
330 val = INV_ICM42600_PWR_MGMT0_GYRO(conf->gyro.mode) |
331 INV_ICM42600_PWR_MGMT0_ACCEL(conf->accel.mode);
332 if (!conf->temp_en)
333 val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
334 ret = regmap_write(map: st->map, INV_ICM42600_REG_PWR_MGMT0, val);
335 if (ret)
336 return ret;
337
338 /* set GYRO_CONFIG0 register (gyro fullscale & odr) */
339 val = INV_ICM42600_GYRO_CONFIG0_FS(conf->gyro.fs) |
340 INV_ICM42600_GYRO_CONFIG0_ODR(conf->gyro.odr);
341 ret = regmap_write(map: st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
342 if (ret)
343 return ret;
344
345 /* set ACCEL_CONFIG0 register (accel fullscale & odr) */
346 val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->accel.fs) |
347 INV_ICM42600_ACCEL_CONFIG0_ODR(conf->accel.odr);
348 ret = regmap_write(map: st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
349 if (ret)
350 return ret;
351
352 /* set GYRO_ACCEL_CONFIG0 register (gyro & accel filters) */
353 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->accel.filter) |
354 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->gyro.filter);
355 ret = regmap_write(map: st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
356 if (ret)
357 return ret;
358
359 /* update internal conf */
360 st->conf = *conf;
361
362 return 0;
363}
364
365/**
366 * inv_icm42600_setup() - check and setup chip
367 * @st: driver internal state
368 * @bus_setup: callback for setting up bus specific registers
369 *
370 * Returns 0 on success, a negative error code otherwise.
371 */
372static int inv_icm42600_setup(struct inv_icm42600_state *st,
373 inv_icm42600_bus_setup bus_setup)
374{
375 const struct inv_icm42600_hw *hw = &inv_icm42600_hw[st->chip];
376 const struct device *dev = regmap_get_device(map: st->map);
377 unsigned int val;
378 int ret;
379
380 /* check chip self-identification value */
381 ret = regmap_read(map: st->map, INV_ICM42600_REG_WHOAMI, val: &val);
382 if (ret)
383 return ret;
384 if (val != hw->whoami) {
385 dev_err(dev, "invalid whoami %#02x expected %#02x (%s)\n",
386 val, hw->whoami, hw->name);
387 return -ENODEV;
388 }
389 st->name = hw->name;
390
391 /* reset to make sure previous state are not there */
392 ret = regmap_write(map: st->map, INV_ICM42600_REG_DEVICE_CONFIG,
393 INV_ICM42600_DEVICE_CONFIG_SOFT_RESET);
394 if (ret)
395 return ret;
396 msleep(INV_ICM42600_RESET_TIME_MS);
397
398 ret = regmap_read(map: st->map, INV_ICM42600_REG_INT_STATUS, val: &val);
399 if (ret)
400 return ret;
401 if (!(val & INV_ICM42600_INT_STATUS_RESET_DONE)) {
402 dev_err(dev, "reset error, reset done bit not set\n");
403 return -ENODEV;
404 }
405
406 /* set chip bus configuration */
407 ret = bus_setup(st);
408 if (ret)
409 return ret;
410
411 /* sensor data in big-endian (default) */
412 ret = regmap_update_bits(map: st->map, INV_ICM42600_REG_INTF_CONFIG0,
413 INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN,
414 INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN);
415 if (ret)
416 return ret;
417
418 return inv_icm42600_set_conf(st, conf: hw->conf);
419}
420
421static irqreturn_t inv_icm42600_irq_timestamp(int irq, void *_data)
422{
423 struct inv_icm42600_state *st = _data;
424
425 st->timestamp.gyro = iio_get_time_ns(indio_dev: st->indio_gyro);
426 st->timestamp.accel = iio_get_time_ns(indio_dev: st->indio_accel);
427
428 return IRQ_WAKE_THREAD;
429}
430
431static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
432{
433 struct inv_icm42600_state *st = _data;
434 struct device *dev = regmap_get_device(map: st->map);
435 unsigned int status;
436 int ret;
437
438 mutex_lock(&st->lock);
439
440 ret = regmap_read(map: st->map, INV_ICM42600_REG_INT_STATUS, val: &status);
441 if (ret)
442 goto out_unlock;
443
444 /* FIFO full */
445 if (status & INV_ICM42600_INT_STATUS_FIFO_FULL)
446 dev_warn(dev, "FIFO full data lost!\n");
447
448 /* FIFO threshold reached */
449 if (status & INV_ICM42600_INT_STATUS_FIFO_THS) {
450 ret = inv_icm42600_buffer_fifo_read(st, max: 0);
451 if (ret) {
452 dev_err(dev, "FIFO read error %d\n", ret);
453 goto out_unlock;
454 }
455 ret = inv_icm42600_buffer_fifo_parse(st);
456 if (ret)
457 dev_err(dev, "FIFO parsing error %d\n", ret);
458 }
459
460out_unlock:
461 mutex_unlock(lock: &st->lock);
462 return IRQ_HANDLED;
463}
464
465/**
466 * inv_icm42600_irq_init() - initialize int pin and interrupt handler
467 * @st: driver internal state
468 * @irq: irq number
469 * @irq_type: irq trigger type
470 * @open_drain: true if irq is open drain, false for push-pull
471 *
472 * Returns 0 on success, a negative error code otherwise.
473 */
474static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
475 int irq_type, bool open_drain)
476{
477 struct device *dev = regmap_get_device(map: st->map);
478 unsigned int val;
479 int ret;
480
481 /* configure INT1 interrupt: default is active low on edge */
482 switch (irq_type) {
483 case IRQF_TRIGGER_RISING:
484 case IRQF_TRIGGER_HIGH:
485 val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH;
486 break;
487 default:
488 val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW;
489 break;
490 }
491
492 switch (irq_type) {
493 case IRQF_TRIGGER_LOW:
494 case IRQF_TRIGGER_HIGH:
495 val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED;
496 break;
497 default:
498 break;
499 }
500
501 if (!open_drain)
502 val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL;
503
504 ret = regmap_write(map: st->map, INV_ICM42600_REG_INT_CONFIG, val);
505 if (ret)
506 return ret;
507
508 /* Deassert async reset for proper INT pin operation (cf datasheet) */
509 ret = regmap_update_bits(map: st->map, INV_ICM42600_REG_INT_CONFIG1,
510 INV_ICM42600_INT_CONFIG1_ASYNC_RESET, val: 0);
511 if (ret)
512 return ret;
513
514 return devm_request_threaded_irq(dev, irq, handler: inv_icm42600_irq_timestamp,
515 thread_fn: inv_icm42600_irq_handler, irqflags: irq_type,
516 devname: "inv_icm42600", dev_id: st);
517}
518
519static int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st)
520{
521 unsigned int val;
522
523 /* enable timestamp register */
524 val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN |
525 INV_ICM42600_TMST_CONFIG_TMST_EN;
526 return regmap_update_bits(map: st->map, INV_ICM42600_REG_TMST_CONFIG,
527 INV_ICM42600_TMST_CONFIG_MASK, val);
528}
529
530static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st)
531{
532 int ret;
533
534 ret = regulator_enable(regulator: st->vddio_supply);
535 if (ret)
536 return ret;
537
538 /* wait a little for supply ramp */
539 usleep_range(min: 3000, max: 4000);
540
541 return 0;
542}
543
544static void inv_icm42600_disable_vdd_reg(void *_data)
545{
546 struct inv_icm42600_state *st = _data;
547 const struct device *dev = regmap_get_device(map: st->map);
548 int ret;
549
550 ret = regulator_disable(regulator: st->vdd_supply);
551 if (ret)
552 dev_err(dev, "failed to disable vdd error %d\n", ret);
553}
554
555static void inv_icm42600_disable_vddio_reg(void *_data)
556{
557 struct inv_icm42600_state *st = _data;
558 const struct device *dev = regmap_get_device(map: st->map);
559 int ret;
560
561 ret = regulator_disable(regulator: st->vddio_supply);
562 if (ret)
563 dev_err(dev, "failed to disable vddio error %d\n", ret);
564}
565
566static void inv_icm42600_disable_pm(void *_data)
567{
568 struct device *dev = _data;
569
570 pm_runtime_put_sync(dev);
571 pm_runtime_disable(dev);
572}
573
574int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
575 inv_icm42600_bus_setup bus_setup)
576{
577 struct device *dev = regmap_get_device(map: regmap);
578 struct inv_icm42600_state *st;
579 struct irq_data *irq_desc;
580 int irq_type;
581 bool open_drain;
582 int ret;
583
584 if (chip <= INV_CHIP_INVALID || chip >= INV_CHIP_NB) {
585 dev_err(dev, "invalid chip = %d\n", chip);
586 return -ENODEV;
587 }
588
589 /* get irq properties, set trigger falling by default */
590 irq_desc = irq_get_irq_data(irq);
591 if (!irq_desc) {
592 dev_err(dev, "could not find IRQ %d\n", irq);
593 return -EINVAL;
594 }
595
596 irq_type = irqd_get_trigger_type(d: irq_desc);
597 if (!irq_type)
598 irq_type = IRQF_TRIGGER_FALLING;
599
600 open_drain = device_property_read_bool(dev, propname: "drive-open-drain");
601
602 st = devm_kzalloc(dev, size: sizeof(*st), GFP_KERNEL);
603 if (!st)
604 return -ENOMEM;
605
606 dev_set_drvdata(dev, data: st);
607 mutex_init(&st->lock);
608 st->chip = chip;
609 st->map = regmap;
610
611 ret = iio_read_mount_matrix(dev, matrix: &st->orientation);
612 if (ret) {
613 dev_err(dev, "failed to retrieve mounting matrix %d\n", ret);
614 return ret;
615 }
616
617 st->vdd_supply = devm_regulator_get(dev, id: "vdd");
618 if (IS_ERR(ptr: st->vdd_supply))
619 return PTR_ERR(ptr: st->vdd_supply);
620
621 st->vddio_supply = devm_regulator_get(dev, id: "vddio");
622 if (IS_ERR(ptr: st->vddio_supply))
623 return PTR_ERR(ptr: st->vddio_supply);
624
625 ret = regulator_enable(regulator: st->vdd_supply);
626 if (ret)
627 return ret;
628 msleep(INV_ICM42600_POWER_UP_TIME_MS);
629
630 ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vdd_reg, st);
631 if (ret)
632 return ret;
633
634 ret = inv_icm42600_enable_regulator_vddio(st);
635 if (ret)
636 return ret;
637
638 ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vddio_reg, st);
639 if (ret)
640 return ret;
641
642 /* setup chip registers */
643 ret = inv_icm42600_setup(st, bus_setup);
644 if (ret)
645 return ret;
646
647 ret = inv_icm42600_timestamp_setup(st);
648 if (ret)
649 return ret;
650
651 ret = inv_icm42600_buffer_init(st);
652 if (ret)
653 return ret;
654
655 st->indio_gyro = inv_icm42600_gyro_init(st);
656 if (IS_ERR(ptr: st->indio_gyro))
657 return PTR_ERR(ptr: st->indio_gyro);
658
659 st->indio_accel = inv_icm42600_accel_init(st);
660 if (IS_ERR(ptr: st->indio_accel))
661 return PTR_ERR(ptr: st->indio_accel);
662
663 ret = inv_icm42600_irq_init(st, irq, irq_type, open_drain);
664 if (ret)
665 return ret;
666
667 /* setup runtime power management */
668 ret = pm_runtime_set_active(dev);
669 if (ret)
670 return ret;
671 pm_runtime_get_noresume(dev);
672 pm_runtime_enable(dev);
673 pm_runtime_set_autosuspend_delay(dev, INV_ICM42600_SUSPEND_DELAY_MS);
674 pm_runtime_use_autosuspend(dev);
675 pm_runtime_put(dev);
676
677 return devm_add_action_or_reset(dev, inv_icm42600_disable_pm, dev);
678}
679EXPORT_SYMBOL_NS_GPL(inv_icm42600_core_probe, IIO_ICM42600);
680
681/*
682 * Suspend saves sensors state and turns everything off.
683 * Check first if runtime suspend has not already done the job.
684 */
685static int inv_icm42600_suspend(struct device *dev)
686{
687 struct inv_icm42600_state *st = dev_get_drvdata(dev);
688 int ret;
689
690 mutex_lock(&st->lock);
691
692 st->suspended.gyro = st->conf.gyro.mode;
693 st->suspended.accel = st->conf.accel.mode;
694 st->suspended.temp = st->conf.temp_en;
695 if (pm_runtime_suspended(dev)) {
696 ret = 0;
697 goto out_unlock;
698 }
699
700 /* disable FIFO data streaming */
701 if (st->fifo.on) {
702 ret = regmap_write(map: st->map, INV_ICM42600_REG_FIFO_CONFIG,
703 INV_ICM42600_FIFO_CONFIG_BYPASS);
704 if (ret)
705 goto out_unlock;
706 }
707
708 ret = inv_icm42600_set_pwr_mgmt0(st, gyro: INV_ICM42600_SENSOR_MODE_OFF,
709 accel: INV_ICM42600_SENSOR_MODE_OFF, temp: false,
710 NULL);
711 if (ret)
712 goto out_unlock;
713
714 regulator_disable(regulator: st->vddio_supply);
715
716out_unlock:
717 mutex_unlock(lock: &st->lock);
718 return ret;
719}
720
721/*
722 * System resume gets the system back on and restores the sensors state.
723 * Manually put runtime power management in system active state.
724 */
725static int inv_icm42600_resume(struct device *dev)
726{
727 struct inv_icm42600_state *st = dev_get_drvdata(dev);
728 int ret;
729
730 mutex_lock(&st->lock);
731
732 ret = inv_icm42600_enable_regulator_vddio(st);
733 if (ret)
734 goto out_unlock;
735
736 pm_runtime_disable(dev);
737 pm_runtime_set_active(dev);
738 pm_runtime_enable(dev);
739
740 /* restore sensors state */
741 ret = inv_icm42600_set_pwr_mgmt0(st, gyro: st->suspended.gyro,
742 accel: st->suspended.accel,
743 temp: st->suspended.temp, NULL);
744 if (ret)
745 goto out_unlock;
746
747 /* restore FIFO data streaming */
748 if (st->fifo.on)
749 ret = regmap_write(map: st->map, INV_ICM42600_REG_FIFO_CONFIG,
750 INV_ICM42600_FIFO_CONFIG_STREAM);
751
752out_unlock:
753 mutex_unlock(lock: &st->lock);
754 return ret;
755}
756
757/* Runtime suspend will turn off sensors that are enabled by iio devices. */
758static int inv_icm42600_runtime_suspend(struct device *dev)
759{
760 struct inv_icm42600_state *st = dev_get_drvdata(dev);
761 int ret;
762
763 mutex_lock(&st->lock);
764
765 /* disable all sensors */
766 ret = inv_icm42600_set_pwr_mgmt0(st, gyro: INV_ICM42600_SENSOR_MODE_OFF,
767 accel: INV_ICM42600_SENSOR_MODE_OFF, temp: false,
768 NULL);
769 if (ret)
770 goto error_unlock;
771
772 regulator_disable(regulator: st->vddio_supply);
773
774error_unlock:
775 mutex_unlock(lock: &st->lock);
776 return ret;
777}
778
779/* Sensors are enabled by iio devices, no need to turn them back on here. */
780static int inv_icm42600_runtime_resume(struct device *dev)
781{
782 struct inv_icm42600_state *st = dev_get_drvdata(dev);
783 int ret;
784
785 mutex_lock(&st->lock);
786
787 ret = inv_icm42600_enable_regulator_vddio(st);
788
789 mutex_unlock(lock: &st->lock);
790 return ret;
791}
792
793EXPORT_NS_GPL_DEV_PM_OPS(inv_icm42600_pm_ops, IIO_ICM42600) = {
794 SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume)
795 RUNTIME_PM_OPS(inv_icm42600_runtime_suspend,
796 inv_icm42600_runtime_resume, NULL)
797};
798
799MODULE_AUTHOR("InvenSense, Inc.");
800MODULE_DESCRIPTION("InvenSense ICM-426xx device driver");
801MODULE_LICENSE("GPL");
802MODULE_IMPORT_NS(IIO_INV_SENSORS_TIMESTAMP);
803

source code of linux/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c