1
2
3
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#include <linux/iio/iio.h>
19
20#include "inv_icm42600.h"
21#include "inv_icm42600_buffer.h"
22#include "inv_icm42600_timestamp.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_GPL(inv_icm42600_regmap_config);
45
46struct inv_icm42600_hw {
47 uint8_t whoami;
48 const char *name;
49 const struct inv_icm42600_conf *conf;
50};
51
52
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};
91
92const struct iio_mount_matrix *
93inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev,
94 const struct iio_chan_spec *chan)
95{
96 const struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
97
98 return &st->orientation;
99}
100
101uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr)
102{
103 static uint32_t odr_periods[INV_ICM42600_ODR_NB] = {
104
105 0, 0, 0,
106
107 125000,
108
109 250000,
110
111 500000,
112
113 1000000,
114
115 5000000,
116
117 10000000,
118
119 20000000,
120
121 40000000,
122
123 80000000,
124
125 160000000,
126
127 320000000,
128
129 640000000,
130
131 2000000,
132 };
133
134 return odr_periods[odr];
135}
136
137static int inv_icm42600_set_pwr_mgmt0(struct inv_icm42600_state *st,
138 enum inv_icm42600_sensor_mode gyro,
139 enum inv_icm42600_sensor_mode accel,
140 bool temp, unsigned int *sleep_ms)
141{
142 enum inv_icm42600_sensor_mode oldgyro = st->conf.gyro.mode;
143 enum inv_icm42600_sensor_mode oldaccel = st->conf.accel.mode;
144 bool oldtemp = st->conf.temp_en;
145 unsigned int sleepval;
146 unsigned int val;
147 int ret;
148
149
150 if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
151 return 0;
152
153 val = INV_ICM42600_PWR_MGMT0_GYRO(gyro) |
154 INV_ICM42600_PWR_MGMT0_ACCEL(accel);
155 if (!temp)
156 val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
157 ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val);
158 if (ret)
159 return ret;
160
161 st->conf.gyro.mode = gyro;
162 st->conf.accel.mode = accel;
163 st->conf.temp_en = temp;
164
165
166 sleepval = 0;
167
168 if (temp && !oldtemp) {
169 if (sleepval < INV_ICM42600_TEMP_STARTUP_TIME_MS)
170 sleepval = INV_ICM42600_TEMP_STARTUP_TIME_MS;
171 }
172
173 if (accel != oldaccel && oldaccel == INV_ICM42600_SENSOR_MODE_OFF) {
174
175 usleep_range(200, 300);
176 if (sleepval < INV_ICM42600_ACCEL_STARTUP_TIME_MS)
177 sleepval = INV_ICM42600_ACCEL_STARTUP_TIME_MS;
178 }
179 if (gyro != oldgyro) {
180
181 if (oldgyro == INV_ICM42600_SENSOR_MODE_OFF) {
182
183 usleep_range(200, 300);
184 if (sleepval < INV_ICM42600_GYRO_STARTUP_TIME_MS)
185 sleepval = INV_ICM42600_GYRO_STARTUP_TIME_MS;
186
187 } else if (gyro == INV_ICM42600_SENSOR_MODE_OFF) {
188 if (sleepval < INV_ICM42600_GYRO_STOP_TIME_MS)
189 sleepval = INV_ICM42600_GYRO_STOP_TIME_MS;
190 }
191 }
192
193
194 if (sleep_ms)
195 *sleep_ms = sleepval;
196 else if (sleepval)
197 msleep(sleepval);
198
199 return 0;
200}
201
202int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st,
203 struct inv_icm42600_sensor_conf *conf,
204 unsigned int *sleep_ms)
205{
206 struct inv_icm42600_sensor_conf *oldconf = &st->conf.accel;
207 unsigned int val;
208 int ret;
209
210
211 if (conf->mode < 0)
212 conf->mode = oldconf->mode;
213 if (conf->fs < 0)
214 conf->fs = oldconf->fs;
215 if (conf->odr < 0)
216 conf->odr = oldconf->odr;
217 if (conf->filter < 0)
218 conf->filter = oldconf->filter;
219
220
221 if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
222 val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) |
223 INV_ICM42600_ACCEL_CONFIG0_ODR(conf->odr);
224 ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
225 if (ret)
226 return ret;
227 oldconf->fs = conf->fs;
228 oldconf->odr = conf->odr;
229 }
230
231
232 if (conf->filter != oldconf->filter) {
233 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->filter) |
234 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(st->conf.gyro.filter);
235 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
236 if (ret)
237 return ret;
238 oldconf->filter = conf->filter;
239 }
240
241
242 return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode,
243 st->conf.temp_en, sleep_ms);
244}
245
246int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st,
247 struct inv_icm42600_sensor_conf *conf,
248 unsigned int *sleep_ms)
249{
250 struct inv_icm42600_sensor_conf *oldconf = &st->conf.gyro;
251 unsigned int val;
252 int ret;
253
254
255 if (conf->mode < 0)
256 conf->mode = oldconf->mode;
257 if (conf->fs < 0)
258 conf->fs = oldconf->fs;
259 if (conf->odr < 0)
260 conf->odr = oldconf->odr;
261 if (conf->filter < 0)
262 conf->filter = oldconf->filter;
263
264
265 if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
266 val = INV_ICM42600_GYRO_CONFIG0_FS(conf->fs) |
267 INV_ICM42600_GYRO_CONFIG0_ODR(conf->odr);
268 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
269 if (ret)
270 return ret;
271 oldconf->fs = conf->fs;
272 oldconf->odr = conf->odr;
273 }
274
275
276 if (conf->filter != oldconf->filter) {
277 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(st->conf.accel.filter) |
278 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->filter);
279 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
280 if (ret)
281 return ret;
282 oldconf->filter = conf->filter;
283 }
284
285
286 return inv_icm42600_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode,
287 st->conf.temp_en, sleep_ms);
288
289 return 0;
290}
291
292int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable,
293 unsigned int *sleep_ms)
294{
295 return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode,
296 st->conf.accel.mode, enable,
297 sleep_ms);
298}
299
300int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
301 unsigned int writeval, unsigned int *readval)
302{
303 struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
304 int ret;
305
306 mutex_lock(&st->lock);
307
308 if (readval)
309 ret = regmap_read(st->map, reg, readval);
310 else
311 ret = regmap_write(st->map, reg, writeval);
312
313 mutex_unlock(&st->lock);
314
315 return ret;
316}
317
318static int inv_icm42600_set_conf(struct inv_icm42600_state *st,
319 const struct inv_icm42600_conf *conf)
320{
321 unsigned int val;
322 int ret;
323
324
325 val = INV_ICM42600_PWR_MGMT0_GYRO(conf->gyro.mode) |
326 INV_ICM42600_PWR_MGMT0_ACCEL(conf->accel.mode);
327 if (!conf->temp_en)
328 val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS;
329 ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val);
330 if (ret)
331 return ret;
332
333
334 val = INV_ICM42600_GYRO_CONFIG0_FS(conf->gyro.fs) |
335 INV_ICM42600_GYRO_CONFIG0_ODR(conf->gyro.odr);
336 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val);
337 if (ret)
338 return ret;
339
340
341 val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->accel.fs) |
342 INV_ICM42600_ACCEL_CONFIG0_ODR(conf->accel.odr);
343 ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val);
344 if (ret)
345 return ret;
346
347
348 val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->accel.filter) |
349 INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->gyro.filter);
350 ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val);
351 if (ret)
352 return ret;
353
354
355 st->conf = *conf;
356
357 return 0;
358}
359
360
361
362
363
364
365
366
367static int inv_icm42600_setup(struct inv_icm42600_state *st,
368 inv_icm42600_bus_setup bus_setup)
369{
370 const struct inv_icm42600_hw *hw = &inv_icm42600_hw[st->chip];
371 const struct device *dev = regmap_get_device(st->map);
372 unsigned int val;
373 int ret;
374
375
376 ret = regmap_read(st->map, INV_ICM42600_REG_WHOAMI, &val);
377 if (ret)
378 return ret;
379 if (val != hw->whoami) {
380 dev_err(dev, "invalid whoami %#02x expected %#02x (%s)\n",
381 val, hw->whoami, hw->name);
382 return -ENODEV;
383 }
384 st->name = hw->name;
385
386
387 ret = regmap_write(st->map, INV_ICM42600_REG_DEVICE_CONFIG,
388 INV_ICM42600_DEVICE_CONFIG_SOFT_RESET);
389 if (ret)
390 return ret;
391 msleep(INV_ICM42600_RESET_TIME_MS);
392
393 ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &val);
394 if (ret)
395 return ret;
396 if (!(val & INV_ICM42600_INT_STATUS_RESET_DONE)) {
397 dev_err(dev, "reset error, reset done bit not set\n");
398 return -ENODEV;
399 }
400
401
402 ret = bus_setup(st);
403 if (ret)
404 return ret;
405
406
407 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
408 INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN,
409 INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN);
410 if (ret)
411 return ret;
412
413 return inv_icm42600_set_conf(st, hw->conf);
414}
415
416static irqreturn_t inv_icm42600_irq_timestamp(int irq, void *_data)
417{
418 struct inv_icm42600_state *st = _data;
419
420 st->timestamp.gyro = iio_get_time_ns(st->indio_gyro);
421 st->timestamp.accel = iio_get_time_ns(st->indio_accel);
422
423 return IRQ_WAKE_THREAD;
424}
425
426static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
427{
428 struct inv_icm42600_state *st = _data;
429 struct device *dev = regmap_get_device(st->map);
430 unsigned int status;
431 int ret;
432
433 mutex_lock(&st->lock);
434
435 ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status);
436 if (ret)
437 goto out_unlock;
438
439
440 if (status & INV_ICM42600_INT_STATUS_FIFO_FULL)
441 dev_warn(dev, "FIFO full data lost!\n");
442
443
444 if (status & INV_ICM42600_INT_STATUS_FIFO_THS) {
445 ret = inv_icm42600_buffer_fifo_read(st, 0);
446 if (ret) {
447 dev_err(dev, "FIFO read error %d\n", ret);
448 goto out_unlock;
449 }
450 ret = inv_icm42600_buffer_fifo_parse(st);
451 if (ret)
452 dev_err(dev, "FIFO parsing error %d\n", ret);
453 }
454
455out_unlock:
456 mutex_unlock(&st->lock);
457 return IRQ_HANDLED;
458}
459
460
461
462
463
464
465
466
467
468
469static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
470 int irq_type, bool open_drain)
471{
472 struct device *dev = regmap_get_device(st->map);
473 unsigned int val;
474 int ret;
475
476
477 switch (irq_type) {
478 case IRQF_TRIGGER_RISING:
479 case IRQF_TRIGGER_HIGH:
480 val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH;
481 break;
482 default:
483 val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW;
484 break;
485 }
486
487 switch (irq_type) {
488 case IRQF_TRIGGER_LOW:
489 case IRQF_TRIGGER_HIGH:
490 val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED;
491 break;
492 default:
493 break;
494 }
495
496 if (!open_drain)
497 val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL;
498
499 ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val);
500 if (ret)
501 return ret;
502
503
504 ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1,
505 INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0);
506 if (ret)
507 return ret;
508
509 return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp,
510 inv_icm42600_irq_handler, irq_type,
511 "inv_icm42600", st);
512}
513
514static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st)
515{
516 int ret;
517
518 ret = regulator_enable(st->vddio_supply);
519 if (ret)
520 return ret;
521
522
523 usleep_range(3000, 4000);
524
525 return 0;
526}
527
528static void inv_icm42600_disable_vdd_reg(void *_data)
529{
530 struct inv_icm42600_state *st = _data;
531 const struct device *dev = regmap_get_device(st->map);
532 int ret;
533
534 ret = regulator_disable(st->vdd_supply);
535 if (ret)
536 dev_err(dev, "failed to disable vdd error %d\n", ret);
537}
538
539static void inv_icm42600_disable_vddio_reg(void *_data)
540{
541 struct inv_icm42600_state *st = _data;
542 const struct device *dev = regmap_get_device(st->map);
543 int ret;
544
545 ret = regulator_disable(st->vddio_supply);
546 if (ret)
547 dev_err(dev, "failed to disable vddio error %d\n", ret);
548}
549
550static void inv_icm42600_disable_pm(void *_data)
551{
552 struct device *dev = _data;
553
554 pm_runtime_put_sync(dev);
555 pm_runtime_disable(dev);
556}
557
558int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
559 inv_icm42600_bus_setup bus_setup)
560{
561 struct device *dev = regmap_get_device(regmap);
562 struct inv_icm42600_state *st;
563 struct irq_data *irq_desc;
564 int irq_type;
565 bool open_drain;
566 int ret;
567
568 if (chip < 0 || chip >= INV_CHIP_NB) {
569 dev_err(dev, "invalid chip = %d\n", chip);
570 return -ENODEV;
571 }
572
573
574 irq_desc = irq_get_irq_data(irq);
575 if (!irq_desc) {
576 dev_err(dev, "could not find IRQ %d\n", irq);
577 return -EINVAL;
578 }
579
580 irq_type = irqd_get_trigger_type(irq_desc);
581 if (!irq_type)
582 irq_type = IRQF_TRIGGER_FALLING;
583
584 open_drain = device_property_read_bool(dev, "drive-open-drain");
585
586 st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
587 if (!st)
588 return -ENOMEM;
589
590 dev_set_drvdata(dev, st);
591 mutex_init(&st->lock);
592 st->chip = chip;
593 st->map = regmap;
594
595 ret = iio_read_mount_matrix(dev, &st->orientation);
596 if (ret) {
597 dev_err(dev, "failed to retrieve mounting matrix %d\n", ret);
598 return ret;
599 }
600
601 st->vdd_supply = devm_regulator_get(dev, "vdd");
602 if (IS_ERR(st->vdd_supply))
603 return PTR_ERR(st->vdd_supply);
604
605 st->vddio_supply = devm_regulator_get(dev, "vddio");
606 if (IS_ERR(st->vddio_supply))
607 return PTR_ERR(st->vddio_supply);
608
609 ret = regulator_enable(st->vdd_supply);
610 if (ret)
611 return ret;
612 msleep(INV_ICM42600_POWER_UP_TIME_MS);
613
614 ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vdd_reg, st);
615 if (ret)
616 return ret;
617
618 ret = inv_icm42600_enable_regulator_vddio(st);
619 if (ret)
620 return ret;
621
622 ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vddio_reg, st);
623 if (ret)
624 return ret;
625
626
627 ret = inv_icm42600_setup(st, bus_setup);
628 if (ret)
629 return ret;
630
631 ret = inv_icm42600_timestamp_setup(st);
632 if (ret)
633 return ret;
634
635 ret = inv_icm42600_buffer_init(st);
636 if (ret)
637 return ret;
638
639 st->indio_gyro = inv_icm42600_gyro_init(st);
640 if (IS_ERR(st->indio_gyro))
641 return PTR_ERR(st->indio_gyro);
642
643 st->indio_accel = inv_icm42600_accel_init(st);
644 if (IS_ERR(st->indio_accel))
645 return PTR_ERR(st->indio_accel);
646
647 ret = inv_icm42600_irq_init(st, irq, irq_type, open_drain);
648 if (ret)
649 return ret;
650
651
652 ret = pm_runtime_set_active(dev);
653 if (ret)
654 return ret;
655 pm_runtime_get_noresume(dev);
656 pm_runtime_enable(dev);
657 pm_runtime_set_autosuspend_delay(dev, INV_ICM42600_SUSPEND_DELAY_MS);
658 pm_runtime_use_autosuspend(dev);
659 pm_runtime_put(dev);
660
661 return devm_add_action_or_reset(dev, inv_icm42600_disable_pm, dev);
662}
663EXPORT_SYMBOL_GPL(inv_icm42600_core_probe);
664
665
666
667
668
669static int __maybe_unused inv_icm42600_suspend(struct device *dev)
670{
671 struct inv_icm42600_state *st = dev_get_drvdata(dev);
672 int ret;
673
674 mutex_lock(&st->lock);
675
676 st->suspended.gyro = st->conf.gyro.mode;
677 st->suspended.accel = st->conf.accel.mode;
678 st->suspended.temp = st->conf.temp_en;
679 if (pm_runtime_suspended(dev)) {
680 ret = 0;
681 goto out_unlock;
682 }
683
684
685 if (st->fifo.on) {
686 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
687 INV_ICM42600_FIFO_CONFIG_BYPASS);
688 if (ret)
689 goto out_unlock;
690 }
691
692 ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
693 INV_ICM42600_SENSOR_MODE_OFF, false,
694 NULL);
695 if (ret)
696 goto out_unlock;
697
698 regulator_disable(st->vddio_supply);
699
700out_unlock:
701 mutex_unlock(&st->lock);
702 return ret;
703}
704
705
706
707
708
709static int __maybe_unused inv_icm42600_resume(struct device *dev)
710{
711 struct inv_icm42600_state *st = dev_get_drvdata(dev);
712 int ret;
713
714 mutex_lock(&st->lock);
715
716 ret = inv_icm42600_enable_regulator_vddio(st);
717 if (ret)
718 goto out_unlock;
719
720 pm_runtime_disable(dev);
721 pm_runtime_set_active(dev);
722 pm_runtime_enable(dev);
723
724
725 ret = inv_icm42600_set_pwr_mgmt0(st, st->suspended.gyro,
726 st->suspended.accel,
727 st->suspended.temp, NULL);
728 if (ret)
729 goto out_unlock;
730
731
732 if (st->fifo.on)
733 ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG,
734 INV_ICM42600_FIFO_CONFIG_STREAM);
735
736out_unlock:
737 mutex_unlock(&st->lock);
738 return ret;
739}
740
741
742static int __maybe_unused inv_icm42600_runtime_suspend(struct device *dev)
743{
744 struct inv_icm42600_state *st = dev_get_drvdata(dev);
745 int ret;
746
747 mutex_lock(&st->lock);
748
749
750 ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
751 INV_ICM42600_SENSOR_MODE_OFF, false,
752 NULL);
753 if (ret)
754 goto error_unlock;
755
756 regulator_disable(st->vddio_supply);
757
758error_unlock:
759 mutex_unlock(&st->lock);
760 return ret;
761}
762
763
764static int __maybe_unused inv_icm42600_runtime_resume(struct device *dev)
765{
766 struct inv_icm42600_state *st = dev_get_drvdata(dev);
767 int ret;
768
769 mutex_lock(&st->lock);
770
771 ret = inv_icm42600_enable_regulator_vddio(st);
772
773 mutex_unlock(&st->lock);
774 return ret;
775}
776
777const struct dev_pm_ops inv_icm42600_pm_ops = {
778 SET_SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume)
779 SET_RUNTIME_PM_OPS(inv_icm42600_runtime_suspend,
780 inv_icm42600_runtime_resume, NULL)
781};
782EXPORT_SYMBOL_GPL(inv_icm42600_pm_ops);
783
784MODULE_AUTHOR("InvenSense, Inc.");
785MODULE_DESCRIPTION("InvenSense ICM-426xx device driver");
786MODULE_LICENSE("GPL");
787