hc
2023-02-13 e440ec23c5a540cdd3f7464e8779219be6fd3d95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021 Rockchip Electronics Co., Ltd */
#include "icm40605.h"
#include <linux/math64.h>
/**
 *  icm40605_set_enable() - enable chip functions.
 *  @indio_dev:    Device driver instance.
 *  @enable: enable/disable
 */
int icm40605_set_enable(struct iio_dev *indio_dev, bool enable)
{
   int ret;
   struct icm40605_data *data = iio_priv(indio_dev);
 
   ret = regmap_write(data->regmap, MPUREG_REG_BANK_SEL, ICM40605_BANK0);
   if (ret) {
       dev_err(regmap_get_device(data->regmap),
           "sel_bank0 fail: %d\n",
           ret);
       goto error_off;
   }
   if (enable) {
       ret = icm40605_set_mode(data, ICM40605_ACCEL, true);
       if (ret)
           goto error_off;
 
       ret = icm40605_set_mode(data, ICM40605_GYRO, true);
       if (ret)
           goto error_accl_off;
 
       ret = icm40605_reset_fifo(indio_dev);
       if (ret)
           goto error_gyro_off;
 
       data->standard_period = data->period_divider > 0 ?
           div_s64(NSEC_PER_MSEC, data->period_divider) :
           NSEC_PER_MSEC * data->period_divider * (-1);
       data->interrupt_period = data->standard_period;
       data->period_min = div_s64((data->standard_period * (100 -
                       INV_MPU6050_TS_PERIOD_JITTER)),
                       100);
       data->period_max = div_s64((data->standard_period * (100 +
                       INV_MPU6050_TS_PERIOD_JITTER)),
                       100);
   } else {
       ret = regmap_write(data->regmap, MPUREG_FIFO_CONFIG_REG, BIT_FIFO_MODE_CTRL_BYPASS);
       if (ret) {
           dev_err(regmap_get_device(data->regmap), "set MPUREG_FIFO_CONFIG_REG fail: %d\n",
               ret);
           goto error_gyro_off;
       }
       ret = icm40605_set_mode(data, ICM40605_GYRO, false);
       if (ret)
           goto error_gyro_off;
 
       ret = icm40605_set_mode(data, ICM40605_ACCEL, false);
       if (ret)
           goto error_accl_off;
   }
   dev_info(regmap_get_device(data->regmap), "set fifo mode end\n");
   return ret;
 
error_gyro_off:
   icm40605_set_mode(data, ICM40605_GYRO, false);
error_accl_off:
   icm40605_set_mode(data, ICM40605_ACCEL, false);
error_off:
   return ret;
}
 
/**
 * inv_mpu_data_rdy_trigger_set_state() - set data ready interrupt state
 * @trig: Trigger instance
 * @state: Desired trigger state
 */
static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
                         bool state)
{
   struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
   struct icm40605_data *data = iio_priv(indio_dev);
   int result;
 
   mutex_lock(&data->lock);
   dev_info(regmap_get_device(data->regmap), "in data_rdy_trigger_set_state, %d\n", state);
   result = icm40605_set_enable(indio_dev, state);
   mutex_unlock(&data->lock);
 
   return result;
}
 
static const struct iio_trigger_ops inv_mpu_trigger_ops = {
   .set_trigger_state = &inv_mpu_data_rdy_trigger_set_state,
};
 
int icm40605_probe_trigger(struct iio_dev *indio_dev, int irq_type)
{
   int ret;
   struct icm40605_data *data = iio_priv(indio_dev);
 
   data->trig = devm_iio_trigger_alloc(&indio_dev->dev,
                       "%s-dev%d",
                       indio_dev->name,
                       indio_dev->id);
   if (!data->trig)
       return -ENOMEM;
 
   ret = devm_request_irq(&indio_dev->dev, data->irq,
                  &iio_trigger_generic_data_rdy_poll,
                  irq_type,
                  "inv_mpu",
                  data->trig);
   if (ret)
       return ret;
 
   data->trig->dev.parent = regmap_get_device(data->regmap);
   data->trig->ops = &inv_mpu_trigger_ops;
   iio_trigger_set_drvdata(data->trig, indio_dev);
 
   ret = devm_iio_trigger_register(&indio_dev->dev, data->trig);
   if (ret)
       return ret;
 
   indio_dev->trig = iio_trigger_get(data->trig);
 
   return 0;
}