Commit | Line | Data |
---|---|---|
09a642b7 GG |
1 | /* |
2 | * Copyright (C) 2012 Invensense, Inc. | |
3 | * | |
4 | * This software is licensed under the terms of the GNU General Public | |
5 | * License version 2, as published by the Free Software Foundation, and | |
6 | * may be copied, distributed, and modified under those terms. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | */ | |
13 | ||
14 | #include <linux/module.h> | |
15 | #include <linux/init.h> | |
16 | #include <linux/slab.h> | |
17 | #include <linux/i2c.h> | |
18 | #include <linux/err.h> | |
19 | #include <linux/delay.h> | |
20 | #include <linux/sysfs.h> | |
21 | #include <linux/jiffies.h> | |
22 | #include <linux/irq.h> | |
23 | #include <linux/interrupt.h> | |
24 | #include <linux/kfifo.h> | |
25 | #include <linux/spinlock.h> | |
452204ae | 26 | #include <linux/iio/iio.h> |
09a642b7 GG |
27 | #include "inv_mpu_iio.h" |
28 | ||
29 | /* | |
30 | * this is the gyro scale translated from dynamic range plus/minus | |
31 | * {250, 500, 1000, 2000} to rad/s | |
32 | */ | |
33 | static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724}; | |
34 | ||
35 | /* | |
36 | * this is the accel scale translated from dynamic range plus/minus | |
37 | * {2, 4, 8, 16} to m/s^2 | |
38 | */ | |
39 | static const int accel_scale[] = {598, 1196, 2392, 4785}; | |
40 | ||
41 | static const struct inv_mpu6050_reg_map reg_set_6050 = { | |
42 | .sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV, | |
43 | .lpf = INV_MPU6050_REG_CONFIG, | |
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 | .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1, | |
55 | .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2, | |
56 | }; | |
57 | ||
58 | static const struct inv_mpu6050_chip_config chip_config_6050 = { | |
59 | .fsr = INV_MPU6050_FSR_2000DPS, | |
60 | .lpf = INV_MPU6050_FILTER_20HZ, | |
61 | .fifo_rate = INV_MPU6050_INIT_FIFO_RATE, | |
62 | .gyro_fifo_enable = false, | |
63 | .accl_fifo_enable = false, | |
64 | .accl_fs = INV_MPU6050_FS_02G, | |
65 | }; | |
66 | ||
67 | static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = { | |
68 | { | |
69 | .num_reg = 117, | |
70 | .name = "MPU6050", | |
71 | .reg = ®_set_6050, | |
72 | .config = &chip_config_6050, | |
73 | }, | |
74 | }; | |
75 | ||
76 | int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d) | |
77 | { | |
78 | return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d); | |
79 | } | |
80 | ||
81 | int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) | |
82 | { | |
83 | u8 d, mgmt_1; | |
84 | int result; | |
85 | ||
86 | /* switch clock needs to be careful. Only when gyro is on, can | |
87 | clock source be switched to gyro. Otherwise, it must be set to | |
88 | internal clock */ | |
89 | if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) { | |
90 | result = i2c_smbus_read_i2c_block_data(st->client, | |
91 | st->reg->pwr_mgmt_1, 1, &mgmt_1); | |
92 | if (result != 1) | |
93 | return result; | |
94 | ||
95 | mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK; | |
96 | } | |
97 | ||
98 | if ((INV_MPU6050_BIT_PWR_GYRO_STBY == mask) && (!en)) { | |
99 | /* turning off gyro requires switch to internal clock first. | |
100 | Then turn off gyro engine */ | |
101 | mgmt_1 |= INV_CLK_INTERNAL; | |
102 | result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1); | |
103 | if (result) | |
104 | return result; | |
105 | } | |
106 | ||
107 | result = i2c_smbus_read_i2c_block_data(st->client, | |
108 | st->reg->pwr_mgmt_2, 1, &d); | |
109 | if (result != 1) | |
110 | return result; | |
111 | if (en) | |
112 | d &= ~mask; | |
113 | else | |
114 | d |= mask; | |
115 | result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d); | |
116 | if (result) | |
117 | return result; | |
118 | ||
119 | if (en) { | |
120 | /* Wait for output stablize */ | |
121 | msleep(INV_MPU6050_TEMP_UP_TIME); | |
122 | if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) { | |
123 | /* switch internal clock to PLL */ | |
124 | mgmt_1 |= INV_CLK_PLL; | |
125 | result = inv_mpu6050_write_reg(st, | |
126 | st->reg->pwr_mgmt_1, mgmt_1); | |
127 | if (result) | |
128 | return result; | |
129 | } | |
130 | } | |
131 | ||
132 | return 0; | |
133 | } | |
134 | ||
135 | int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) | |
136 | { | |
137 | int result; | |
138 | ||
139 | if (power_on) | |
140 | result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0); | |
141 | else | |
142 | result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, | |
143 | INV_MPU6050_BIT_SLEEP); | |
144 | if (result) | |
145 | return result; | |
146 | ||
147 | if (power_on) | |
148 | msleep(INV_MPU6050_REG_UP_TIME); | |
149 | ||
150 | return 0; | |
151 | } | |
152 | ||
153 | /** | |
154 | * inv_mpu6050_init_config() - Initialize hardware, disable FIFO. | |
155 | * | |
156 | * Initial configuration: | |
157 | * FSR: ± 2000DPS | |
158 | * DLPF: 20Hz | |
159 | * FIFO rate: 50Hz | |
160 | * Clock source: Gyro PLL | |
161 | */ | |
162 | static int inv_mpu6050_init_config(struct iio_dev *indio_dev) | |
163 | { | |
164 | int result; | |
165 | u8 d; | |
166 | struct inv_mpu6050_state *st = iio_priv(indio_dev); | |
167 | ||
168 | result = inv_mpu6050_set_power_itg(st, true); | |
169 | if (result) | |
170 | return result; | |
171 | d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT); | |
172 | result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d); | |
173 | if (result) | |
174 | return result; | |
175 | ||
176 | d = INV_MPU6050_FILTER_20HZ; | |
177 | result = inv_mpu6050_write_reg(st, st->reg->lpf, d); | |
178 | if (result) | |
179 | return result; | |
180 | ||
181 | d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1; | |
182 | result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d); | |
183 | if (result) | |
184 | return result; | |
185 | ||
186 | d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); | |
187 | result = inv_mpu6050_write_reg(st, st->reg->accl_config, d); | |
188 | if (result) | |
189 | return result; | |
190 | ||
191 | memcpy(&st->chip_config, hw_info[st->chip_type].config, | |
192 | sizeof(struct inv_mpu6050_chip_config)); | |
193 | result = inv_mpu6050_set_power_itg(st, false); | |
194 | ||
195 | return result; | |
196 | } | |
197 | ||
198 | static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg, | |
199 | int axis, int *val) | |
200 | { | |
201 | int ind, result; | |
202 | __be16 d; | |
203 | ||
204 | ind = (axis - IIO_MOD_X) * 2; | |
205 | result = i2c_smbus_read_i2c_block_data(st->client, reg + ind, 2, | |
206 | (u8 *)&d); | |
207 | if (result != 2) | |
208 | return -EINVAL; | |
209 | *val = (short)be16_to_cpup(&d); | |
210 | ||
211 | return IIO_VAL_INT; | |
212 | } | |
213 | ||
214 | static int inv_mpu6050_read_raw(struct iio_dev *indio_dev, | |
215 | struct iio_chan_spec const *chan, | |
216 | int *val, | |
217 | int *val2, | |
218 | long mask) { | |
219 | struct inv_mpu6050_state *st = iio_priv(indio_dev); | |
220 | ||
221 | switch (mask) { | |
222 | case IIO_CHAN_INFO_RAW: | |
223 | { | |
224 | int ret, result; | |
225 | ||
226 | ret = IIO_VAL_INT; | |
227 | result = 0; | |
228 | mutex_lock(&indio_dev->mlock); | |
229 | if (!st->chip_config.enable) { | |
230 | result = inv_mpu6050_set_power_itg(st, true); | |
231 | if (result) | |
232 | goto error_read_raw; | |
233 | } | |
234 | /* when enable is on, power is already on */ | |
235 | switch (chan->type) { | |
236 | case IIO_ANGL_VEL: | |
237 | if (!st->chip_config.gyro_fifo_enable || | |
238 | !st->chip_config.enable) { | |
239 | result = inv_mpu6050_switch_engine(st, true, | |
240 | INV_MPU6050_BIT_PWR_GYRO_STBY); | |
241 | if (result) | |
242 | goto error_read_raw; | |
243 | } | |
244 | ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro, | |
245 | chan->channel2, val); | |
246 | if (!st->chip_config.gyro_fifo_enable || | |
247 | !st->chip_config.enable) { | |
248 | result = inv_mpu6050_switch_engine(st, false, | |
249 | INV_MPU6050_BIT_PWR_GYRO_STBY); | |
250 | if (result) | |
251 | goto error_read_raw; | |
252 | } | |
253 | break; | |
254 | case IIO_ACCEL: | |
255 | if (!st->chip_config.accl_fifo_enable || | |
256 | !st->chip_config.enable) { | |
257 | result = inv_mpu6050_switch_engine(st, true, | |
258 | INV_MPU6050_BIT_PWR_ACCL_STBY); | |
259 | if (result) | |
260 | goto error_read_raw; | |
261 | } | |
262 | ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl, | |
263 | chan->channel2, val); | |
264 | if (!st->chip_config.accl_fifo_enable || | |
265 | !st->chip_config.enable) { | |
266 | result = inv_mpu6050_switch_engine(st, false, | |
267 | INV_MPU6050_BIT_PWR_ACCL_STBY); | |
268 | if (result) | |
269 | goto error_read_raw; | |
270 | } | |
271 | break; | |
272 | case IIO_TEMP: | |
273 | /* wait for stablization */ | |
274 | msleep(INV_MPU6050_SENSOR_UP_TIME); | |
275 | inv_mpu6050_sensor_show(st, st->reg->temperature, | |
276 | IIO_MOD_X, val); | |
277 | break; | |
278 | default: | |
279 | ret = -EINVAL; | |
280 | break; | |
281 | } | |
282 | error_read_raw: | |
283 | if (!st->chip_config.enable) | |
284 | result |= inv_mpu6050_set_power_itg(st, false); | |
285 | mutex_unlock(&indio_dev->mlock); | |
286 | if (result) | |
287 | return result; | |
288 | ||
289 | return ret; | |
290 | } | |
291 | case IIO_CHAN_INFO_SCALE: | |
292 | switch (chan->type) { | |
293 | case IIO_ANGL_VEL: | |
294 | *val = 0; | |
295 | *val2 = gyro_scale_6050[st->chip_config.fsr]; | |
296 | ||
297 | return IIO_VAL_INT_PLUS_NANO; | |
298 | case IIO_ACCEL: | |
299 | *val = 0; | |
300 | *val2 = accel_scale[st->chip_config.accl_fs]; | |
301 | ||
302 | return IIO_VAL_INT_PLUS_MICRO; | |
303 | case IIO_TEMP: | |
304 | *val = 0; | |
305 | *val2 = INV_MPU6050_TEMP_SCALE; | |
306 | ||
307 | return IIO_VAL_INT_PLUS_MICRO; | |
308 | default: | |
309 | return -EINVAL; | |
310 | } | |
311 | case IIO_CHAN_INFO_OFFSET: | |
312 | switch (chan->type) { | |
313 | case IIO_TEMP: | |
314 | *val = INV_MPU6050_TEMP_OFFSET; | |
315 | ||
316 | return IIO_VAL_INT; | |
317 | default: | |
318 | return -EINVAL; | |
319 | } | |
320 | default: | |
321 | return -EINVAL; | |
322 | } | |
323 | } | |
324 | ||
325 | static int inv_mpu6050_write_fsr(struct inv_mpu6050_state *st, int fsr) | |
326 | { | |
327 | int result; | |
328 | u8 d; | |
329 | ||
330 | if (fsr < 0 || fsr > INV_MPU6050_MAX_GYRO_FS_PARAM) | |
331 | return -EINVAL; | |
332 | if (fsr == st->chip_config.fsr) | |
333 | return 0; | |
334 | ||
335 | d = (fsr << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT); | |
336 | result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d); | |
337 | if (result) | |
338 | return result; | |
339 | st->chip_config.fsr = fsr; | |
340 | ||
341 | return 0; | |
342 | } | |
343 | ||
344 | static int inv_mpu6050_write_accel_fs(struct inv_mpu6050_state *st, int fs) | |
345 | { | |
346 | int result; | |
347 | u8 d; | |
348 | ||
349 | if (fs < 0 || fs > INV_MPU6050_MAX_ACCL_FS_PARAM) | |
350 | return -EINVAL; | |
351 | if (fs == st->chip_config.accl_fs) | |
352 | return 0; | |
353 | ||
354 | d = (fs << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); | |
355 | result = inv_mpu6050_write_reg(st, st->reg->accl_config, d); | |
356 | if (result) | |
357 | return result; | |
358 | st->chip_config.accl_fs = fs; | |
359 | ||
360 | return 0; | |
361 | } | |
362 | ||
363 | static int inv_mpu6050_write_raw(struct iio_dev *indio_dev, | |
364 | struct iio_chan_spec const *chan, | |
365 | int val, | |
366 | int val2, | |
367 | long mask) { | |
368 | struct inv_mpu6050_state *st = iio_priv(indio_dev); | |
369 | int result; | |
370 | ||
371 | mutex_lock(&indio_dev->mlock); | |
372 | /* we should only update scale when the chip is disabled, i.e., | |
373 | not running */ | |
374 | if (st->chip_config.enable) { | |
375 | result = -EBUSY; | |
376 | goto error_write_raw; | |
377 | } | |
378 | result = inv_mpu6050_set_power_itg(st, true); | |
379 | if (result) | |
380 | goto error_write_raw; | |
381 | ||
382 | switch (mask) { | |
383 | case IIO_CHAN_INFO_SCALE: | |
384 | switch (chan->type) { | |
385 | case IIO_ANGL_VEL: | |
386 | result = inv_mpu6050_write_fsr(st, val); | |
387 | break; | |
388 | case IIO_ACCEL: | |
389 | result = inv_mpu6050_write_accel_fs(st, val); | |
390 | break; | |
391 | default: | |
392 | result = -EINVAL; | |
393 | break; | |
394 | } | |
395 | break; | |
396 | default: | |
397 | result = -EINVAL; | |
398 | break; | |
399 | } | |
400 | ||
401 | error_write_raw: | |
402 | result |= inv_mpu6050_set_power_itg(st, false); | |
403 | mutex_unlock(&indio_dev->mlock); | |
404 | ||
405 | return result; | |
406 | } | |
407 | ||
408 | /** | |
409 | * inv_mpu6050_set_lpf() - set low pass filer based on fifo rate. | |
410 | * | |
411 | * Based on the Nyquist principle, the sampling rate must | |
412 | * exceed twice of the bandwidth of the signal, or there | |
413 | * would be alising. This function basically search for the | |
414 | * correct low pass parameters based on the fifo rate, e.g, | |
415 | * sampling frequency. | |
416 | */ | |
417 | static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate) | |
418 | { | |
419 | const int hz[] = {188, 98, 42, 20, 10, 5}; | |
420 | const int d[] = {INV_MPU6050_FILTER_188HZ, INV_MPU6050_FILTER_98HZ, | |
421 | INV_MPU6050_FILTER_42HZ, INV_MPU6050_FILTER_20HZ, | |
422 | INV_MPU6050_FILTER_10HZ, INV_MPU6050_FILTER_5HZ}; | |
423 | int i, h, result; | |
424 | u8 data; | |
425 | ||
426 | h = (rate >> 1); | |
427 | i = 0; | |
428 | while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1)) | |
429 | i++; | |
430 | data = d[i]; | |
431 | result = inv_mpu6050_write_reg(st, st->reg->lpf, data); | |
432 | if (result) | |
433 | return result; | |
434 | st->chip_config.lpf = data; | |
435 | ||
436 | return 0; | |
437 | } | |
438 | ||
439 | /** | |
440 | * inv_mpu6050_fifo_rate_store() - Set fifo rate. | |
441 | */ | |
442 | static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev, | |
443 | struct device_attribute *attr, const char *buf, size_t count) | |
444 | { | |
445 | s32 fifo_rate; | |
446 | u8 d; | |
447 | int result; | |
448 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | |
449 | struct inv_mpu6050_state *st = iio_priv(indio_dev); | |
450 | ||
451 | if (kstrtoint(buf, 10, &fifo_rate)) | |
452 | return -EINVAL; | |
453 | if (fifo_rate < INV_MPU6050_MIN_FIFO_RATE || | |
454 | fifo_rate > INV_MPU6050_MAX_FIFO_RATE) | |
455 | return -EINVAL; | |
456 | if (fifo_rate == st->chip_config.fifo_rate) | |
457 | return count; | |
458 | ||
459 | mutex_lock(&indio_dev->mlock); | |
460 | if (st->chip_config.enable) { | |
461 | result = -EBUSY; | |
462 | goto fifo_rate_fail; | |
463 | } | |
464 | result = inv_mpu6050_set_power_itg(st, true); | |
465 | if (result) | |
466 | goto fifo_rate_fail; | |
467 | ||
468 | d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1; | |
469 | result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d); | |
470 | if (result) | |
471 | goto fifo_rate_fail; | |
472 | st->chip_config.fifo_rate = fifo_rate; | |
473 | ||
474 | result = inv_mpu6050_set_lpf(st, fifo_rate); | |
475 | if (result) | |
476 | goto fifo_rate_fail; | |
477 | ||
478 | fifo_rate_fail: | |
479 | result |= inv_mpu6050_set_power_itg(st, false); | |
480 | mutex_unlock(&indio_dev->mlock); | |
481 | if (result) | |
482 | return result; | |
483 | ||
484 | return count; | |
485 | } | |
486 | ||
487 | /** | |
488 | * inv_fifo_rate_show() - Get the current sampling rate. | |
489 | */ | |
490 | static ssize_t inv_fifo_rate_show(struct device *dev, | |
491 | struct device_attribute *attr, char *buf) | |
492 | { | |
493 | struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev)); | |
494 | ||
495 | return sprintf(buf, "%d\n", st->chip_config.fifo_rate); | |
496 | } | |
497 | ||
498 | /** | |
499 | * inv_attr_show() - calling this function will show current | |
500 | * parameters. | |
501 | */ | |
502 | static ssize_t inv_attr_show(struct device *dev, | |
503 | struct device_attribute *attr, char *buf) | |
504 | { | |
505 | struct inv_mpu6050_state *st = iio_priv(dev_to_iio_dev(dev)); | |
506 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | |
507 | s8 *m; | |
508 | ||
509 | switch (this_attr->address) { | |
510 | /* In MPU6050, the two matrix are the same because gyro and accel | |
511 | are integrated in one chip */ | |
512 | case ATTR_GYRO_MATRIX: | |
513 | case ATTR_ACCL_MATRIX: | |
514 | m = st->plat_data.orientation; | |
515 | ||
516 | return sprintf(buf, "%d, %d, %d; %d, %d, %d; %d, %d, %d\n", | |
517 | m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]); | |
518 | default: | |
519 | return -EINVAL; | |
520 | } | |
521 | } | |
522 | ||
523 | /** | |
524 | * inv_mpu6050_validate_trigger() - validate_trigger callback for invensense | |
525 | * MPU6050 device. | |
526 | * @indio_dev: The IIO device | |
527 | * @trig: The new trigger | |
528 | * | |
529 | * Returns: 0 if the 'trig' matches the trigger registered by the MPU6050 | |
530 | * device, -EINVAL otherwise. | |
531 | */ | |
532 | static int inv_mpu6050_validate_trigger(struct iio_dev *indio_dev, | |
533 | struct iio_trigger *trig) | |
534 | { | |
535 | struct inv_mpu6050_state *st = iio_priv(indio_dev); | |
536 | ||
537 | if (st->trig != trig) | |
538 | return -EINVAL; | |
539 | ||
540 | return 0; | |
541 | } | |
542 | ||
543 | #define INV_MPU6050_CHAN(_type, _channel2, _index) \ | |
544 | { \ | |
545 | .type = _type, \ | |
546 | .modified = 1, \ | |
547 | .channel2 = _channel2, \ | |
0b1f8da3 JC |
548 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
549 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
09a642b7 GG |
550 | .scan_index = _index, \ |
551 | .scan_type = { \ | |
552 | .sign = 's', \ | |
553 | .realbits = 16, \ | |
554 | .storagebits = 16, \ | |
555 | .shift = 0 , \ | |
556 | .endianness = IIO_BE, \ | |
557 | }, \ | |
558 | } | |
559 | ||
560 | static const struct iio_chan_spec inv_mpu_channels[] = { | |
561 | IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP), | |
562 | /* | |
563 | * Note that temperature should only be via polled reading only, | |
564 | * not the final scan elements output. | |
565 | */ | |
566 | { | |
567 | .type = IIO_TEMP, | |
0b1f8da3 JC |
568 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
569 | | BIT(IIO_CHAN_INFO_OFFSET) | |
570 | | BIT(IIO_CHAN_INFO_SCALE), | |
09a642b7 GG |
571 | .scan_index = -1, |
572 | }, | |
573 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), | |
574 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), | |
575 | INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), | |
576 | ||
577 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X), | |
578 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y), | |
579 | INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), | |
580 | }; | |
581 | ||
582 | /* constant IIO attribute */ | |
583 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500"); | |
584 | static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show, | |
585 | inv_mpu6050_fifo_rate_store); | |
586 | static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL, | |
587 | ATTR_GYRO_MATRIX); | |
588 | static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL, | |
589 | ATTR_ACCL_MATRIX); | |
590 | ||
591 | static struct attribute *inv_attributes[] = { | |
592 | &iio_dev_attr_in_gyro_matrix.dev_attr.attr, | |
593 | &iio_dev_attr_in_accel_matrix.dev_attr.attr, | |
594 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | |
595 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | |
596 | NULL, | |
597 | }; | |
598 | ||
599 | static const struct attribute_group inv_attribute_group = { | |
600 | .attrs = inv_attributes | |
601 | }; | |
602 | ||
603 | static const struct iio_info mpu_info = { | |
604 | .driver_module = THIS_MODULE, | |
605 | .read_raw = &inv_mpu6050_read_raw, | |
606 | .write_raw = &inv_mpu6050_write_raw, | |
607 | .attrs = &inv_attribute_group, | |
608 | .validate_trigger = inv_mpu6050_validate_trigger, | |
609 | }; | |
610 | ||
611 | /** | |
612 | * inv_check_and_setup_chip() - check and setup chip. | |
613 | */ | |
614 | static int inv_check_and_setup_chip(struct inv_mpu6050_state *st, | |
615 | const struct i2c_device_id *id) | |
616 | { | |
617 | int result; | |
618 | ||
619 | st->chip_type = INV_MPU6050; | |
620 | st->hw = &hw_info[st->chip_type]; | |
621 | st->reg = hw_info[st->chip_type].reg; | |
622 | ||
623 | /* reset to make sure previous state are not there */ | |
624 | result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, | |
625 | INV_MPU6050_BIT_H_RESET); | |
626 | if (result) | |
627 | return result; | |
628 | msleep(INV_MPU6050_POWER_UP_TIME); | |
629 | /* toggle power state. After reset, the sleep bit could be on | |
630 | or off depending on the OTP settings. Toggling power would | |
631 | make it in a definite state as well as making the hardware | |
632 | state align with the software state */ | |
633 | result = inv_mpu6050_set_power_itg(st, false); | |
634 | if (result) | |
635 | return result; | |
636 | result = inv_mpu6050_set_power_itg(st, true); | |
637 | if (result) | |
638 | return result; | |
639 | ||
640 | result = inv_mpu6050_switch_engine(st, false, | |
641 | INV_MPU6050_BIT_PWR_ACCL_STBY); | |
642 | if (result) | |
643 | return result; | |
644 | result = inv_mpu6050_switch_engine(st, false, | |
645 | INV_MPU6050_BIT_PWR_GYRO_STBY); | |
646 | if (result) | |
647 | return result; | |
648 | ||
649 | return 0; | |
650 | } | |
651 | ||
652 | /** | |
653 | * inv_mpu_probe() - probe function. | |
654 | * @client: i2c client. | |
655 | * @id: i2c device id. | |
656 | * | |
657 | * Returns 0 on success, a negative error code otherwise. | |
658 | */ | |
659 | static int inv_mpu_probe(struct i2c_client *client, | |
660 | const struct i2c_device_id *id) | |
661 | { | |
662 | struct inv_mpu6050_state *st; | |
663 | struct iio_dev *indio_dev; | |
664 | int result; | |
665 | ||
666 | if (!i2c_check_functionality(client->adapter, | |
452204ae SK |
667 | I2C_FUNC_SMBUS_I2C_BLOCK)) |
668 | return -ENOSYS; | |
669 | ||
670 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); | |
671 | if (!indio_dev) | |
672 | return -ENOMEM; | |
2ffdcd3d | 673 | |
09a642b7 GG |
674 | st = iio_priv(indio_dev); |
675 | st->client = client; | |
676 | st->plat_data = *(struct inv_mpu6050_platform_data | |
677 | *)dev_get_platdata(&client->dev); | |
678 | /* power is turned on inside check chip type*/ | |
679 | result = inv_check_and_setup_chip(st, id); | |
680 | if (result) | |
452204ae | 681 | return result; |
09a642b7 GG |
682 | |
683 | result = inv_mpu6050_init_config(indio_dev); | |
684 | if (result) { | |
685 | dev_err(&client->dev, | |
686 | "Could not initialize device.\n"); | |
452204ae | 687 | return result; |
09a642b7 GG |
688 | } |
689 | ||
690 | i2c_set_clientdata(client, indio_dev); | |
691 | indio_dev->dev.parent = &client->dev; | |
692 | indio_dev->name = id->name; | |
693 | indio_dev->channels = inv_mpu_channels; | |
694 | indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); | |
695 | ||
696 | indio_dev->info = &mpu_info; | |
697 | indio_dev->modes = INDIO_BUFFER_TRIGGERED; | |
698 | ||
699 | result = iio_triggered_buffer_setup(indio_dev, | |
700 | inv_mpu6050_irq_handler, | |
701 | inv_mpu6050_read_fifo, | |
702 | NULL); | |
703 | if (result) { | |
704 | dev_err(&st->client->dev, "configure buffer fail %d\n", | |
705 | result); | |
452204ae | 706 | return result; |
09a642b7 GG |
707 | } |
708 | result = inv_mpu6050_probe_trigger(indio_dev); | |
709 | if (result) { | |
710 | dev_err(&st->client->dev, "trigger probe fail %d\n", result); | |
711 | goto out_unreg_ring; | |
712 | } | |
713 | ||
714 | INIT_KFIFO(st->timestamps); | |
715 | spin_lock_init(&st->time_stamp_lock); | |
716 | result = iio_device_register(indio_dev); | |
717 | if (result) { | |
718 | dev_err(&st->client->dev, "IIO register fail %d\n", result); | |
719 | goto out_remove_trigger; | |
720 | } | |
721 | ||
722 | return 0; | |
723 | ||
724 | out_remove_trigger: | |
725 | inv_mpu6050_remove_trigger(st); | |
726 | out_unreg_ring: | |
727 | iio_triggered_buffer_cleanup(indio_dev); | |
09a642b7 GG |
728 | return result; |
729 | } | |
730 | ||
731 | static int inv_mpu_remove(struct i2c_client *client) | |
732 | { | |
733 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
734 | struct inv_mpu6050_state *st = iio_priv(indio_dev); | |
735 | ||
736 | iio_device_unregister(indio_dev); | |
737 | inv_mpu6050_remove_trigger(st); | |
738 | iio_triggered_buffer_cleanup(indio_dev); | |
09a642b7 GG |
739 | |
740 | return 0; | |
741 | } | |
742 | #ifdef CONFIG_PM_SLEEP | |
743 | ||
744 | static int inv_mpu_resume(struct device *dev) | |
745 | { | |
746 | return inv_mpu6050_set_power_itg( | |
747 | iio_priv(i2c_get_clientdata(to_i2c_client(dev))), true); | |
748 | } | |
749 | ||
750 | static int inv_mpu_suspend(struct device *dev) | |
751 | { | |
752 | return inv_mpu6050_set_power_itg( | |
753 | iio_priv(i2c_get_clientdata(to_i2c_client(dev))), false); | |
754 | } | |
755 | static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume); | |
756 | ||
757 | #define INV_MPU6050_PMOPS (&inv_mpu_pmops) | |
758 | #else | |
759 | #define INV_MPU6050_PMOPS NULL | |
760 | #endif /* CONFIG_PM_SLEEP */ | |
761 | ||
762 | /* | |
763 | * device id table is used to identify what device can be | |
764 | * supported by this driver | |
765 | */ | |
766 | static const struct i2c_device_id inv_mpu_id[] = { | |
767 | {"mpu6050", INV_MPU6050}, | |
768 | {} | |
769 | }; | |
770 | ||
771 | MODULE_DEVICE_TABLE(i2c, inv_mpu_id); | |
772 | ||
773 | static struct i2c_driver inv_mpu_driver = { | |
774 | .probe = inv_mpu_probe, | |
775 | .remove = inv_mpu_remove, | |
776 | .id_table = inv_mpu_id, | |
777 | .driver = { | |
778 | .owner = THIS_MODULE, | |
779 | .name = "inv-mpu6050", | |
780 | .pm = INV_MPU6050_PMOPS, | |
781 | }, | |
782 | }; | |
783 | ||
784 | module_i2c_driver(inv_mpu_driver); | |
785 | ||
786 | MODULE_AUTHOR("Invensense Corporation"); | |
787 | MODULE_DESCRIPTION("Invensense device MPU6050 driver"); | |
788 | MODULE_LICENSE("GPL"); |