1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2012 Invensense, Inc.
4 */
5 
6 #include <linux/pm_runtime.h>
7 #include "inv_mpu_iio.h"
8 
inv_scan_query_mpu6050(struct iio_dev * indio_dev)9 static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev)
10 {
11 	struct inv_mpu6050_state  *st = iio_priv(indio_dev);
12 	unsigned int mask;
13 
14 	st->chip_config.gyro_fifo_enable =
15 		test_bit(INV_MPU6050_SCAN_GYRO_X,
16 			 indio_dev->active_scan_mask) ||
17 		test_bit(INV_MPU6050_SCAN_GYRO_Y,
18 			 indio_dev->active_scan_mask) ||
19 		test_bit(INV_MPU6050_SCAN_GYRO_Z,
20 			 indio_dev->active_scan_mask);
21 
22 	st->chip_config.accl_fifo_enable =
23 		test_bit(INV_MPU6050_SCAN_ACCL_X,
24 			 indio_dev->active_scan_mask) ||
25 		test_bit(INV_MPU6050_SCAN_ACCL_Y,
26 			 indio_dev->active_scan_mask) ||
27 		test_bit(INV_MPU6050_SCAN_ACCL_Z,
28 			 indio_dev->active_scan_mask);
29 
30 	st->chip_config.temp_fifo_enable =
31 		test_bit(INV_MPU6050_SCAN_TEMP, indio_dev->active_scan_mask);
32 
33 	mask = 0;
34 	if (st->chip_config.gyro_fifo_enable)
35 		mask |= INV_MPU6050_SENSOR_GYRO;
36 	if (st->chip_config.accl_fifo_enable)
37 		mask |= INV_MPU6050_SENSOR_ACCL;
38 	if (st->chip_config.temp_fifo_enable)
39 		mask |= INV_MPU6050_SENSOR_TEMP;
40 
41 	return mask;
42 }
43 
inv_scan_query_mpu9x50(struct iio_dev * indio_dev)44 static unsigned int inv_scan_query_mpu9x50(struct iio_dev *indio_dev)
45 {
46 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
47 	unsigned int mask;
48 
49 	mask = inv_scan_query_mpu6050(indio_dev);
50 
51 	/* no magnetometer if i2c auxiliary bus is used */
52 	if (st->magn_disabled)
53 		return mask;
54 
55 	st->chip_config.magn_fifo_enable =
56 		test_bit(INV_MPU9X50_SCAN_MAGN_X,
57 			 indio_dev->active_scan_mask) ||
58 		test_bit(INV_MPU9X50_SCAN_MAGN_Y,
59 			 indio_dev->active_scan_mask) ||
60 		test_bit(INV_MPU9X50_SCAN_MAGN_Z,
61 			 indio_dev->active_scan_mask);
62 	if (st->chip_config.magn_fifo_enable)
63 		mask |= INV_MPU6050_SENSOR_MAGN;
64 
65 	return mask;
66 }
67 
inv_scan_query(struct iio_dev * indio_dev)68 static unsigned int inv_scan_query(struct iio_dev *indio_dev)
69 {
70 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
71 
72 	switch (st->chip_type) {
73 	case INV_MPU9150:
74 	case INV_MPU9250:
75 	case INV_MPU9255:
76 		return inv_scan_query_mpu9x50(indio_dev);
77 	default:
78 		return inv_scan_query_mpu6050(indio_dev);
79 	}
80 }
81 
inv_compute_skip_samples(const struct inv_mpu6050_state * st)82 static unsigned int inv_compute_skip_samples(const struct inv_mpu6050_state *st)
83 {
84 	unsigned int gyro_skip = 0;
85 	unsigned int magn_skip = 0;
86 	unsigned int skip_samples;
87 
88 	/* gyro first sample is out of specs, skip it */
89 	if (st->chip_config.gyro_fifo_enable)
90 		gyro_skip = 1;
91 
92 	/* mag first sample is always not ready, skip it */
93 	if (st->chip_config.magn_fifo_enable)
94 		magn_skip = 1;
95 
96 	/* compute first samples to skip */
97 	skip_samples = gyro_skip;
98 	if (magn_skip > skip_samples)
99 		skip_samples = magn_skip;
100 
101 	return skip_samples;
102 }
103 
inv_mpu6050_prepare_fifo(struct inv_mpu6050_state * st,bool enable)104 int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable)
105 {
106 	uint8_t d;
107 	int ret;
108 
109 	if (enable) {
110 		st->it_timestamp = 0;
111 		/* reset FIFO */
112 		d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST;
113 		ret = regmap_write(st->map, st->reg->user_ctrl, d);
114 		if (ret)
115 			return ret;
116 		/* enable sensor output to FIFO */
117 		d = 0;
118 		if (st->chip_config.gyro_fifo_enable)
119 			d |= INV_MPU6050_BITS_GYRO_OUT;
120 		if (st->chip_config.accl_fifo_enable)
121 			d |= INV_MPU6050_BIT_ACCEL_OUT;
122 		if (st->chip_config.temp_fifo_enable)
123 			d |= INV_MPU6050_BIT_TEMP_OUT;
124 		if (st->chip_config.magn_fifo_enable)
125 			d |= INV_MPU6050_BIT_SLAVE_0;
126 		ret = regmap_write(st->map, st->reg->fifo_en, d);
127 		if (ret)
128 			return ret;
129 		/* enable FIFO reading */
130 		d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_EN;
131 		ret = regmap_write(st->map, st->reg->user_ctrl, d);
132 		if (ret)
133 			return ret;
134 		/* enable interrupt */
135 		ret = regmap_write(st->map, st->reg->int_enable,
136 				   INV_MPU6050_BIT_DATA_RDY_EN);
137 	} else {
138 		ret = regmap_write(st->map, st->reg->int_enable, 0);
139 		if (ret)
140 			return ret;
141 		ret = regmap_write(st->map, st->reg->fifo_en, 0);
142 		if (ret)
143 			return ret;
144 		/* restore user_ctrl for disabling FIFO reading */
145 		ret = regmap_write(st->map, st->reg->user_ctrl,
146 				   st->chip_config.user_ctrl);
147 	}
148 
149 	return ret;
150 }
151 
152 /**
153  *  inv_mpu6050_set_enable() - enable chip functions.
154  *  @indio_dev:	Device driver instance.
155  *  @enable: enable/disable
156  */
inv_mpu6050_set_enable(struct iio_dev * indio_dev,bool enable)157 static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
158 {
159 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
160 	struct device *pdev = regmap_get_device(st->map);
161 	unsigned int scan;
162 	int result;
163 
164 	if (enable) {
165 		scan = inv_scan_query(indio_dev);
166 		result = pm_runtime_get_sync(pdev);
167 		if (result < 0) {
168 			pm_runtime_put_noidle(pdev);
169 			return result;
170 		}
171 		/*
172 		 * In case autosuspend didn't trigger, turn off first not
173 		 * required sensors.
174 		 */
175 		result = inv_mpu6050_switch_engine(st, false, ~scan);
176 		if (result)
177 			goto error_power_off;
178 		result = inv_mpu6050_switch_engine(st, true, scan);
179 		if (result)
180 			goto error_power_off;
181 		st->skip_samples = inv_compute_skip_samples(st);
182 		result = inv_mpu6050_prepare_fifo(st, true);
183 		if (result)
184 			goto error_power_off;
185 	} else {
186 		result = inv_mpu6050_prepare_fifo(st, false);
187 		if (result)
188 			goto error_power_off;
189 		pm_runtime_mark_last_busy(pdev);
190 		pm_runtime_put_autosuspend(pdev);
191 	}
192 
193 	return 0;
194 
195 error_power_off:
196 	pm_runtime_put_autosuspend(pdev);
197 	return result;
198 }
199 
200 /**
201  * inv_mpu_data_rdy_trigger_set_state() - set data ready interrupt state
202  * @trig: Trigger instance
203  * @state: Desired trigger state
204  */
inv_mpu_data_rdy_trigger_set_state(struct iio_trigger * trig,bool state)205 static int inv_mpu_data_rdy_trigger_set_state(struct iio_trigger *trig,
206 					      bool state)
207 {
208 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
209 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
210 	int result;
211 
212 	mutex_lock(&st->lock);
213 	result = inv_mpu6050_set_enable(indio_dev, state);
214 	mutex_unlock(&st->lock);
215 
216 	return result;
217 }
218 
219 static const struct iio_trigger_ops inv_mpu_trigger_ops = {
220 	.set_trigger_state = &inv_mpu_data_rdy_trigger_set_state,
221 };
222 
inv_mpu6050_probe_trigger(struct iio_dev * indio_dev,int irq_type)223 int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type)
224 {
225 	int ret;
226 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
227 
228 	st->trig = devm_iio_trigger_alloc(&indio_dev->dev,
229 					  "%s-dev%d",
230 					  indio_dev->name,
231 					  indio_dev->id);
232 	if (!st->trig)
233 		return -ENOMEM;
234 
235 	ret = devm_request_irq(&indio_dev->dev, st->irq,
236 			       &iio_trigger_generic_data_rdy_poll,
237 			       irq_type,
238 			       "inv_mpu",
239 			       st->trig);
240 	if (ret)
241 		return ret;
242 
243 	st->trig->dev.parent = regmap_get_device(st->map);
244 	st->trig->ops = &inv_mpu_trigger_ops;
245 	iio_trigger_set_drvdata(st->trig, indio_dev);
246 
247 	ret = devm_iio_trigger_register(&indio_dev->dev, st->trig);
248 	if (ret)
249 		return ret;
250 
251 	indio_dev->trig = iio_trigger_get(st->trig);
252 
253 	return 0;
254 }
255