1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2012 Invensense, Inc. |
4 | */ |
5 | |
6 | #include <linux/module.h> |
7 | #include <linux/slab.h> |
8 | #include <linux/i2c.h> |
9 | #include <linux/err.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/sysfs.h> |
12 | #include <linux/jiffies.h> |
13 | #include <linux/irq.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/acpi.h> |
16 | #include <linux/platform_device.h> |
17 | #include <linux/regulator/consumer.h> |
18 | #include <linux/pm.h> |
19 | #include <linux/pm_runtime.h> |
20 | #include <linux/property.h> |
21 | |
22 | #include <linux/iio/common/inv_sensors_timestamp.h> |
23 | #include <linux/iio/iio.h> |
24 | |
25 | #include "inv_mpu_iio.h" |
26 | #include "inv_mpu_magn.h" |
27 | |
28 | /* |
29 | * this is the gyro scale translated from dynamic range plus/minus |
30 | * {250, 500, 1000, 2000} to rad/s |
31 | */ |
32 | static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724}; |
33 | |
34 | /* |
35 | * this is the accel scale translated from dynamic range plus/minus |
36 | * {2, 4, 8, 16} to m/s^2 |
37 | */ |
38 | static const int accel_scale[] = {598, 1196, 2392, 4785}; |
39 | |
40 | static const struct inv_mpu6050_reg_map reg_set_icm20602 = { |
41 | .sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV, |
42 | .lpf = INV_MPU6050_REG_CONFIG, |
43 | .accel_lpf = INV_MPU6500_REG_ACCEL_CONFIG_2, |
44 | .user_ctrl = INV_MPU6050_REG_USER_CTRL, |
45 | .fifo_en = INV_MPU6050_REG_FIFO_EN, |
46 | .gyro_config = INV_MPU6050_REG_GYRO_CONFIG, |
47 | .accl_config = INV_MPU6050_REG_ACCEL_CONFIG, |
48 | .fifo_count_h = INV_MPU6050_REG_FIFO_COUNT_H, |
49 | .fifo_r_w = INV_MPU6050_REG_FIFO_R_W, |
50 | .raw_gyro = INV_MPU6050_REG_RAW_GYRO, |
51 | .raw_accl = INV_MPU6050_REG_RAW_ACCEL, |
52 | .temperature = INV_MPU6050_REG_TEMPERATURE, |
53 | .int_enable = INV_MPU6050_REG_INT_ENABLE, |
54 | .int_status = INV_MPU6050_REG_INT_STATUS, |
55 | .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1, |
56 | .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2, |
57 | .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG, |
58 | .accl_offset = INV_MPU6500_REG_ACCEL_OFFSET, |
59 | .gyro_offset = INV_MPU6050_REG_GYRO_OFFSET, |
60 | .i2c_if = INV_ICM20602_REG_I2C_IF, |
61 | }; |
62 | |
63 | static const struct inv_mpu6050_reg_map reg_set_6500 = { |
64 | .sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV, |
65 | .lpf = INV_MPU6050_REG_CONFIG, |
66 | .accel_lpf = INV_MPU6500_REG_ACCEL_CONFIG_2, |
67 | .user_ctrl = INV_MPU6050_REG_USER_CTRL, |
68 | .fifo_en = INV_MPU6050_REG_FIFO_EN, |
69 | .gyro_config = INV_MPU6050_REG_GYRO_CONFIG, |
70 | .accl_config = INV_MPU6050_REG_ACCEL_CONFIG, |
71 | .fifo_count_h = INV_MPU6050_REG_FIFO_COUNT_H, |
72 | .fifo_r_w = INV_MPU6050_REG_FIFO_R_W, |
73 | .raw_gyro = INV_MPU6050_REG_RAW_GYRO, |
74 | .raw_accl = INV_MPU6050_REG_RAW_ACCEL, |
75 | .temperature = INV_MPU6050_REG_TEMPERATURE, |
76 | .int_enable = INV_MPU6050_REG_INT_ENABLE, |
77 | .int_status = INV_MPU6050_REG_INT_STATUS, |
78 | .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1, |
79 | .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2, |
80 | .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG, |
81 | .accl_offset = INV_MPU6500_REG_ACCEL_OFFSET, |
82 | .gyro_offset = INV_MPU6050_REG_GYRO_OFFSET, |
83 | .i2c_if = 0, |
84 | }; |
85 | |
86 | static const struct inv_mpu6050_reg_map reg_set_6050 = { |
87 | .sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV, |
88 | .lpf = INV_MPU6050_REG_CONFIG, |
89 | .user_ctrl = INV_MPU6050_REG_USER_CTRL, |
90 | .fifo_en = INV_MPU6050_REG_FIFO_EN, |
91 | .gyro_config = INV_MPU6050_REG_GYRO_CONFIG, |
92 | .accl_config = INV_MPU6050_REG_ACCEL_CONFIG, |
93 | .fifo_count_h = INV_MPU6050_REG_FIFO_COUNT_H, |
94 | .fifo_r_w = INV_MPU6050_REG_FIFO_R_W, |
95 | .raw_gyro = INV_MPU6050_REG_RAW_GYRO, |
96 | .raw_accl = INV_MPU6050_REG_RAW_ACCEL, |
97 | .temperature = INV_MPU6050_REG_TEMPERATURE, |
98 | .int_enable = INV_MPU6050_REG_INT_ENABLE, |
99 | .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1, |
100 | .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2, |
101 | .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG, |
102 | .accl_offset = INV_MPU6050_REG_ACCEL_OFFSET, |
103 | .gyro_offset = INV_MPU6050_REG_GYRO_OFFSET, |
104 | .i2c_if = 0, |
105 | }; |
106 | |
107 | static const struct inv_mpu6050_chip_config chip_config_6050 = { |
108 | .clk = INV_CLK_INTERNAL, |
109 | .fsr = INV_MPU6050_FSR_2000DPS, |
110 | .lpf = INV_MPU6050_FILTER_20HZ, |
111 | .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(50), |
112 | .gyro_en = true, |
113 | .accl_en = true, |
114 | .temp_en = true, |
115 | .magn_en = false, |
116 | .gyro_fifo_enable = false, |
117 | .accl_fifo_enable = false, |
118 | .temp_fifo_enable = false, |
119 | .magn_fifo_enable = false, |
120 | .accl_fs = INV_MPU6050_FS_02G, |
121 | .user_ctrl = 0, |
122 | }; |
123 | |
124 | static const struct inv_mpu6050_chip_config chip_config_6500 = { |
125 | .clk = INV_CLK_PLL, |
126 | .fsr = INV_MPU6050_FSR_2000DPS, |
127 | .lpf = INV_MPU6050_FILTER_20HZ, |
128 | .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(50), |
129 | .gyro_en = true, |
130 | .accl_en = true, |
131 | .temp_en = true, |
132 | .magn_en = false, |
133 | .gyro_fifo_enable = false, |
134 | .accl_fifo_enable = false, |
135 | .temp_fifo_enable = false, |
136 | .magn_fifo_enable = false, |
137 | .accl_fs = INV_MPU6050_FS_02G, |
138 | .user_ctrl = 0, |
139 | }; |
140 | |
141 | /* Indexed by enum inv_devices */ |
142 | static const struct inv_mpu6050_hw hw_info[] = { |
143 | { |
144 | .whoami = INV_MPU6050_WHOAMI_VALUE, |
145 | .name = "MPU6050" , |
146 | .reg = ®_set_6050, |
147 | .config = &chip_config_6050, |
148 | .fifo_size = 1024, |
149 | .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE}, |
150 | .startup_time = {INV_MPU6050_GYRO_STARTUP_TIME, INV_MPU6050_ACCEL_STARTUP_TIME}, |
151 | }, |
152 | { |
153 | .whoami = INV_MPU6500_WHOAMI_VALUE, |
154 | .name = "MPU6500" , |
155 | .reg = ®_set_6500, |
156 | .config = &chip_config_6500, |
157 | .fifo_size = 512, |
158 | .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, |
159 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
160 | }, |
161 | { |
162 | .whoami = INV_MPU6515_WHOAMI_VALUE, |
163 | .name = "MPU6515" , |
164 | .reg = ®_set_6500, |
165 | .config = &chip_config_6500, |
166 | .fifo_size = 512, |
167 | .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, |
168 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
169 | }, |
170 | { |
171 | .whoami = INV_MPU6880_WHOAMI_VALUE, |
172 | .name = "MPU6880" , |
173 | .reg = ®_set_6500, |
174 | .config = &chip_config_6500, |
175 | .fifo_size = 4096, |
176 | .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, |
177 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
178 | }, |
179 | { |
180 | .whoami = INV_MPU6000_WHOAMI_VALUE, |
181 | .name = "MPU6000" , |
182 | .reg = ®_set_6050, |
183 | .config = &chip_config_6050, |
184 | .fifo_size = 1024, |
185 | .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE}, |
186 | .startup_time = {INV_MPU6050_GYRO_STARTUP_TIME, INV_MPU6050_ACCEL_STARTUP_TIME}, |
187 | }, |
188 | { |
189 | .whoami = INV_MPU9150_WHOAMI_VALUE, |
190 | .name = "MPU9150" , |
191 | .reg = ®_set_6050, |
192 | .config = &chip_config_6050, |
193 | .fifo_size = 1024, |
194 | .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE}, |
195 | .startup_time = {INV_MPU6050_GYRO_STARTUP_TIME, INV_MPU6050_ACCEL_STARTUP_TIME}, |
196 | }, |
197 | { |
198 | .whoami = INV_MPU9250_WHOAMI_VALUE, |
199 | .name = "MPU9250" , |
200 | .reg = ®_set_6500, |
201 | .config = &chip_config_6500, |
202 | .fifo_size = 512, |
203 | .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, |
204 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
205 | }, |
206 | { |
207 | .whoami = INV_MPU9255_WHOAMI_VALUE, |
208 | .name = "MPU9255" , |
209 | .reg = ®_set_6500, |
210 | .config = &chip_config_6500, |
211 | .fifo_size = 512, |
212 | .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, |
213 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
214 | }, |
215 | { |
216 | .whoami = INV_ICM20608_WHOAMI_VALUE, |
217 | .name = "ICM20608" , |
218 | .reg = ®_set_6500, |
219 | .config = &chip_config_6500, |
220 | .fifo_size = 512, |
221 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
222 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
223 | }, |
224 | { |
225 | .whoami = INV_ICM20608D_WHOAMI_VALUE, |
226 | .name = "ICM20608D" , |
227 | .reg = ®_set_6500, |
228 | .config = &chip_config_6500, |
229 | .fifo_size = 512, |
230 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
231 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
232 | }, |
233 | { |
234 | .whoami = INV_ICM20609_WHOAMI_VALUE, |
235 | .name = "ICM20609" , |
236 | .reg = ®_set_6500, |
237 | .config = &chip_config_6500, |
238 | .fifo_size = 4 * 1024, |
239 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
240 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
241 | }, |
242 | { |
243 | .whoami = INV_ICM20689_WHOAMI_VALUE, |
244 | .name = "ICM20689" , |
245 | .reg = ®_set_6500, |
246 | .config = &chip_config_6500, |
247 | .fifo_size = 4 * 1024, |
248 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
249 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
250 | }, |
251 | { |
252 | .whoami = INV_ICM20600_WHOAMI_VALUE, |
253 | .name = "ICM20600" , |
254 | .reg = ®_set_icm20602, |
255 | .config = &chip_config_6500, |
256 | .fifo_size = 1008, |
257 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
258 | .startup_time = {INV_ICM20602_GYRO_STARTUP_TIME, INV_ICM20602_ACCEL_STARTUP_TIME}, |
259 | }, |
260 | { |
261 | .whoami = INV_ICM20602_WHOAMI_VALUE, |
262 | .name = "ICM20602" , |
263 | .reg = ®_set_icm20602, |
264 | .config = &chip_config_6500, |
265 | .fifo_size = 1008, |
266 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
267 | .startup_time = {INV_ICM20602_GYRO_STARTUP_TIME, INV_ICM20602_ACCEL_STARTUP_TIME}, |
268 | }, |
269 | { |
270 | .whoami = INV_ICM20690_WHOAMI_VALUE, |
271 | .name = "ICM20690" , |
272 | .reg = ®_set_6500, |
273 | .config = &chip_config_6500, |
274 | .fifo_size = 1024, |
275 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
276 | .startup_time = {INV_ICM20690_GYRO_STARTUP_TIME, INV_ICM20690_ACCEL_STARTUP_TIME}, |
277 | }, |
278 | { |
279 | .whoami = INV_IAM20680_WHOAMI_VALUE, |
280 | .name = "IAM20680" , |
281 | .reg = ®_set_6500, |
282 | .config = &chip_config_6500, |
283 | .fifo_size = 512, |
284 | .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, |
285 | .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME}, |
286 | }, |
287 | }; |
288 | |
289 | static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep, |
290 | int clock, int temp_dis) |
291 | { |
292 | u8 val; |
293 | |
294 | if (clock < 0) |
295 | clock = st->chip_config.clk; |
296 | if (temp_dis < 0) |
297 | temp_dis = !st->chip_config.temp_en; |
298 | |
299 | val = clock & INV_MPU6050_BIT_CLK_MASK; |
300 | if (temp_dis) |
301 | val |= INV_MPU6050_BIT_TEMP_DIS; |
302 | if (sleep) |
303 | val |= INV_MPU6050_BIT_SLEEP; |
304 | |
305 | dev_dbg(regmap_get_device(st->map), "pwr_mgmt_1: 0x%x\n" , val); |
306 | return regmap_write(map: st->map, reg: st->reg->pwr_mgmt_1, val); |
307 | } |
308 | |
309 | static int inv_mpu6050_clock_switch(struct inv_mpu6050_state *st, |
310 | unsigned int clock) |
311 | { |
312 | int ret; |
313 | |
314 | switch (st->chip_type) { |
315 | case INV_MPU6050: |
316 | case INV_MPU6000: |
317 | case INV_MPU9150: |
318 | /* old chips: switch clock manually */ |
319 | ret = inv_mpu6050_pwr_mgmt_1_write(st, sleep: false, clock, temp_dis: -1); |
320 | if (ret) |
321 | return ret; |
322 | st->chip_config.clk = clock; |
323 | break; |
324 | default: |
325 | /* automatic clock switching, nothing to do */ |
326 | break; |
327 | } |
328 | |
329 | return 0; |
330 | } |
331 | |
332 | int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, |
333 | unsigned int mask) |
334 | { |
335 | unsigned int sleep; |
336 | u8 pwr_mgmt2, user_ctrl; |
337 | int ret; |
338 | |
339 | /* delete useless requests */ |
340 | if (mask & INV_MPU6050_SENSOR_ACCL && en == st->chip_config.accl_en) |
341 | mask &= ~INV_MPU6050_SENSOR_ACCL; |
342 | if (mask & INV_MPU6050_SENSOR_GYRO && en == st->chip_config.gyro_en) |
343 | mask &= ~INV_MPU6050_SENSOR_GYRO; |
344 | if (mask & INV_MPU6050_SENSOR_TEMP && en == st->chip_config.temp_en) |
345 | mask &= ~INV_MPU6050_SENSOR_TEMP; |
346 | if (mask & INV_MPU6050_SENSOR_MAGN && en == st->chip_config.magn_en) |
347 | mask &= ~INV_MPU6050_SENSOR_MAGN; |
348 | if (mask == 0) |
349 | return 0; |
350 | |
351 | /* turn on/off temperature sensor */ |
352 | if (mask & INV_MPU6050_SENSOR_TEMP) { |
353 | ret = inv_mpu6050_pwr_mgmt_1_write(st, sleep: false, clock: -1, temp_dis: !en); |
354 | if (ret) |
355 | return ret; |
356 | st->chip_config.temp_en = en; |
357 | } |
358 | |
359 | /* update user_crtl for driving magnetometer */ |
360 | if (mask & INV_MPU6050_SENSOR_MAGN) { |
361 | user_ctrl = st->chip_config.user_ctrl; |
362 | if (en) |
363 | user_ctrl |= INV_MPU6050_BIT_I2C_MST_EN; |
364 | else |
365 | user_ctrl &= ~INV_MPU6050_BIT_I2C_MST_EN; |
366 | ret = regmap_write(map: st->map, reg: st->reg->user_ctrl, val: user_ctrl); |
367 | if (ret) |
368 | return ret; |
369 | st->chip_config.user_ctrl = user_ctrl; |
370 | st->chip_config.magn_en = en; |
371 | } |
372 | |
373 | /* manage accel & gyro engines */ |
374 | if (mask & (INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO)) { |
375 | /* compute power management 2 current value */ |
376 | pwr_mgmt2 = 0; |
377 | if (!st->chip_config.accl_en) |
378 | pwr_mgmt2 |= INV_MPU6050_BIT_PWR_ACCL_STBY; |
379 | if (!st->chip_config.gyro_en) |
380 | pwr_mgmt2 |= INV_MPU6050_BIT_PWR_GYRO_STBY; |
381 | |
382 | /* update to new requested value */ |
383 | if (mask & INV_MPU6050_SENSOR_ACCL) { |
384 | if (en) |
385 | pwr_mgmt2 &= ~INV_MPU6050_BIT_PWR_ACCL_STBY; |
386 | else |
387 | pwr_mgmt2 |= INV_MPU6050_BIT_PWR_ACCL_STBY; |
388 | } |
389 | if (mask & INV_MPU6050_SENSOR_GYRO) { |
390 | if (en) |
391 | pwr_mgmt2 &= ~INV_MPU6050_BIT_PWR_GYRO_STBY; |
392 | else |
393 | pwr_mgmt2 |= INV_MPU6050_BIT_PWR_GYRO_STBY; |
394 | } |
395 | |
396 | /* switch clock to internal when turning gyro off */ |
397 | if (mask & INV_MPU6050_SENSOR_GYRO && !en) { |
398 | ret = inv_mpu6050_clock_switch(st, clock: INV_CLK_INTERNAL); |
399 | if (ret) |
400 | return ret; |
401 | } |
402 | |
403 | /* update sensors engine */ |
404 | dev_dbg(regmap_get_device(st->map), "pwr_mgmt_2: 0x%x\n" , |
405 | pwr_mgmt2); |
406 | ret = regmap_write(map: st->map, reg: st->reg->pwr_mgmt_2, val: pwr_mgmt2); |
407 | if (ret) |
408 | return ret; |
409 | if (mask & INV_MPU6050_SENSOR_ACCL) |
410 | st->chip_config.accl_en = en; |
411 | if (mask & INV_MPU6050_SENSOR_GYRO) |
412 | st->chip_config.gyro_en = en; |
413 | |
414 | /* compute required time to have sensors stabilized */ |
415 | sleep = 0; |
416 | if (en) { |
417 | if (mask & INV_MPU6050_SENSOR_ACCL) { |
418 | if (sleep < st->hw->startup_time.accel) |
419 | sleep = st->hw->startup_time.accel; |
420 | } |
421 | if (mask & INV_MPU6050_SENSOR_GYRO) { |
422 | if (sleep < st->hw->startup_time.gyro) |
423 | sleep = st->hw->startup_time.gyro; |
424 | } |
425 | } else { |
426 | if (mask & INV_MPU6050_SENSOR_GYRO) { |
427 | if (sleep < INV_MPU6050_GYRO_DOWN_TIME) |
428 | sleep = INV_MPU6050_GYRO_DOWN_TIME; |
429 | } |
430 | } |
431 | if (sleep) |
432 | msleep(msecs: sleep); |
433 | |
434 | /* switch clock to PLL when turning gyro on */ |
435 | if (mask & INV_MPU6050_SENSOR_GYRO && en) { |
436 | ret = inv_mpu6050_clock_switch(st, clock: INV_CLK_PLL); |
437 | if (ret) |
438 | return ret; |
439 | } |
440 | } |
441 | |
442 | return 0; |
443 | } |
444 | |
445 | static int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, |
446 | bool power_on) |
447 | { |
448 | int result; |
449 | |
450 | result = inv_mpu6050_pwr_mgmt_1_write(st, sleep: !power_on, clock: -1, temp_dis: -1); |
451 | if (result) |
452 | return result; |
453 | |
454 | if (power_on) |
455 | usleep_range(INV_MPU6050_REG_UP_TIME_MIN, |
456 | INV_MPU6050_REG_UP_TIME_MAX); |
457 | |
458 | return 0; |
459 | } |
460 | |
461 | static int inv_mpu6050_set_gyro_fsr(struct inv_mpu6050_state *st, |
462 | enum inv_mpu6050_fsr_e val) |
463 | { |
464 | unsigned int gyro_shift; |
465 | u8 data; |
466 | |
467 | switch (st->chip_type) { |
468 | case INV_ICM20690: |
469 | gyro_shift = INV_ICM20690_GYRO_CONFIG_FSR_SHIFT; |
470 | break; |
471 | default: |
472 | gyro_shift = INV_MPU6050_GYRO_CONFIG_FSR_SHIFT; |
473 | break; |
474 | } |
475 | |
476 | data = val << gyro_shift; |
477 | return regmap_write(map: st->map, reg: st->reg->gyro_config, val: data); |
478 | } |
479 | |
480 | /* |
481 | * inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent |
482 | * |
483 | * MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope |
484 | * MPU6500 and above have a dedicated register for accelerometer |
485 | */ |
486 | static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st, |
487 | enum inv_mpu6050_filter_e val) |
488 | { |
489 | int result; |
490 | |
491 | result = regmap_write(map: st->map, reg: st->reg->lpf, val); |
492 | if (result) |
493 | return result; |
494 | |
495 | /* set accel lpf */ |
496 | switch (st->chip_type) { |
497 | case INV_MPU6050: |
498 | case INV_MPU6000: |
499 | case INV_MPU9150: |
500 | /* old chips, nothing to do */ |
501 | return 0; |
502 | case INV_ICM20689: |
503 | case INV_ICM20690: |
504 | /* set FIFO size to maximum value */ |
505 | val |= INV_ICM20689_BITS_FIFO_SIZE_MAX; |
506 | break; |
507 | default: |
508 | break; |
509 | } |
510 | |
511 | return regmap_write(map: st->map, reg: st->reg->accel_lpf, val); |
512 | } |
513 | |
514 | /* |
515 | * inv_mpu6050_init_config() - Initialize hardware, disable FIFO. |
516 | * |
517 | * Initial configuration: |
518 | * FSR: ± 2000DPS |
519 | * DLPF: 20Hz |
520 | * FIFO rate: 50Hz |
521 | * Clock source: Gyro PLL |
522 | */ |
523 | static int inv_mpu6050_init_config(struct iio_dev *indio_dev) |
524 | { |
525 | int result; |
526 | u8 d; |
527 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
528 | struct inv_sensors_timestamp_chip timestamp; |
529 | |
530 | result = inv_mpu6050_set_gyro_fsr(st, val: st->chip_config.fsr); |
531 | if (result) |
532 | return result; |
533 | |
534 | result = inv_mpu6050_set_lpf_regs(st, val: st->chip_config.lpf); |
535 | if (result) |
536 | return result; |
537 | |
538 | d = st->chip_config.divider; |
539 | result = regmap_write(map: st->map, reg: st->reg->sample_rate_div, val: d); |
540 | if (result) |
541 | return result; |
542 | |
543 | d = (st->chip_config.accl_fs << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); |
544 | result = regmap_write(map: st->map, reg: st->reg->accl_config, val: d); |
545 | if (result) |
546 | return result; |
547 | |
548 | result = regmap_write(map: st->map, reg: st->reg->int_pin_cfg, val: st->irq_mask); |
549 | if (result) |
550 | return result; |
551 | |
552 | /* clock jitter is +/- 2% */ |
553 | timestamp.clock_period = NSEC_PER_SEC / INV_MPU6050_INTERNAL_FREQ_HZ; |
554 | timestamp.jitter = 20; |
555 | timestamp.init_period = |
556 | NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); |
557 | inv_sensors_timestamp_init(ts: &st->timestamp, chip: ×tamp); |
558 | |
559 | /* magn chip init, noop if not present in the chip */ |
560 | result = inv_mpu_magn_probe(st); |
561 | if (result) |
562 | return result; |
563 | |
564 | return 0; |
565 | } |
566 | |
567 | static int inv_mpu6050_sensor_set(struct inv_mpu6050_state *st, int reg, |
568 | int axis, int val) |
569 | { |
570 | int ind; |
571 | __be16 d = cpu_to_be16(val); |
572 | |
573 | ind = (axis - IIO_MOD_X) * 2; |
574 | |
575 | return regmap_bulk_write(map: st->map, reg: reg + ind, val: &d, val_count: sizeof(d)); |
576 | } |
577 | |
578 | static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg, |
579 | int axis, int *val) |
580 | { |
581 | int ind, result; |
582 | __be16 d; |
583 | |
584 | ind = (axis - IIO_MOD_X) * 2; |
585 | result = regmap_bulk_read(map: st->map, reg: reg + ind, val: &d, val_count: sizeof(d)); |
586 | if (result) |
587 | return result; |
588 | *val = (short)be16_to_cpup(p: &d); |
589 | |
590 | return IIO_VAL_INT; |
591 | } |
592 | |
593 | static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, |
594 | struct iio_chan_spec const *chan, |
595 | int *val) |
596 | { |
597 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
598 | struct device *pdev = regmap_get_device(map: st->map); |
599 | unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us; |
600 | int result; |
601 | int ret; |
602 | |
603 | /* compute sample period */ |
604 | freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); |
605 | period_us = 1000000 / freq_hz; |
606 | |
607 | result = pm_runtime_resume_and_get(dev: pdev); |
608 | if (result) |
609 | return result; |
610 | |
611 | switch (chan->type) { |
612 | case IIO_ANGL_VEL: |
613 | if (!st->chip_config.gyro_en) { |
614 | result = inv_mpu6050_switch_engine(st, en: true, |
615 | INV_MPU6050_SENSOR_GYRO); |
616 | if (result) |
617 | goto error_power_off; |
618 | /* need to wait 2 periods to have first valid sample */ |
619 | min_sleep_us = 2 * period_us; |
620 | max_sleep_us = 2 * (period_us + period_us / 2); |
621 | usleep_range(min: min_sleep_us, max: max_sleep_us); |
622 | } |
623 | ret = inv_mpu6050_sensor_show(st, reg: st->reg->raw_gyro, |
624 | axis: chan->channel2, val); |
625 | break; |
626 | case IIO_ACCEL: |
627 | if (!st->chip_config.accl_en) { |
628 | result = inv_mpu6050_switch_engine(st, en: true, |
629 | INV_MPU6050_SENSOR_ACCL); |
630 | if (result) |
631 | goto error_power_off; |
632 | /* wait 1 period for first sample availability */ |
633 | min_sleep_us = period_us; |
634 | max_sleep_us = period_us + period_us / 2; |
635 | usleep_range(min: min_sleep_us, max: max_sleep_us); |
636 | } |
637 | ret = inv_mpu6050_sensor_show(st, reg: st->reg->raw_accl, |
638 | axis: chan->channel2, val); |
639 | break; |
640 | case IIO_TEMP: |
641 | /* temperature sensor work only with accel and/or gyro */ |
642 | if (!st->chip_config.accl_en && !st->chip_config.gyro_en) { |
643 | result = -EBUSY; |
644 | goto error_power_off; |
645 | } |
646 | if (!st->chip_config.temp_en) { |
647 | result = inv_mpu6050_switch_engine(st, en: true, |
648 | INV_MPU6050_SENSOR_TEMP); |
649 | if (result) |
650 | goto error_power_off; |
651 | /* wait 1 period for first sample availability */ |
652 | min_sleep_us = period_us; |
653 | max_sleep_us = period_us + period_us / 2; |
654 | usleep_range(min: min_sleep_us, max: max_sleep_us); |
655 | } |
656 | ret = inv_mpu6050_sensor_show(st, reg: st->reg->temperature, |
657 | axis: IIO_MOD_X, val); |
658 | break; |
659 | case IIO_MAGN: |
660 | if (!st->chip_config.magn_en) { |
661 | result = inv_mpu6050_switch_engine(st, en: true, |
662 | INV_MPU6050_SENSOR_MAGN); |
663 | if (result) |
664 | goto error_power_off; |
665 | /* frequency is limited for magnetometer */ |
666 | if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX) { |
667 | freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX; |
668 | period_us = 1000000 / freq_hz; |
669 | } |
670 | /* need to wait 2 periods to have first valid sample */ |
671 | min_sleep_us = 2 * period_us; |
672 | max_sleep_us = 2 * (period_us + period_us / 2); |
673 | usleep_range(min: min_sleep_us, max: max_sleep_us); |
674 | } |
675 | ret = inv_mpu_magn_read(st, axis: chan->channel2, val); |
676 | break; |
677 | default: |
678 | ret = -EINVAL; |
679 | break; |
680 | } |
681 | |
682 | pm_runtime_mark_last_busy(dev: pdev); |
683 | pm_runtime_put_autosuspend(dev: pdev); |
684 | |
685 | return ret; |
686 | |
687 | error_power_off: |
688 | pm_runtime_put_autosuspend(dev: pdev); |
689 | return result; |
690 | } |
691 | |
692 | static int |
693 | inv_mpu6050_read_raw(struct iio_dev *indio_dev, |
694 | struct iio_chan_spec const *chan, |
695 | int *val, int *val2, long mask) |
696 | { |
697 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
698 | int ret = 0; |
699 | |
700 | switch (mask) { |
701 | case IIO_CHAN_INFO_RAW: |
702 | ret = iio_device_claim_direct_mode(indio_dev); |
703 | if (ret) |
704 | return ret; |
705 | mutex_lock(&st->lock); |
706 | ret = inv_mpu6050_read_channel_data(indio_dev, chan, val); |
707 | mutex_unlock(lock: &st->lock); |
708 | iio_device_release_direct_mode(indio_dev); |
709 | return ret; |
710 | case IIO_CHAN_INFO_SCALE: |
711 | switch (chan->type) { |
712 | case IIO_ANGL_VEL: |
713 | mutex_lock(&st->lock); |
714 | *val = 0; |
715 | *val2 = gyro_scale_6050[st->chip_config.fsr]; |
716 | mutex_unlock(lock: &st->lock); |
717 | |
718 | return IIO_VAL_INT_PLUS_NANO; |
719 | case IIO_ACCEL: |
720 | mutex_lock(&st->lock); |
721 | *val = 0; |
722 | *val2 = accel_scale[st->chip_config.accl_fs]; |
723 | mutex_unlock(lock: &st->lock); |
724 | |
725 | return IIO_VAL_INT_PLUS_MICRO; |
726 | case IIO_TEMP: |
727 | *val = st->hw->temp.scale / 1000000; |
728 | *val2 = st->hw->temp.scale % 1000000; |
729 | return IIO_VAL_INT_PLUS_MICRO; |
730 | case IIO_MAGN: |
731 | return inv_mpu_magn_get_scale(st, chan, val, val2); |
732 | default: |
733 | return -EINVAL; |
734 | } |
735 | case IIO_CHAN_INFO_OFFSET: |
736 | switch (chan->type) { |
737 | case IIO_TEMP: |
738 | *val = st->hw->temp.offset; |
739 | return IIO_VAL_INT; |
740 | default: |
741 | return -EINVAL; |
742 | } |
743 | case IIO_CHAN_INFO_CALIBBIAS: |
744 | switch (chan->type) { |
745 | case IIO_ANGL_VEL: |
746 | mutex_lock(&st->lock); |
747 | ret = inv_mpu6050_sensor_show(st, reg: st->reg->gyro_offset, |
748 | axis: chan->channel2, val); |
749 | mutex_unlock(lock: &st->lock); |
750 | return ret; |
751 | case IIO_ACCEL: |
752 | mutex_lock(&st->lock); |
753 | ret = inv_mpu6050_sensor_show(st, reg: st->reg->accl_offset, |
754 | axis: chan->channel2, val); |
755 | mutex_unlock(lock: &st->lock); |
756 | return ret; |
757 | |
758 | default: |
759 | return -EINVAL; |
760 | } |
761 | default: |
762 | return -EINVAL; |
763 | } |
764 | } |
765 | |
766 | static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val, |
767 | int val2) |
768 | { |
769 | int result, i; |
770 | |
771 | if (val != 0) |
772 | return -EINVAL; |
773 | |
774 | for (i = 0; i < ARRAY_SIZE(gyro_scale_6050); ++i) { |
775 | if (gyro_scale_6050[i] == val2) { |
776 | result = inv_mpu6050_set_gyro_fsr(st, val: i); |
777 | if (result) |
778 | return result; |
779 | |
780 | st->chip_config.fsr = i; |
781 | return 0; |
782 | } |
783 | } |
784 | |
785 | return -EINVAL; |
786 | } |
787 | |
788 | static int inv_write_raw_get_fmt(struct iio_dev *indio_dev, |
789 | struct iio_chan_spec const *chan, long mask) |
790 | { |
791 | switch (mask) { |
792 | case IIO_CHAN_INFO_SCALE: |
793 | switch (chan->type) { |
794 | case IIO_ANGL_VEL: |
795 | return IIO_VAL_INT_PLUS_NANO; |
796 | default: |
797 | return IIO_VAL_INT_PLUS_MICRO; |
798 | } |
799 | default: |
800 | return IIO_VAL_INT_PLUS_MICRO; |
801 | } |
802 | |
803 | return -EINVAL; |
804 | } |
805 | |
806 | static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val, |
807 | int val2) |
808 | { |
809 | int result, i; |
810 | u8 d; |
811 | |
812 | if (val != 0) |
813 | return -EINVAL; |
814 | |
815 | for (i = 0; i < ARRAY_SIZE(accel_scale); ++i) { |
816 | if (accel_scale[i] == val2) { |
817 | d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); |
818 | result = regmap_write(map: st->map, reg: st->reg->accl_config, val: d); |
819 | if (result) |
820 | return result; |
821 | |
822 | st->chip_config.accl_fs = i; |
823 | return 0; |
824 | } |
825 | } |
826 | |
827 | return -EINVAL; |
828 | } |
829 | |
830 | static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, |
831 | struct iio_chan_spec const *chan, |
832 | int val, int val2, long mask) |
833 | { |
834 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
835 | struct device *pdev = regmap_get_device(map: st->map); |
836 | int result; |
837 | |
838 | /* |
839 | * we should only update scale when the chip is disabled, i.e. |
840 | * not running |
841 | */ |
842 | result = iio_device_claim_direct_mode(indio_dev); |
843 | if (result) |
844 | return result; |
845 | |
846 | mutex_lock(&st->lock); |
847 | result = pm_runtime_resume_and_get(dev: pdev); |
848 | if (result) |
849 | goto error_write_raw_unlock; |
850 | |
851 | switch (mask) { |
852 | case IIO_CHAN_INFO_SCALE: |
853 | switch (chan->type) { |
854 | case IIO_ANGL_VEL: |
855 | result = inv_mpu6050_write_gyro_scale(st, val, val2); |
856 | break; |
857 | case IIO_ACCEL: |
858 | result = inv_mpu6050_write_accel_scale(st, val, val2); |
859 | break; |
860 | default: |
861 | result = -EINVAL; |
862 | break; |
863 | } |
864 | break; |
865 | case IIO_CHAN_INFO_CALIBBIAS: |
866 | switch (chan->type) { |
867 | case IIO_ANGL_VEL: |
868 | result = inv_mpu6050_sensor_set(st, |
869 | reg: st->reg->gyro_offset, |
870 | axis: chan->channel2, val); |
871 | break; |
872 | case IIO_ACCEL: |
873 | result = inv_mpu6050_sensor_set(st, |
874 | reg: st->reg->accl_offset, |
875 | axis: chan->channel2, val); |
876 | break; |
877 | default: |
878 | result = -EINVAL; |
879 | break; |
880 | } |
881 | break; |
882 | default: |
883 | result = -EINVAL; |
884 | break; |
885 | } |
886 | |
887 | pm_runtime_mark_last_busy(dev: pdev); |
888 | pm_runtime_put_autosuspend(dev: pdev); |
889 | error_write_raw_unlock: |
890 | mutex_unlock(lock: &st->lock); |
891 | iio_device_release_direct_mode(indio_dev); |
892 | |
893 | return result; |
894 | } |
895 | |
896 | /* |
897 | * inv_mpu6050_set_lpf() - set low pass filer based on fifo rate. |
898 | * |
899 | * Based on the Nyquist principle, the bandwidth of the low |
900 | * pass filter must not exceed the signal sampling rate divided |
901 | * by 2, or there would be aliasing. |
902 | * This function basically search for the correct low pass |
903 | * parameters based on the fifo rate, e.g, sampling frequency. |
904 | * |
905 | * lpf is set automatically when setting sampling rate to avoid any aliases. |
906 | */ |
907 | static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate) |
908 | { |
909 | static const int hz[] = {400, 200, 90, 40, 20, 10}; |
910 | static const int d[] = { |
911 | INV_MPU6050_FILTER_200HZ, INV_MPU6050_FILTER_100HZ, |
912 | INV_MPU6050_FILTER_45HZ, INV_MPU6050_FILTER_20HZ, |
913 | INV_MPU6050_FILTER_10HZ, INV_MPU6050_FILTER_5HZ |
914 | }; |
915 | int i, result; |
916 | u8 data; |
917 | |
918 | data = INV_MPU6050_FILTER_5HZ; |
919 | for (i = 0; i < ARRAY_SIZE(hz); ++i) { |
920 | if (rate >= hz[i]) { |
921 | data = d[i]; |
922 | break; |
923 | } |
924 | } |
925 | result = inv_mpu6050_set_lpf_regs(st, val: data); |
926 | if (result) |
927 | return result; |
928 | st->chip_config.lpf = data; |
929 | |
930 | return 0; |
931 | } |
932 | |
933 | /* |
934 | * inv_mpu6050_fifo_rate_store() - Set fifo rate. |
935 | */ |
936 | static ssize_t |
937 | inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, |
938 | const char *buf, size_t count) |
939 | { |
940 | int fifo_rate; |
941 | u32 fifo_period; |
942 | bool fifo_on; |
943 | u8 d; |
944 | int result; |
945 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
946 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
947 | struct device *pdev = regmap_get_device(map: st->map); |
948 | |
949 | if (kstrtoint(s: buf, base: 10, res: &fifo_rate)) |
950 | return -EINVAL; |
951 | if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE || |
952 | fifo_rate > INV_MPU6050_MAX_FIFO_RATE) |
953 | return -EINVAL; |
954 | |
955 | /* compute the chip sample rate divider */ |
956 | d = INV_MPU6050_FIFO_RATE_TO_DIVIDER(fifo_rate); |
957 | /* compute back the fifo rate to handle truncation cases */ |
958 | fifo_rate = INV_MPU6050_DIVIDER_TO_FIFO_RATE(d); |
959 | fifo_period = NSEC_PER_SEC / fifo_rate; |
960 | |
961 | mutex_lock(&st->lock); |
962 | if (d == st->chip_config.divider) { |
963 | result = 0; |
964 | goto fifo_rate_fail_unlock; |
965 | } |
966 | |
967 | fifo_on = st->chip_config.accl_fifo_enable || |
968 | st->chip_config.gyro_fifo_enable || |
969 | st->chip_config.magn_fifo_enable; |
970 | result = inv_sensors_timestamp_update_odr(ts: &st->timestamp, period: fifo_period, fifo: fifo_on); |
971 | if (result) |
972 | goto fifo_rate_fail_unlock; |
973 | |
974 | result = pm_runtime_resume_and_get(dev: pdev); |
975 | if (result) |
976 | goto fifo_rate_fail_unlock; |
977 | |
978 | result = regmap_write(map: st->map, reg: st->reg->sample_rate_div, val: d); |
979 | if (result) |
980 | goto fifo_rate_fail_power_off; |
981 | st->chip_config.divider = d; |
982 | |
983 | result = inv_mpu6050_set_lpf(st, rate: fifo_rate); |
984 | if (result) |
985 | goto fifo_rate_fail_power_off; |
986 | |
987 | /* update rate for magn, noop if not present in chip */ |
988 | result = inv_mpu_magn_set_rate(st, fifo_rate); |
989 | if (result) |
990 | goto fifo_rate_fail_power_off; |
991 | |
992 | pm_runtime_mark_last_busy(dev: pdev); |
993 | fifo_rate_fail_power_off: |
994 | pm_runtime_put_autosuspend(dev: pdev); |
995 | fifo_rate_fail_unlock: |
996 | mutex_unlock(lock: &st->lock); |
997 | if (result) |
998 | return result; |
999 | |
1000 | return count; |
1001 | } |
1002 | |
1003 | /* |
1004 | * inv_fifo_rate_show() - Get the current sampling rate. |
1005 | */ |
1006 | static ssize_t |
1007 | inv_fifo_rate_show(struct device *dev, struct device_attribute *attr, |
1008 | char *buf) |
1009 | { |
1010 | struct inv_mpu6050_state *st = iio_priv(indio_dev: dev_to_iio_dev(dev)); |
1011 | unsigned fifo_rate; |
1012 | |
1013 | mutex_lock(&st->lock); |
1014 | fifo_rate = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); |
1015 | mutex_unlock(lock: &st->lock); |
1016 | |
1017 | return scnprintf(buf, PAGE_SIZE, fmt: "%u\n" , fifo_rate); |
1018 | } |
1019 | |
1020 | /* |
1021 | * inv_attr_show() - calling this function will show current |
1022 | * parameters. |
1023 | * |
1024 | * Deprecated in favor of IIO mounting matrix API. |
1025 | * |
1026 | * See inv_get_mount_matrix() |
1027 | */ |
1028 | static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr, |
1029 | char *buf) |
1030 | { |
1031 | struct inv_mpu6050_state *st = iio_priv(indio_dev: dev_to_iio_dev(dev)); |
1032 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
1033 | s8 *m; |
1034 | |
1035 | switch (this_attr->address) { |
1036 | /* |
1037 | * In MPU6050, the two matrix are the same because gyro and accel |
1038 | * are integrated in one chip |
1039 | */ |
1040 | case ATTR_GYRO_MATRIX: |
1041 | case ATTR_ACCL_MATRIX: |
1042 | m = st->plat_data.orientation; |
1043 | |
1044 | return scnprintf(buf, PAGE_SIZE, |
1045 | fmt: "%d, %d, %d; %d, %d, %d; %d, %d, %d\n" , |
1046 | m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]); |
1047 | default: |
1048 | return -EINVAL; |
1049 | } |
1050 | } |
1051 | |
1052 | /** |
1053 | * inv_mpu6050_validate_trigger() - validate_trigger callback for invensense |
1054 | * MPU6050 device. |
1055 | * @indio_dev: The IIO device |
1056 | * @trig: The new trigger |
1057 | * |
1058 | * Returns: 0 if the 'trig' matches the trigger registered by the MPU6050 |
1059 | * device, -EINVAL otherwise. |
1060 | */ |
1061 | static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev, |
1062 | struct iio_trigger *trig) |
1063 | { |
1064 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
1065 | |
1066 | if (st->trig != trig) |
1067 | return -EINVAL; |
1068 | |
1069 | return 0; |
1070 | } |
1071 | |
1072 | static const struct iio_mount_matrix * |
1073 | inv_get_mount_matrix(const struct iio_dev *indio_dev, |
1074 | const struct iio_chan_spec *chan) |
1075 | { |
1076 | struct inv_mpu6050_state *data = iio_priv(indio_dev); |
1077 | const struct iio_mount_matrix *matrix; |
1078 | |
1079 | if (chan->type == IIO_MAGN) |
1080 | matrix = &data->magn_orient; |
1081 | else |
1082 | matrix = &data->orientation; |
1083 | |
1084 | return matrix; |
1085 | } |
1086 | |
1087 | static const struct iio_chan_spec_ext_info inv_ext_info[] = { |
1088 | IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, inv_get_mount_matrix), |
1089 | { } |
1090 | }; |
1091 | |
1092 | #define INV_MPU6050_CHAN(_type, _channel2, _index) \ |
1093 | { \ |
1094 | .type = _type, \ |
1095 | .modified = 1, \ |
1096 | .channel2 = _channel2, \ |
1097 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
1098 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
1099 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
1100 | .scan_index = _index, \ |
1101 | .scan_type = { \ |
1102 | .sign = 's', \ |
1103 | .realbits = 16, \ |
1104 | .storagebits = 16, \ |
1105 | .shift = 0, \ |
1106 | .endianness = IIO_BE, \ |
1107 | }, \ |
1108 | .ext_info = inv_ext_info, \ |
1109 | } |
1110 | |
1111 | #define INV_MPU6050_TEMP_CHAN(_index) \ |
1112 | { \ |
1113 | .type = IIO_TEMP, \ |
1114 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ |
1115 | | BIT(IIO_CHAN_INFO_OFFSET) \ |
1116 | | BIT(IIO_CHAN_INFO_SCALE), \ |
1117 | .scan_index = _index, \ |
1118 | .scan_type = { \ |
1119 | .sign = 's', \ |
1120 | .realbits = 16, \ |
1121 | .storagebits = 16, \ |
1122 | .shift = 0, \ |
1123 | .endianness = IIO_BE, \ |
1124 | }, \ |
1125 | } |
1126 | |
1127 | static const struct iio_chan_spec inv_mpu_channels[] = { |
1128 | IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP), |
1129 | |
1130 | INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), |
1131 | |
1132 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), |
1133 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), |
1134 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), |
1135 | |
1136 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X), |
1137 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y), |
1138 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), |
1139 | }; |
1140 | |
1141 | #define INV_MPU6050_SCAN_MASK_3AXIS_ACCEL \ |
1142 | (BIT(INV_MPU6050_SCAN_ACCL_X) \ |
1143 | | BIT(INV_MPU6050_SCAN_ACCL_Y) \ |
1144 | | BIT(INV_MPU6050_SCAN_ACCL_Z)) |
1145 | |
1146 | #define INV_MPU6050_SCAN_MASK_3AXIS_GYRO \ |
1147 | (BIT(INV_MPU6050_SCAN_GYRO_X) \ |
1148 | | BIT(INV_MPU6050_SCAN_GYRO_Y) \ |
1149 | | BIT(INV_MPU6050_SCAN_GYRO_Z)) |
1150 | |
1151 | #define INV_MPU6050_SCAN_MASK_TEMP (BIT(INV_MPU6050_SCAN_TEMP)) |
1152 | |
1153 | static const unsigned long inv_mpu_scan_masks[] = { |
1154 | /* 3-axis accel */ |
1155 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, |
1156 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, |
1157 | /* 3-axis gyro */ |
1158 | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, |
1159 | INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, |
1160 | /* 6-axis accel + gyro */ |
1161 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, |
1162 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO |
1163 | | INV_MPU6050_SCAN_MASK_TEMP, |
1164 | 0, |
1165 | }; |
1166 | |
1167 | #define INV_MPU9X50_MAGN_CHAN(_chan2, _bits, _index) \ |
1168 | { \ |
1169 | .type = IIO_MAGN, \ |
1170 | .modified = 1, \ |
1171 | .channel2 = _chan2, \ |
1172 | .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) | \ |
1173 | BIT(IIO_CHAN_INFO_RAW), \ |
1174 | .scan_index = _index, \ |
1175 | .scan_type = { \ |
1176 | .sign = 's', \ |
1177 | .realbits = _bits, \ |
1178 | .storagebits = 16, \ |
1179 | .shift = 0, \ |
1180 | .endianness = IIO_BE, \ |
1181 | }, \ |
1182 | .ext_info = inv_ext_info, \ |
1183 | } |
1184 | |
1185 | static const struct iio_chan_spec inv_mpu9150_channels[] = { |
1186 | IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), |
1187 | |
1188 | INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), |
1189 | |
1190 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), |
1191 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), |
1192 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), |
1193 | |
1194 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X), |
1195 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y), |
1196 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), |
1197 | |
1198 | /* Magnetometer resolution is 13 bits */ |
1199 | INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 13, INV_MPU9X50_SCAN_MAGN_X), |
1200 | INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 13, INV_MPU9X50_SCAN_MAGN_Y), |
1201 | INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 13, INV_MPU9X50_SCAN_MAGN_Z), |
1202 | }; |
1203 | |
1204 | static const struct iio_chan_spec inv_mpu9250_channels[] = { |
1205 | IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), |
1206 | |
1207 | INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), |
1208 | |
1209 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), |
1210 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), |
1211 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), |
1212 | |
1213 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X), |
1214 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y), |
1215 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), |
1216 | |
1217 | /* Magnetometer resolution is 16 bits */ |
1218 | INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 16, INV_MPU9X50_SCAN_MAGN_X), |
1219 | INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 16, INV_MPU9X50_SCAN_MAGN_Y), |
1220 | INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 16, INV_MPU9X50_SCAN_MAGN_Z), |
1221 | }; |
1222 | |
1223 | #define INV_MPU9X50_SCAN_MASK_3AXIS_MAGN \ |
1224 | (BIT(INV_MPU9X50_SCAN_MAGN_X) \ |
1225 | | BIT(INV_MPU9X50_SCAN_MAGN_Y) \ |
1226 | | BIT(INV_MPU9X50_SCAN_MAGN_Z)) |
1227 | |
1228 | static const unsigned long inv_mpu9x50_scan_masks[] = { |
1229 | /* 3-axis accel */ |
1230 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, |
1231 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, |
1232 | /* 3-axis gyro */ |
1233 | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, |
1234 | INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, |
1235 | /* 3-axis magn */ |
1236 | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, |
1237 | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN | INV_MPU6050_SCAN_MASK_TEMP, |
1238 | /* 6-axis accel + gyro */ |
1239 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, |
1240 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO |
1241 | | INV_MPU6050_SCAN_MASK_TEMP, |
1242 | /* 6-axis accel + magn */ |
1243 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, |
1244 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN |
1245 | | INV_MPU6050_SCAN_MASK_TEMP, |
1246 | /* 6-axis gyro + magn */ |
1247 | INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, |
1248 | INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN |
1249 | | INV_MPU6050_SCAN_MASK_TEMP, |
1250 | /* 9-axis accel + gyro + magn */ |
1251 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO |
1252 | | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, |
1253 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO |
1254 | | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN |
1255 | | INV_MPU6050_SCAN_MASK_TEMP, |
1256 | 0, |
1257 | }; |
1258 | |
1259 | static const unsigned long inv_icm20602_scan_masks[] = { |
1260 | /* 3-axis accel + temp (mandatory) */ |
1261 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, |
1262 | /* 3-axis gyro + temp (mandatory) */ |
1263 | INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, |
1264 | /* 6-axis accel + gyro + temp (mandatory) */ |
1265 | INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO |
1266 | | INV_MPU6050_SCAN_MASK_TEMP, |
1267 | 0, |
1268 | }; |
1269 | |
1270 | /* |
1271 | * The user can choose any frequency between INV_MPU6050_MIN_FIFO_RATE and |
1272 | * INV_MPU6050_MAX_FIFO_RATE, but only these frequencies are matched by the |
1273 | * low-pass filter. Specifically, each of these sampling rates are about twice |
1274 | * the bandwidth of a corresponding low-pass filter, which should eliminate |
1275 | * aliasing following the Nyquist principle. By picking a frequency different |
1276 | * from these, the user risks aliasing effects. |
1277 | */ |
1278 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500" ); |
1279 | static IIO_CONST_ATTR(in_anglvel_scale_available, |
1280 | "0.000133090 0.000266181 0.000532362 0.001064724" ); |
1281 | static IIO_CONST_ATTR(in_accel_scale_available, |
1282 | "0.000598 0.001196 0.002392 0.004785" ); |
1283 | static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show, |
1284 | inv_mpu6050_fifo_rate_store); |
1285 | |
1286 | /* Deprecated: kept for userspace backward compatibility. */ |
1287 | static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL, |
1288 | ATTR_GYRO_MATRIX); |
1289 | static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL, |
1290 | ATTR_ACCL_MATRIX); |
1291 | |
1292 | static struct attribute *inv_attributes[] = { |
1293 | &iio_dev_attr_in_gyro_matrix.dev_attr.attr, /* deprecated */ |
1294 | &iio_dev_attr_in_accel_matrix.dev_attr.attr, /* deprecated */ |
1295 | &iio_dev_attr_sampling_frequency.dev_attr.attr, |
1296 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
1297 | &iio_const_attr_in_accel_scale_available.dev_attr.attr, |
1298 | &iio_const_attr_in_anglvel_scale_available.dev_attr.attr, |
1299 | NULL, |
1300 | }; |
1301 | |
1302 | static const struct attribute_group inv_attribute_group = { |
1303 | .attrs = inv_attributes |
1304 | }; |
1305 | |
1306 | static int inv_mpu6050_reg_access(struct iio_dev *indio_dev, |
1307 | unsigned int reg, |
1308 | unsigned int writeval, |
1309 | unsigned int *readval) |
1310 | { |
1311 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
1312 | int ret; |
1313 | |
1314 | mutex_lock(&st->lock); |
1315 | if (readval) |
1316 | ret = regmap_read(map: st->map, reg, val: readval); |
1317 | else |
1318 | ret = regmap_write(map: st->map, reg, val: writeval); |
1319 | mutex_unlock(lock: &st->lock); |
1320 | |
1321 | return ret; |
1322 | } |
1323 | |
1324 | static const struct iio_info mpu_info = { |
1325 | .read_raw = &inv_mpu6050_read_raw, |
1326 | .write_raw = &inv_mpu6050_write_raw, |
1327 | .write_raw_get_fmt = &inv_write_raw_get_fmt, |
1328 | .attrs = &inv_attribute_group, |
1329 | .validate_trigger = inv_mpu6050_validate_trigger, |
1330 | .debugfs_reg_access = &inv_mpu6050_reg_access, |
1331 | }; |
1332 | |
1333 | /* |
1334 | * inv_check_and_setup_chip() - check and setup chip. |
1335 | */ |
1336 | static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) |
1337 | { |
1338 | int result; |
1339 | unsigned int regval, mask; |
1340 | int i; |
1341 | |
1342 | st->hw = &hw_info[st->chip_type]; |
1343 | st->reg = hw_info[st->chip_type].reg; |
1344 | memcpy(&st->chip_config, hw_info[st->chip_type].config, |
1345 | sizeof(st->chip_config)); |
1346 | st->data = devm_kzalloc(dev: regmap_get_device(map: st->map), size: st->hw->fifo_size, GFP_KERNEL); |
1347 | if (st->data == NULL) |
1348 | return -ENOMEM; |
1349 | |
1350 | /* check chip self-identification */ |
1351 | result = regmap_read(map: st->map, INV_MPU6050_REG_WHOAMI, val: ®val); |
1352 | if (result) |
1353 | return result; |
1354 | if (regval != st->hw->whoami) { |
1355 | /* check whoami against all possible values */ |
1356 | for (i = 0; i < INV_NUM_PARTS; ++i) { |
1357 | if (regval == hw_info[i].whoami) { |
1358 | dev_warn(regmap_get_device(st->map), |
1359 | "whoami mismatch got 0x%02x (%s) expected 0x%02x (%s)\n" , |
1360 | regval, hw_info[i].name, |
1361 | st->hw->whoami, st->hw->name); |
1362 | break; |
1363 | } |
1364 | } |
1365 | if (i >= INV_NUM_PARTS) { |
1366 | dev_err(regmap_get_device(st->map), |
1367 | "invalid whoami 0x%02x expected 0x%02x (%s)\n" , |
1368 | regval, st->hw->whoami, st->hw->name); |
1369 | return -ENODEV; |
1370 | } |
1371 | } |
1372 | |
1373 | /* reset to make sure previous state are not there */ |
1374 | result = regmap_write(map: st->map, reg: st->reg->pwr_mgmt_1, |
1375 | INV_MPU6050_BIT_H_RESET); |
1376 | if (result) |
1377 | return result; |
1378 | msleep(INV_MPU6050_POWER_UP_TIME); |
1379 | switch (st->chip_type) { |
1380 | case INV_MPU6000: |
1381 | case INV_MPU6500: |
1382 | case INV_MPU6515: |
1383 | case INV_MPU6880: |
1384 | case INV_MPU9250: |
1385 | case INV_MPU9255: |
1386 | /* reset signal path (required for spi connection) */ |
1387 | regval = INV_MPU6050_BIT_TEMP_RST | INV_MPU6050_BIT_ACCEL_RST | |
1388 | INV_MPU6050_BIT_GYRO_RST; |
1389 | result = regmap_write(map: st->map, INV_MPU6050_REG_SIGNAL_PATH_RESET, |
1390 | val: regval); |
1391 | if (result) |
1392 | return result; |
1393 | msleep(INV_MPU6050_POWER_UP_TIME); |
1394 | break; |
1395 | default: |
1396 | break; |
1397 | } |
1398 | |
1399 | /* |
1400 | * Turn power on. After reset, the sleep bit could be on |
1401 | * or off depending on the OTP settings. Turning power on |
1402 | * make it in a definite state as well as making the hardware |
1403 | * state align with the software state |
1404 | */ |
1405 | result = inv_mpu6050_set_power_itg(st, power_on: true); |
1406 | if (result) |
1407 | return result; |
1408 | mask = INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO | |
1409 | INV_MPU6050_SENSOR_TEMP | INV_MPU6050_SENSOR_MAGN; |
1410 | result = inv_mpu6050_switch_engine(st, en: false, mask); |
1411 | if (result) |
1412 | goto error_power_off; |
1413 | |
1414 | return 0; |
1415 | |
1416 | error_power_off: |
1417 | inv_mpu6050_set_power_itg(st, power_on: false); |
1418 | return result; |
1419 | } |
1420 | |
1421 | static int inv_mpu_core_enable_regulator_vddio(struct inv_mpu6050_state *st) |
1422 | { |
1423 | int result; |
1424 | |
1425 | result = regulator_enable(regulator: st->vddio_supply); |
1426 | if (result) { |
1427 | dev_err(regmap_get_device(st->map), |
1428 | "Failed to enable vddio regulator: %d\n" , result); |
1429 | } else { |
1430 | /* Give the device a little bit of time to start up. */ |
1431 | usleep_range(min: 3000, max: 5000); |
1432 | } |
1433 | |
1434 | return result; |
1435 | } |
1436 | |
1437 | static int inv_mpu_core_disable_regulator_vddio(struct inv_mpu6050_state *st) |
1438 | { |
1439 | int result; |
1440 | |
1441 | result = regulator_disable(regulator: st->vddio_supply); |
1442 | if (result) |
1443 | dev_err(regmap_get_device(st->map), |
1444 | "Failed to disable vddio regulator: %d\n" , result); |
1445 | |
1446 | return result; |
1447 | } |
1448 | |
1449 | static void inv_mpu_core_disable_regulator_action(void *_data) |
1450 | { |
1451 | struct inv_mpu6050_state *st = _data; |
1452 | int result; |
1453 | |
1454 | result = regulator_disable(regulator: st->vdd_supply); |
1455 | if (result) |
1456 | dev_err(regmap_get_device(st->map), |
1457 | "Failed to disable vdd regulator: %d\n" , result); |
1458 | |
1459 | inv_mpu_core_disable_regulator_vddio(st); |
1460 | } |
1461 | |
1462 | static void inv_mpu_pm_disable(void *data) |
1463 | { |
1464 | struct device *dev = data; |
1465 | |
1466 | pm_runtime_disable(dev); |
1467 | } |
1468 | |
1469 | int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, |
1470 | int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type) |
1471 | { |
1472 | struct inv_mpu6050_state *st; |
1473 | struct iio_dev *indio_dev; |
1474 | struct inv_mpu6050_platform_data *pdata; |
1475 | struct device *dev = regmap_get_device(map: regmap); |
1476 | int result; |
1477 | struct irq_data *desc; |
1478 | int irq_type; |
1479 | |
1480 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*st)); |
1481 | if (!indio_dev) |
1482 | return -ENOMEM; |
1483 | |
1484 | BUILD_BUG_ON(ARRAY_SIZE(hw_info) != INV_NUM_PARTS); |
1485 | if (chip_type < 0 || chip_type >= INV_NUM_PARTS) { |
1486 | dev_err(dev, "Bad invensense chip_type=%d name=%s\n" , |
1487 | chip_type, name); |
1488 | return -ENODEV; |
1489 | } |
1490 | st = iio_priv(indio_dev); |
1491 | mutex_init(&st->lock); |
1492 | st->chip_type = chip_type; |
1493 | st->irq = irq; |
1494 | st->map = regmap; |
1495 | |
1496 | st->level_shifter = device_property_read_bool(dev, |
1497 | propname: "invensense,level-shifter" ); |
1498 | pdata = dev_get_platdata(dev); |
1499 | if (!pdata) { |
1500 | result = iio_read_mount_matrix(dev, matrix: &st->orientation); |
1501 | if (result) { |
1502 | dev_err(dev, "Failed to retrieve mounting matrix %d\n" , |
1503 | result); |
1504 | return result; |
1505 | } |
1506 | } else { |
1507 | st->plat_data = *pdata; |
1508 | } |
1509 | |
1510 | if (irq > 0) { |
1511 | desc = irq_get_irq_data(irq); |
1512 | if (!desc) { |
1513 | dev_err(dev, "Could not find IRQ %d\n" , irq); |
1514 | return -EINVAL; |
1515 | } |
1516 | |
1517 | irq_type = irqd_get_trigger_type(d: desc); |
1518 | if (!irq_type) |
1519 | irq_type = IRQF_TRIGGER_RISING; |
1520 | } else { |
1521 | /* Doesn't really matter, use the default */ |
1522 | irq_type = IRQF_TRIGGER_RISING; |
1523 | } |
1524 | |
1525 | if (irq_type & IRQF_TRIGGER_RISING) // rising or both-edge |
1526 | st->irq_mask = INV_MPU6050_ACTIVE_HIGH; |
1527 | else if (irq_type == IRQF_TRIGGER_FALLING) |
1528 | st->irq_mask = INV_MPU6050_ACTIVE_LOW; |
1529 | else if (irq_type == IRQF_TRIGGER_HIGH) |
1530 | st->irq_mask = INV_MPU6050_ACTIVE_HIGH | |
1531 | INV_MPU6050_LATCH_INT_EN; |
1532 | else if (irq_type == IRQF_TRIGGER_LOW) |
1533 | st->irq_mask = INV_MPU6050_ACTIVE_LOW | |
1534 | INV_MPU6050_LATCH_INT_EN; |
1535 | else { |
1536 | dev_err(dev, "Invalid interrupt type 0x%x specified\n" , |
1537 | irq_type); |
1538 | return -EINVAL; |
1539 | } |
1540 | |
1541 | st->vdd_supply = devm_regulator_get(dev, id: "vdd" ); |
1542 | if (IS_ERR(ptr: st->vdd_supply)) |
1543 | return dev_err_probe(dev, err: PTR_ERR(ptr: st->vdd_supply), |
1544 | fmt: "Failed to get vdd regulator\n" ); |
1545 | |
1546 | st->vddio_supply = devm_regulator_get(dev, id: "vddio" ); |
1547 | if (IS_ERR(ptr: st->vddio_supply)) |
1548 | return dev_err_probe(dev, err: PTR_ERR(ptr: st->vddio_supply), |
1549 | fmt: "Failed to get vddio regulator\n" ); |
1550 | |
1551 | result = regulator_enable(regulator: st->vdd_supply); |
1552 | if (result) { |
1553 | dev_err(dev, "Failed to enable vdd regulator: %d\n" , result); |
1554 | return result; |
1555 | } |
1556 | msleep(INV_MPU6050_POWER_UP_TIME); |
1557 | |
1558 | result = inv_mpu_core_enable_regulator_vddio(st); |
1559 | if (result) { |
1560 | regulator_disable(regulator: st->vdd_supply); |
1561 | return result; |
1562 | } |
1563 | |
1564 | result = devm_add_action_or_reset(dev, inv_mpu_core_disable_regulator_action, |
1565 | st); |
1566 | if (result) { |
1567 | dev_err(dev, "Failed to setup regulator cleanup action %d\n" , |
1568 | result); |
1569 | return result; |
1570 | } |
1571 | |
1572 | /* fill magnetometer orientation */ |
1573 | result = inv_mpu_magn_set_orient(st); |
1574 | if (result) |
1575 | return result; |
1576 | |
1577 | /* power is turned on inside check chip type*/ |
1578 | result = inv_check_and_setup_chip(st); |
1579 | if (result) |
1580 | return result; |
1581 | |
1582 | result = inv_mpu6050_init_config(indio_dev); |
1583 | if (result) { |
1584 | dev_err(dev, "Could not initialize device.\n" ); |
1585 | goto error_power_off; |
1586 | } |
1587 | |
1588 | dev_set_drvdata(dev, data: indio_dev); |
1589 | /* name will be NULL when enumerated via ACPI */ |
1590 | if (name) |
1591 | indio_dev->name = name; |
1592 | else |
1593 | indio_dev->name = dev_name(dev); |
1594 | |
1595 | /* requires parent device set in indio_dev */ |
1596 | if (inv_mpu_bus_setup) { |
1597 | result = inv_mpu_bus_setup(indio_dev); |
1598 | if (result) |
1599 | goto error_power_off; |
1600 | } |
1601 | |
1602 | /* chip init is done, turning on runtime power management */ |
1603 | result = pm_runtime_set_active(dev); |
1604 | if (result) |
1605 | goto error_power_off; |
1606 | pm_runtime_get_noresume(dev); |
1607 | pm_runtime_enable(dev); |
1608 | pm_runtime_set_autosuspend_delay(dev, INV_MPU6050_SUSPEND_DELAY_MS); |
1609 | pm_runtime_use_autosuspend(dev); |
1610 | pm_runtime_put(dev); |
1611 | result = devm_add_action_or_reset(dev, inv_mpu_pm_disable, dev); |
1612 | if (result) |
1613 | return result; |
1614 | |
1615 | switch (chip_type) { |
1616 | case INV_MPU9150: |
1617 | indio_dev->channels = inv_mpu9150_channels; |
1618 | indio_dev->num_channels = ARRAY_SIZE(inv_mpu9150_channels); |
1619 | indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; |
1620 | break; |
1621 | case INV_MPU9250: |
1622 | case INV_MPU9255: |
1623 | indio_dev->channels = inv_mpu9250_channels; |
1624 | indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels); |
1625 | indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; |
1626 | break; |
1627 | case INV_ICM20600: |
1628 | case INV_ICM20602: |
1629 | indio_dev->channels = inv_mpu_channels; |
1630 | indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); |
1631 | indio_dev->available_scan_masks = inv_icm20602_scan_masks; |
1632 | break; |
1633 | default: |
1634 | indio_dev->channels = inv_mpu_channels; |
1635 | indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); |
1636 | indio_dev->available_scan_masks = inv_mpu_scan_masks; |
1637 | break; |
1638 | } |
1639 | /* |
1640 | * Use magnetometer inside the chip only if there is no i2c |
1641 | * auxiliary device in use. Otherwise Going back to 6-axis only. |
1642 | */ |
1643 | if (st->magn_disabled) { |
1644 | indio_dev->channels = inv_mpu_channels; |
1645 | indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); |
1646 | indio_dev->available_scan_masks = inv_mpu_scan_masks; |
1647 | } |
1648 | |
1649 | indio_dev->info = &mpu_info; |
1650 | |
1651 | if (irq > 0) { |
1652 | /* |
1653 | * The driver currently only supports buffered capture with its |
1654 | * own trigger. So no IRQ, no trigger, no buffer |
1655 | */ |
1656 | result = devm_iio_triggered_buffer_setup(dev, indio_dev, |
1657 | iio_pollfunc_store_time, |
1658 | inv_mpu6050_read_fifo, |
1659 | NULL); |
1660 | if (result) { |
1661 | dev_err(dev, "configure buffer fail %d\n" , result); |
1662 | return result; |
1663 | } |
1664 | |
1665 | result = inv_mpu6050_probe_trigger(indio_dev, irq_type); |
1666 | if (result) { |
1667 | dev_err(dev, "trigger probe fail %d\n" , result); |
1668 | return result; |
1669 | } |
1670 | } |
1671 | |
1672 | result = devm_iio_device_register(dev, indio_dev); |
1673 | if (result) { |
1674 | dev_err(dev, "IIO register fail %d\n" , result); |
1675 | return result; |
1676 | } |
1677 | |
1678 | return 0; |
1679 | |
1680 | error_power_off: |
1681 | inv_mpu6050_set_power_itg(st, power_on: false); |
1682 | return result; |
1683 | } |
1684 | EXPORT_SYMBOL_NS_GPL(inv_mpu_core_probe, IIO_MPU6050); |
1685 | |
1686 | static int inv_mpu_resume(struct device *dev) |
1687 | { |
1688 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1689 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
1690 | int result; |
1691 | |
1692 | mutex_lock(&st->lock); |
1693 | result = inv_mpu_core_enable_regulator_vddio(st); |
1694 | if (result) |
1695 | goto out_unlock; |
1696 | |
1697 | result = inv_mpu6050_set_power_itg(st, power_on: true); |
1698 | if (result) |
1699 | goto out_unlock; |
1700 | |
1701 | pm_runtime_disable(dev); |
1702 | pm_runtime_set_active(dev); |
1703 | pm_runtime_enable(dev); |
1704 | |
1705 | result = inv_mpu6050_switch_engine(st, en: true, mask: st->suspended_sensors); |
1706 | if (result) |
1707 | goto out_unlock; |
1708 | |
1709 | if (iio_buffer_enabled(indio_dev)) |
1710 | result = inv_mpu6050_prepare_fifo(st, enable: true); |
1711 | |
1712 | out_unlock: |
1713 | mutex_unlock(lock: &st->lock); |
1714 | |
1715 | return result; |
1716 | } |
1717 | |
1718 | static int inv_mpu_suspend(struct device *dev) |
1719 | { |
1720 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
1721 | struct inv_mpu6050_state *st = iio_priv(indio_dev); |
1722 | int result; |
1723 | |
1724 | mutex_lock(&st->lock); |
1725 | |
1726 | st->suspended_sensors = 0; |
1727 | if (pm_runtime_suspended(dev)) { |
1728 | result = 0; |
1729 | goto out_unlock; |
1730 | } |
1731 | |
1732 | if (iio_buffer_enabled(indio_dev)) { |
1733 | result = inv_mpu6050_prepare_fifo(st, enable: false); |
1734 | if (result) |
1735 | goto out_unlock; |
1736 | } |
1737 | |
1738 | if (st->chip_config.accl_en) |
1739 | st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL; |
1740 | if (st->chip_config.gyro_en) |
1741 | st->suspended_sensors |= INV_MPU6050_SENSOR_GYRO; |
1742 | if (st->chip_config.temp_en) |
1743 | st->suspended_sensors |= INV_MPU6050_SENSOR_TEMP; |
1744 | if (st->chip_config.magn_en) |
1745 | st->suspended_sensors |= INV_MPU6050_SENSOR_MAGN; |
1746 | result = inv_mpu6050_switch_engine(st, en: false, mask: st->suspended_sensors); |
1747 | if (result) |
1748 | goto out_unlock; |
1749 | |
1750 | result = inv_mpu6050_set_power_itg(st, power_on: false); |
1751 | if (result) |
1752 | goto out_unlock; |
1753 | |
1754 | inv_mpu_core_disable_regulator_vddio(st); |
1755 | out_unlock: |
1756 | mutex_unlock(lock: &st->lock); |
1757 | |
1758 | return result; |
1759 | } |
1760 | |
1761 | static int inv_mpu_runtime_suspend(struct device *dev) |
1762 | { |
1763 | struct inv_mpu6050_state *st = iio_priv(indio_dev: dev_get_drvdata(dev)); |
1764 | unsigned int sensors; |
1765 | int ret; |
1766 | |
1767 | mutex_lock(&st->lock); |
1768 | |
1769 | sensors = INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO | |
1770 | INV_MPU6050_SENSOR_TEMP | INV_MPU6050_SENSOR_MAGN; |
1771 | ret = inv_mpu6050_switch_engine(st, en: false, mask: sensors); |
1772 | if (ret) |
1773 | goto out_unlock; |
1774 | |
1775 | ret = inv_mpu6050_set_power_itg(st, power_on: false); |
1776 | if (ret) |
1777 | goto out_unlock; |
1778 | |
1779 | inv_mpu_core_disable_regulator_vddio(st); |
1780 | |
1781 | out_unlock: |
1782 | mutex_unlock(lock: &st->lock); |
1783 | return ret; |
1784 | } |
1785 | |
1786 | static int inv_mpu_runtime_resume(struct device *dev) |
1787 | { |
1788 | struct inv_mpu6050_state *st = iio_priv(indio_dev: dev_get_drvdata(dev)); |
1789 | int ret; |
1790 | |
1791 | ret = inv_mpu_core_enable_regulator_vddio(st); |
1792 | if (ret) |
1793 | return ret; |
1794 | |
1795 | return inv_mpu6050_set_power_itg(st, power_on: true); |
1796 | } |
1797 | |
1798 | EXPORT_NS_GPL_DEV_PM_OPS(inv_mpu_pmops, IIO_MPU6050) = { |
1799 | SYSTEM_SLEEP_PM_OPS(inv_mpu_suspend, inv_mpu_resume) |
1800 | RUNTIME_PM_OPS(inv_mpu_runtime_suspend, inv_mpu_runtime_resume, NULL) |
1801 | }; |
1802 | |
1803 | MODULE_AUTHOR("Invensense Corporation" ); |
1804 | MODULE_DESCRIPTION("Invensense device MPU6050 driver" ); |
1805 | MODULE_LICENSE("GPL" ); |
1806 | MODULE_IMPORT_NS(IIO_INV_SENSORS_TIMESTAMP); |
1807 | |