blob: 1f246a881d6aedb197b28247d7b95e5ae9808341 [file] [log] [blame]
Flemmard0604a8e2013-05-23 16:15:48 -07001/*
2 mpu-dev.c - mpu3050 char device interface
3
4 Copyright (C) 1995-97 Simon G. Vogl
5 Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
6 Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
7 Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22#include <linux/i2c.h>
23#include <linux/i2c-dev.h>
24#include <linux/interrupt.h>
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/kernel.h>
28#include <linux/init.h>
29#include <linux/stat.h>
30#include <linux/irq.h>
31#include <linux/gpio.h>
32#include <linux/signal.h>
33#include <linux/miscdevice.h>
34#include <linux/slab.h>
35#include <linux/version.h>
36#include <linux/pm.h>
37
38#ifdef CONFIG_HAS_EARLYSUSPEND
39#include <linux/earlysuspend.h>
40#endif
41
42#include <linux/errno.h>
43#include <linux/fs.h>
44#include <linux/mm.h>
45#include <linux/sched.h>
46#include <linux/wait.h>
47#include <linux/uaccess.h>
48#include <linux/io.h>
49
50#include "mpuirq.h"
51#include "slaveirq.h"
52#include "mlsl.h"
53#include "mpu-i2c.h"
54#include "mldl_cfg.h"
55#include "mpu.h"
56
57#define MPU3050_EARLY_SUSPEND_IN_DRIVER 0
58
59#define D(x...) printk(KERN_DEBUG "[GYRO][MPU3050] " x)
60#define I(x...) printk(KERN_INFO "[GYRO][MPU3050] " x)
61#define E(x...) printk(KERN_ERR "[GYRO][MPU3050 ERROR] " x)
62
63struct mpu_private_data {
64 struct mldl_cfg mldl_cfg;
65
66#ifdef CONFIG_HAS_EARLYSUSPEND
67 struct early_suspend early_suspend;
68#endif
69};
70
71static int pid;
72
73static struct i2c_client *this_client;
74
75int mpu_debug_flag;
76int mpu_sensors_reset;
77int mpu_lpm_flag;
78
79static int mpu_open(struct inode *inode, struct file *file)
80{
81 struct mpu_private_data *mpu =
82 (struct mpu_private_data *) i2c_get_clientdata(this_client);
83 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
84
85 dev_dbg(&this_client->adapter->dev, "mpu_open\n");
86 dev_dbg(&this_client->adapter->dev, "current->pid %d\n",
87 current->pid);
88 pid = current->pid;
89 file->private_data = this_client;
90
91
92
93
94
95 mldl_cfg->requested_sensors = ML_THREE_AXIS_GYRO;
96 if (mldl_cfg->accel && mldl_cfg->accel->resume)
97 mldl_cfg->requested_sensors |= ML_THREE_AXIS_ACCEL;
98
99 if (mldl_cfg->compass && mldl_cfg->compass->resume)
100 mldl_cfg->requested_sensors |= ML_THREE_AXIS_COMPASS;
101
102 if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
103 mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
104
105 return 0;
106}
107
108static int mpu_release(struct inode *inode, struct file *file)
109{
110 struct i2c_client *client =
111 (struct i2c_client *) file->private_data;
112 struct mpu_private_data *mpu =
113 (struct mpu_private_data *) i2c_get_clientdata(client);
114 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
115 struct i2c_adapter *accel_adapter;
116 struct i2c_adapter *compass_adapter;
117 struct i2c_adapter *pressure_adapter;
118 int result = 0;
119
120 pid = 0;
121
122 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
123 compass_adapter = i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
124 pressure_adapter = i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
125 result = mpu3050_suspend(mldl_cfg, client->adapter,
126 accel_adapter, compass_adapter,
127 pressure_adapter,
128 TRUE, TRUE, TRUE, TRUE);
129
130 dev_dbg(&this_client->adapter->dev, "mpu_release\n");
131 return result;
132}
133
134static noinline int mpudev_ioctl_rdrw(struct i2c_client *client,
135 unsigned long arg)
136{
137 struct i2c_rdwr_ioctl_data rdwr_arg;
138 struct i2c_msg *rdwr_pa;
139 u8 __user **data_ptrs;
140 int i, res;
141
142 if (copy_from_user(&rdwr_arg,
143 (struct i2c_rdwr_ioctl_data __user *) arg,
144 sizeof(rdwr_arg)))
145 return -EFAULT;
146
147 if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
148 return -EINVAL;
149
150 rdwr_pa = (struct i2c_msg *)
151 kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);
152 if (!rdwr_pa)
153 return -ENOMEM;
154
155 if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
156 rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
157 kfree(rdwr_pa);
158 return -EFAULT;
159 }
160
161 data_ptrs =
162 kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
163 if (data_ptrs == NULL) {
164 kfree(rdwr_pa);
165 return -ENOMEM;
166 }
167
168 res = 0;
169 for (i = 0; i < rdwr_arg.nmsgs; i++) {
170 if ((rdwr_pa[i].len > 8192) ||
171 (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
172 res = -EINVAL;
173 break;
174 }
175 data_ptrs[i] = (u8 __user *) rdwr_pa[i].buf;
176 rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
177 if (rdwr_pa[i].buf == NULL) {
178 res = -ENOMEM;
179 break;
180 }
181 if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i],
182 rdwr_pa[i].len)) {
183 ++i;
184 res = -EFAULT;
185 break;
186 }
187 }
188 if (res < 0) {
189 int j;
190 for (j = 0; j < i; ++j)
191 kfree(rdwr_pa[j].buf);
192 kfree(data_ptrs);
193 kfree(rdwr_pa);
194 return res;
195 }
196
197 res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
198 while (i-- > 0) {
199 if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
200 if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
201 rdwr_pa[i].len))
202 res = -EFAULT;
203 }
204 kfree(rdwr_pa[i].buf);
205 }
206 kfree(data_ptrs);
207 kfree(rdwr_pa);
208 return res;
209}
210
211static ssize_t mpu_read(struct file *file,
212 char __user *buf, size_t count, loff_t *offset)
213{
214 char *tmp;
215 int ret;
216
217 struct i2c_client *client =
218 (struct i2c_client *) file->private_data;
219
220 if (count > 8192)
221 count = 8192;
222
223 tmp = kmalloc(count, GFP_KERNEL);
224 if (tmp == NULL)
225 return -ENOMEM;
226
227 pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",
228 iminor(file->f_path.dentry->d_inode), count);
229
230 ret = i2c_master_recv(client, tmp, count);
231 if (ret >= 0) {
232 ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
233 if (ret)
234 ret = -EFAULT;
235 }
236 kfree(tmp);
237 return ret;
238}
239
240static int
241mpu_ioctl_set_mpu_pdata(struct i2c_client *client, unsigned long arg)
242{
243 int ii;
244 struct mpu_private_data *mpu =
245 (struct mpu_private_data *) i2c_get_clientdata(client);
246 struct mpu3050_platform_data *pdata = mpu->mldl_cfg.pdata;
247 struct mpu3050_platform_data local_pdata;
248
249 if (copy_from_user(&local_pdata, (unsigned char __user *) arg,
250 sizeof(local_pdata)))
251 return -EFAULT;
252
253 pdata->int_config = local_pdata.int_config;
254 for (ii = 0; ii < DIM(pdata->orientation); ii++)
255 pdata->orientation[ii] = local_pdata.orientation[ii];
256 pdata->level_shifter = local_pdata.level_shifter;
257
258 pdata->accel.address = local_pdata.accel.address;
259 for (ii = 0; ii < DIM(pdata->accel.orientation); ii++)
260 pdata->accel.orientation[ii] =
261 local_pdata.accel.orientation[ii];
262
263 pdata->compass.address = local_pdata.compass.address;
264 for (ii = 0; ii < DIM(pdata->compass.orientation); ii++)
265 pdata->compass.orientation[ii] =
266 local_pdata.compass.orientation[ii];
267
268 pdata->pressure.address = local_pdata.pressure.address;
269 for (ii = 0; ii < DIM(pdata->pressure.orientation); ii++)
270 pdata->pressure.orientation[ii] =
271 local_pdata.pressure.orientation[ii];
272
273 dev_dbg(&client->adapter->dev, "%s\n", __func__);
274
275 return ML_SUCCESS;
276}
277
278static int
279mpu_ioctl_set_mpu_config(struct i2c_client *client, unsigned long arg)
280{
281 int ii;
282 int result = ML_SUCCESS;
283 struct mpu_private_data *mpu =
284 (struct mpu_private_data *) i2c_get_clientdata(client);
285 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
286 struct mldl_cfg *temp_mldl_cfg;
287
288 dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
289
290 temp_mldl_cfg = kzalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
291 if (NULL == temp_mldl_cfg)
292 return -ENOMEM;
293
294 if (copy_from_user(temp_mldl_cfg, (struct mldl_cfg __user *) arg,
295 offsetof(struct mldl_cfg, silicon_revision))) {
296 result = -EFAULT;
297 goto out;
298 }
299
300 if (mldl_cfg->gyro_is_suspended) {
301 if (mldl_cfg->addr != temp_mldl_cfg->addr)
302 mldl_cfg->gyro_needs_reset = TRUE;
303
304 if (mldl_cfg->int_config != temp_mldl_cfg->int_config)
305 mldl_cfg->gyro_needs_reset = TRUE;
306
307 if (mldl_cfg->ext_sync != temp_mldl_cfg->ext_sync)
308 mldl_cfg->gyro_needs_reset = TRUE;
309
310 if (mldl_cfg->full_scale != temp_mldl_cfg->full_scale)
311 mldl_cfg->gyro_needs_reset = TRUE;
312
313 if (mldl_cfg->lpf != temp_mldl_cfg->lpf)
314 mldl_cfg->gyro_needs_reset = TRUE;
315
316 if (mldl_cfg->clk_src != temp_mldl_cfg->clk_src)
317 mldl_cfg->gyro_needs_reset = TRUE;
318
319 if (mldl_cfg->divider != temp_mldl_cfg->divider)
320 mldl_cfg->gyro_needs_reset = TRUE;
321
322 if (mldl_cfg->dmp_enable != temp_mldl_cfg->dmp_enable)
323 mldl_cfg->gyro_needs_reset = TRUE;
324
325 if (mldl_cfg->fifo_enable != temp_mldl_cfg->fifo_enable)
326 mldl_cfg->gyro_needs_reset = TRUE;
327
328 if (mldl_cfg->dmp_cfg1 != temp_mldl_cfg->dmp_cfg1)
329 mldl_cfg->gyro_needs_reset = TRUE;
330
331 if (mldl_cfg->dmp_cfg2 != temp_mldl_cfg->dmp_cfg2)
332 mldl_cfg->gyro_needs_reset = TRUE;
333
334 if (mldl_cfg->gyro_power != temp_mldl_cfg->gyro_power)
335 mldl_cfg->gyro_needs_reset = TRUE;
336
337 for (ii = 0; ii < MPU_NUM_AXES; ii++)
338 if (mldl_cfg->offset_tc[ii] !=
339 temp_mldl_cfg->offset_tc[ii])
340 mldl_cfg->gyro_needs_reset = TRUE;
341
342 for (ii = 0; ii < MPU_NUM_AXES; ii++)
343 if (mldl_cfg->offset[ii] != temp_mldl_cfg->offset[ii])
344 mldl_cfg->gyro_needs_reset = TRUE;
345
346 if (memcmp(mldl_cfg->ram, temp_mldl_cfg->ram,
347 MPU_MEM_NUM_RAM_BANKS * MPU_MEM_BANK_SIZE *
348 sizeof(unsigned char)))
349 mldl_cfg->gyro_needs_reset = TRUE;
350 }
351
352 memcpy(mldl_cfg, temp_mldl_cfg,
353 offsetof(struct mldl_cfg, silicon_revision));
354
355out:
356 kfree(temp_mldl_cfg);
357 return result;
358}
359
360static int
361mpu_ioctl_get_mpu_config(struct i2c_client *client, unsigned long arg)
362{
363 struct mpu_private_data *mpu =
364 (struct mpu_private_data *) i2c_get_clientdata(client);
365 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
366 struct mldl_cfg *local_mldl_cfg;
367 int retval = 0;
368
369 local_mldl_cfg = kzalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
370 if (NULL == local_mldl_cfg)
371 return -ENOMEM;
372
373 retval =
374 copy_from_user(local_mldl_cfg, (struct mldl_cfg __user *) arg,
375 sizeof(struct mldl_cfg));
376 if (retval) {
377 dev_err(&this_client->adapter->dev,
378 "%s|%s:%d: EFAULT on arg\n",
379 __FILE__, __func__, __LINE__);
380 retval = -EFAULT;
381 goto out;
382 }
383
384
385 if (mldl_cfg->accel) {
386 retval = copy_to_user((void __user *)local_mldl_cfg->accel,
387 mldl_cfg->accel,
388 sizeof(*mldl_cfg->accel));
389 if (retval) {
390 dev_err(&this_client->adapter->dev,
391 "%s|%s:%d: EFAULT on accel\n",
392 __FILE__, __func__, __LINE__);
393 retval = -EFAULT;
394 goto out;
395 }
396 }
397
398 if (mldl_cfg->compass) {
399 retval = copy_to_user((void __user *)local_mldl_cfg->compass,
400 mldl_cfg->compass,
401 sizeof(*mldl_cfg->compass));
402 if (retval) {
403 dev_err(&this_client->adapter->dev,
404 "%s|%s:%d: EFAULT on compass\n",
405 __FILE__, __func__, __LINE__);
406 retval = -EFAULT;
407 goto out;
408 }
409 }
410
411 if (mldl_cfg->pressure) {
412 retval = copy_to_user((void __user *)local_mldl_cfg->pressure,
413 mldl_cfg->pressure,
414 sizeof(*mldl_cfg->pressure));
415 if (retval) {
416 dev_err(&this_client->adapter->dev,
417 "%s|%s:%d: EFAULT on pressure\n",
418 __FILE__, __func__, __LINE__);
419 retval = -EFAULT;
420 goto out;
421 }
422 }
423
424 if (mldl_cfg->pdata) {
425 retval = copy_to_user((void __user *)local_mldl_cfg->pdata,
426 mldl_cfg->pdata,
427 sizeof(*mldl_cfg->pdata));
428 if (retval) {
429 dev_err(&this_client->adapter->dev,
430 "%s|%s:%d: EFAULT on pdata\n",
431 __FILE__, __func__, __LINE__);
432 retval = -EFAULT;
433 goto out;
434 }
435 }
436
437
438 retval = copy_to_user((struct mldl_cfg __user *) arg,
439 mldl_cfg, offsetof(struct mldl_cfg, accel));
440
441 if (retval)
442 retval = -EFAULT;
443out:
444 kfree(local_mldl_cfg);
445 return retval;
446}
447
448static int slave_config(void *adapter,
449 struct mldl_cfg *mldl_cfg,
450 struct ext_slave_descr *slave,
451 struct ext_slave_platform_data *pdata,
452 struct ext_slave_config __user *usr_config)
453{
454 int retval = ML_SUCCESS;
455 if ((slave) && (slave->config)) {
456 struct ext_slave_config config;
457 retval = copy_from_user(
458 &config,
459 usr_config,
460 sizeof(config));
461 if (retval)
462 return -EFAULT;
463
464 if (config.len && config.data) {
465 int *data;
466 data = kzalloc(config.len, GFP_KERNEL);
467 if (!data)
468 return ML_ERROR_MEMORY_EXAUSTED;
469
470 retval = copy_from_user(data,
471 (void __user *)config.data,
472 config.len);
473 if (retval) {
474 retval = -EFAULT;
475 kfree(data);
476 return retval;
477 }
478 config.data = data;
479 }
480 retval = slave->config(adapter,
481 slave,
482 pdata,
483 &config);
484 kfree(config.data);
485 }
486 return retval;
487}
488
489static int slave_get_config(void *adapter,
490 struct mldl_cfg *mldl_cfg,
491 struct ext_slave_descr *slave,
492 struct ext_slave_platform_data *pdata,
493 struct ext_slave_config __user *usr_config)
494{
495 int retval = ML_SUCCESS;
496 if ((slave) && (slave->get_config)) {
497 struct ext_slave_config config;
498 void *user_data;
499 retval = copy_from_user(
500 &config,
501 usr_config,
502 sizeof(config));
503 if (retval)
504 return -EFAULT;
505
506 user_data = config.data;
507 if (config.len && config.data) {
508 int *data;
509 data = kzalloc(config.len, GFP_KERNEL);
510 if (!data)
511 return ML_ERROR_MEMORY_EXAUSTED;
512
513 retval = copy_from_user(data,
514 (void __user *)config.data,
515 config.len);
516 if (retval) {
517 retval = -EFAULT;
518 kfree(data);
519 return retval;
520 }
521 config.data = data;
522 }
523 retval = slave->get_config(adapter,
524 slave,
525 pdata,
526 &config);
527 if (retval) {
528 kfree(config.data);
529 return retval;
530 }
531 retval = copy_to_user((unsigned char __user *) user_data,
532 config.data,
533 config.len);
534 kfree(config.data);
535 }
536 return retval;
537}
538
539static long mpu_ioctl(struct file *file,
540 unsigned int cmd, unsigned long arg)
541{
542 struct i2c_client *client =
543 (struct i2c_client *) file->private_data;
544 struct mpu_private_data *mpu =
545 (struct mpu_private_data *) i2c_get_clientdata(client);
546 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
547 int retval = 0;
548 struct i2c_adapter *accel_adapter;
549 struct i2c_adapter *compass_adapter;
550 struct i2c_adapter *pressure_adapter;
551
552 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
553 compass_adapter =
554 i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
555 pressure_adapter =
556 i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
557
558 switch (cmd) {
559 case I2C_RDWR:
560 mpudev_ioctl_rdrw(client, arg);
561 break;
562 case I2C_SLAVE:
563 if ((arg & 0x7E) != (client->addr & 0x7E)) {
564 dev_err(&this_client->adapter->dev,
565 "[mpu_err]%s: Invalid I2C_SLAVE arg %lu\n",
566 __func__, arg);
567 }
568 break;
569 case MPU_SET_MPU_CONFIG:
570 retval = mpu_ioctl_set_mpu_config(client, arg);
571 break;
572 case MPU_SET_INT_CONFIG:
573 mldl_cfg->int_config = (unsigned char) arg;
574 break;
575 case MPU_SET_EXT_SYNC:
576 mldl_cfg->ext_sync = (enum mpu_ext_sync) arg;
577 break;
578 case MPU_SET_FULL_SCALE:
579 mldl_cfg->full_scale = (enum mpu_fullscale) arg;
580 break;
581 case MPU_SET_LPF:
582 mldl_cfg->lpf = (enum mpu_filter) arg;
583 break;
584 case MPU_SET_CLK_SRC:
585 mldl_cfg->clk_src = (enum mpu_clock_sel) arg;
586 break;
587 case MPU_SET_DIVIDER:
588 mldl_cfg->divider = (unsigned char) arg;
589 break;
590 case MPU_SET_LEVEL_SHIFTER:
591 mldl_cfg->pdata->level_shifter = (unsigned char) arg;
592 break;
593 case MPU_SET_DMP_ENABLE:
594 mldl_cfg->dmp_enable = (unsigned char) arg;
595 break;
596 case MPU_SET_FIFO_ENABLE:
597 mldl_cfg->fifo_enable = (unsigned char) arg;
598 break;
599 case MPU_SET_DMP_CFG1:
600 mldl_cfg->dmp_cfg1 = (unsigned char) arg;
601 break;
602 case MPU_SET_DMP_CFG2:
603 mldl_cfg->dmp_cfg2 = (unsigned char) arg;
604 break;
605 case MPU_SET_OFFSET_TC:
606 retval = copy_from_user(mldl_cfg->offset_tc,
607 (unsigned char __user *) arg,
608 sizeof(mldl_cfg->offset_tc));
609 if (retval)
610 retval = -EFAULT;
611
612 break;
613 case MPU_SET_RAM:
614 retval = copy_from_user(mldl_cfg->ram,
615 (unsigned char __user *) arg,
616 sizeof(mldl_cfg->ram));
617 if (retval)
618 retval = -EFAULT;
619 break;
620 case MPU_SET_PLATFORM_DATA:
621 retval = mpu_ioctl_set_mpu_pdata(client, arg);
622 break;
623 case MPU_GET_MPU_CONFIG:
624 retval = mpu_ioctl_get_mpu_config(client, arg);
625 break;
626 case MPU_GET_INT_CONFIG:
627 retval = put_user(mldl_cfg->int_config,
628 (unsigned char __user *) arg);
629 break;
630 case MPU_GET_EXT_SYNC:
631 retval = put_user(mldl_cfg->ext_sync,
632 (unsigned char __user *) arg);
633 break;
634 case MPU_GET_FULL_SCALE:
635 retval = put_user(mldl_cfg->full_scale,
636 (unsigned char __user *) arg);
637 break;
638 case MPU_GET_LPF:
639 retval = put_user(mldl_cfg->lpf,
640 (unsigned char __user *) arg);
641 break;
642 case MPU_GET_CLK_SRC:
643 retval = put_user(mldl_cfg->clk_src,
644 (unsigned char __user *) arg);
645 break;
646 case MPU_GET_DIVIDER:
647 retval = put_user(mldl_cfg->divider,
648 (unsigned char __user *) arg);
649 break;
650 case MPU_GET_LEVEL_SHIFTER:
651 retval = put_user(mldl_cfg->pdata->level_shifter,
652 (unsigned char __user *) arg);
653 break;
654 case MPU_GET_DMP_ENABLE:
655 retval = put_user(mldl_cfg->dmp_enable,
656 (unsigned char __user *) arg);
657 break;
658 case MPU_GET_FIFO_ENABLE:
659 retval = put_user(mldl_cfg->fifo_enable,
660 (unsigned char __user *) arg);
661 break;
662 case MPU_GET_DMP_CFG1:
663 retval = put_user(mldl_cfg->dmp_cfg1,
664 (unsigned char __user *) arg);
665 break;
666 case MPU_GET_DMP_CFG2:
667 retval = put_user(mldl_cfg->dmp_cfg2,
668 (unsigned char __user *) arg);
669 break;
670 case MPU_GET_OFFSET_TC:
671 retval = copy_to_user((unsigned char __user *) arg,
672 mldl_cfg->offset_tc,
673 sizeof(mldl_cfg->offset_tc));
674 if (retval)
675 retval = -EFAULT;
676 break;
677 case MPU_GET_RAM:
678 retval = copy_to_user((unsigned char __user *) arg,
679 mldl_cfg->ram,
680 sizeof(mldl_cfg->ram));
681 if (retval)
682 retval = -EFAULT;
683 break;
684 case MPU_CONFIG_ACCEL:
685 retval = slave_config(accel_adapter, mldl_cfg,
686 mldl_cfg->accel,
687 &mldl_cfg->pdata->accel,
688 (struct ext_slave_config __user *) arg);
689 break;
690 case MPU_CONFIG_COMPASS:
691 retval = slave_config(compass_adapter, mldl_cfg,
692 mldl_cfg->compass,
693 &mldl_cfg->pdata->compass,
694 (struct ext_slave_config __user *) arg);
695 break;
696 case MPU_CONFIG_PRESSURE:
697 retval = slave_config(pressure_adapter, mldl_cfg,
698 mldl_cfg->pressure,
699 &mldl_cfg->pdata->pressure,
700 (struct ext_slave_config __user *) arg);
701 break;
702 case MPU_GET_CONFIG_ACCEL:
703 retval = slave_get_config(accel_adapter, mldl_cfg,
704 mldl_cfg->accel,
705 &mldl_cfg->pdata->accel,
706 (struct ext_slave_config __user *) arg);
707 break;
708 case MPU_GET_CONFIG_COMPASS:
709 retval = slave_get_config(compass_adapter, mldl_cfg,
710 mldl_cfg->compass,
711 &mldl_cfg->pdata->compass,
712 (struct ext_slave_config __user *) arg);
713 break;
714 case MPU_GET_CONFIG_PRESSURE:
715 retval = slave_get_config(pressure_adapter, mldl_cfg,
716 mldl_cfg->pressure,
717 &mldl_cfg->pdata->pressure,
718 (struct ext_slave_config __user *) arg);
719 break;
720 case MPU_SUSPEND:
721 {
722 unsigned long sensors;
723 sensors = ~(mldl_cfg->requested_sensors);
724 retval = mpu3050_suspend(mldl_cfg,
725 client->adapter,
726 accel_adapter,
727 compass_adapter,
728 pressure_adapter,
729 ((sensors & ML_THREE_AXIS_GYRO)
730 == ML_THREE_AXIS_GYRO),
731 ((sensors & ML_THREE_AXIS_ACCEL)
732 == ML_THREE_AXIS_ACCEL),
733 ((sensors & ML_THREE_AXIS_COMPASS)
734 == ML_THREE_AXIS_COMPASS),
735 ((sensors & ML_THREE_AXIS_PRESSURE)
736 == ML_THREE_AXIS_PRESSURE));
737 }
738 break;
739 case MPU_RESUME:
740 {
741 unsigned long sensors;
742
743
744 sensors = mldl_cfg->requested_sensors;
745 retval = mpu3050_resume(mldl_cfg,
746 client->adapter,
747 accel_adapter,
748 compass_adapter,
749 pressure_adapter,
750 sensors & ML_THREE_AXIS_GYRO,
751 sensors & ML_THREE_AXIS_ACCEL,
752 sensors & ML_THREE_AXIS_COMPASS,
753 sensors & ML_THREE_AXIS_PRESSURE);
754 }
755 break;
756 case MPU_READ_ACCEL:
757 {
758 unsigned char data[6];
759 retval = mpu3050_read_accel(mldl_cfg, client->adapter,
760 data);
761 if ((ML_SUCCESS == retval) &&
762 (copy_to_user((unsigned char __user *) arg,
763 data, sizeof(data))))
764 retval = -EFAULT;
765 }
766 break;
767 case MPU_READ_COMPASS:
768 {
769 unsigned char data[6];
770 struct i2c_adapter *compass_adapt =
771 i2c_get_adapter(mldl_cfg->pdata->compass.
772 adapt_num);
773 retval = mpu3050_read_compass(mldl_cfg, compass_adapt,
774 data);
775 if ((ML_SUCCESS == retval) &&
776 (copy_to_user((unsigned char *) arg,
777 data, sizeof(data))))
778 retval = -EFAULT;
779 }
780 break;
781 case MPU_READ_PRESSURE:
782 {
783 unsigned char data[3];
784 struct i2c_adapter *pressure_adapt =
785 i2c_get_adapter(mldl_cfg->pdata->pressure.
786 adapt_num);
787 retval =
788 mpu3050_read_pressure(mldl_cfg, pressure_adapt,
789 data);
790 if ((ML_SUCCESS == retval) &&
791 (copy_to_user((unsigned char __user *) arg,
792 data, sizeof(data))))
793 retval = -EFAULT;
794 }
795 break;
796#ifdef HTC_READ_CAL_DATA
797 case MPU_READ_CAL_DATA:
798 {
799 int index;
800 unsigned char mpu_gyro_gsensor_kvalue[37];
801
802 for (index = 0;
803 index < sizeof(mpu_gyro_gsensor_kvalue);
804 index++) {
805 mpu_gyro_gsensor_kvalue[index] =
806 gyro_gsensor_kvalue[index];
807 printk(KERN_DEBUG "gyro_gsensor_kvalue[%d] = 0x%x\n",
808 index, gyro_gsensor_kvalue[index]);
809 }
810
811 retval =
812 copy_to_user((unsigned char *) arg,
813 mpu_gyro_gsensor_kvalue,
814 sizeof(mpu_gyro_gsensor_kvalue));
815 }
816 break;
817#endif
818 case MPU_READ_MEMORY:
819 case MPU_WRITE_MEMORY:
820 default:
821 dev_err(&this_client->adapter->dev,
822 "[mpu_err]%s: Unknown cmd %d, arg %lu\n", __func__, cmd,
823 arg);
824 retval = -EINVAL;
825 }
826
827 return retval;
828}
829
830#ifdef CONFIG_HAS_EARLYSUSPEND
831void mpu3050_early_suspend(struct early_suspend *h)
832{
833 struct mpu_private_data *mpu = container_of(h,
834 struct
835 mpu_private_data,
836 early_suspend);
837 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
838 struct i2c_adapter *accel_adapter;
839 struct i2c_adapter *compass_adapter;
840 struct i2c_adapter *pressure_adapter;
841
842 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
843 compass_adapter =
844 i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
845 pressure_adapter =
846 i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
847
848 dev_dbg(&this_client->adapter->dev, "%s: %d, %d\n", __func__,
849 h->level, mpu->mldl_cfg.gyro_is_suspended);
850 if (MPU3050_EARLY_SUSPEND_IN_DRIVER)
851 (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
852 accel_adapter, compass_adapter,
853 pressure_adapter, TRUE, TRUE, TRUE, TRUE);
854}
855
856void mpu3050_early_resume(struct early_suspend *h)
857{
858 struct mpu_private_data *mpu = container_of(h,
859 struct
860 mpu_private_data,
861 early_suspend);
862 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
863 struct i2c_adapter *accel_adapter;
864 struct i2c_adapter *compass_adapter;
865 struct i2c_adapter *pressure_adapter;
866
867 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
868 compass_adapter =
869 i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
870 pressure_adapter =
871 i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
872
873 if (MPU3050_EARLY_SUSPEND_IN_DRIVER) {
874 if (pid) {
875 unsigned long sensors = mldl_cfg->requested_sensors;
876 (void) mpu3050_resume(mldl_cfg,
877 this_client->adapter,
878 accel_adapter,
879 compass_adapter,
880 pressure_adapter,
881 sensors & ML_THREE_AXIS_GYRO,
882 sensors & ML_THREE_AXIS_ACCEL,
883 sensors & ML_THREE_AXIS_COMPASS,
884 sensors & ML_THREE_AXIS_PRESSURE);
885 dev_dbg(&this_client->adapter->dev,
886 "%s for pid %d\n", __func__, pid);
887 }
888 }
889 dev_dbg(&this_client->adapter->dev, "%s: %d\n", __func__, h->level);
890}
891#endif
892
893void mpu_shutdown(struct i2c_client *client)
894{
895 struct mpu_private_data *mpu =
896 (struct mpu_private_data *) i2c_get_clientdata(client);
897 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
898 struct i2c_adapter *accel_adapter;
899 struct i2c_adapter *compass_adapter;
900 struct i2c_adapter *pressure_adapter;
901
902 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
903 compass_adapter =
904 i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
905 pressure_adapter =
906 i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
907
908 (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
909 accel_adapter, compass_adapter, pressure_adapter,
910 TRUE, TRUE, TRUE, TRUE);
911 dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
912}
913
914int mpu_suspend(struct i2c_client *client, pm_message_t mesg)
915{
916 struct mpu_private_data *mpu =
917 (struct mpu_private_data *) i2c_get_clientdata(client);
918 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
919 struct i2c_adapter *accel_adapter;
920 struct i2c_adapter *compass_adapter;
921 struct i2c_adapter *pressure_adapter;
922
923 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
924 compass_adapter =
925 i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
926 pressure_adapter =
927 i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
928
929 if (!mpu->mldl_cfg.gyro_is_suspended) {
930 dev_dbg(&this_client->adapter->dev,
931 "%s: suspending on event %d\n", __func__,
932 mesg.event);
933 (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
934 accel_adapter, compass_adapter,
935 pressure_adapter,
936 TRUE, TRUE, TRUE, TRUE);
937 } else {
938 dev_dbg(&this_client->adapter->dev,
939 "%s: Already suspended %d\n", __func__,
940 mesg.event);
941 }
942
943 return 0;
944}
945
946int mpu_resume(struct i2c_client *client)
947{
948 struct mpu_private_data *mpu =
949 (struct mpu_private_data *) i2c_get_clientdata(client);
950 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
951 struct i2c_adapter *accel_adapter;
952 struct i2c_adapter *compass_adapter;
953 struct i2c_adapter *pressure_adapter;
954
955 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
956 compass_adapter =
957 i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
958 pressure_adapter =
959 i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
960
961 if (pid) {
962 unsigned long sensors = mldl_cfg->requested_sensors;
963 (void) mpu3050_resume(mldl_cfg, this_client->adapter,
964 accel_adapter,
965 compass_adapter,
966 pressure_adapter,
967 sensors & ML_THREE_AXIS_GYRO,
968 sensors & ML_THREE_AXIS_ACCEL,
969 sensors & ML_THREE_AXIS_COMPASS,
970 sensors & ML_THREE_AXIS_PRESSURE);
971 dev_dbg(&this_client->adapter->dev,
972 "%s for pid %d\n", __func__, pid);
973 }
974
975 return 0;
976}
977
978static const struct file_operations mpu_fops = {
979 .owner = THIS_MODULE,
980 .read = mpu_read,
981#if HAVE_COMPAT_IOCTL
982 .compat_ioctl = mpu_ioctl,
983#endif
984#if HAVE_UNLOCKED_IOCTL
985 .unlocked_ioctl = mpu_ioctl,
986#endif
987 .open = mpu_open,
988 .release = mpu_release,
989};
990
991static unsigned short normal_i2c[] = { I2C_CLIENT_END };
992
993static struct miscdevice i2c_mpu_device = {
994 .minor = MISC_DYNAMIC_MINOR,
995 .name = "mpu",
996 .fops = &mpu_fops,
997};
998
999void *g_handler;
1000int (*g_sensors_reset)(void);
1001
1002struct class *mpu3050_class;
1003struct device *mpu3050_dev;
1004
1005static ssize_t pwr_reg_show(struct device *dev,
1006 struct device_attribute *attr, char *buf)
1007{
1008 unsigned char b[2] = "";
1009 int result;
1010
1011 unsigned char bma[8] = "";
1012
1013 result = MLSLSerialRead(g_handler, 0x68,
1014 MPUREG_USER_CTRL, 2, b);
1015
1016 result = MLSLSerialRead(g_handler, 0x18,
1017 0x0F, 3, bma);
1018
1019 result = sprintf(buf, "MPUREG_USER_CTRL = 0x%x, MPUREG_PWR_MGM = "
1020 "0x%x.\n"
1021 "BMA register 0x0F = 0x%x, "
1022 "BMA register 0x10 = 0x%x, "
1023 "BMA register 0x11 = 0x%x\n"
1024 "",
1025 b[0], b[1],
1026 bma[0], bma[1], bma[2]);
1027
1028 return result;
1029}
1030
1031static ssize_t pwr_reg_store(struct device *dev,
1032 struct device_attribute *attr,
1033 const char *buf, size_t count)
1034{
1035 return count;
1036}
1037
1038static DEVICE_ATTR(pwr_reg, 0664, pwr_reg_show, pwr_reg_store);
1039
1040static ssize_t mpu_debug_flag_show(struct device *dev,
1041 struct device_attribute *attr, char *buf)
1042{
1043 char *s = buf;
1044
1045 s += sprintf(s, "mpu_debug_flag = 0x%x\n", mpu_debug_flag);
1046
1047 return s - buf;
1048}
1049
1050static ssize_t mpu_debug_flag_store(struct device *dev,
1051 struct device_attribute *attr,
1052 const char *buf, size_t count)
1053{
1054 mpu_debug_flag = -1;
1055 sscanf(buf, "%d", &mpu_debug_flag);
1056
1057 D("%s: mpu_debug_flag = %d\n", __func__, mpu_debug_flag);
1058
1059 return count;
1060}
1061
1062static DEVICE_ATTR(mpu_debug_flag, 0664, mpu_debug_flag_show, \
1063 mpu_debug_flag_store);
1064
1065static ssize_t mpu_sensors_reset_show(struct device *dev,
1066 struct device_attribute *attr, char *buf)
1067{
1068 char *s = buf;
1069
1070 s += sprintf(s, "mpu_sensors_reset = 0x%x\n", mpu_sensors_reset);
1071
1072 return s - buf;
1073}
1074
1075static ssize_t mpu_sensors_reset_store(struct device *dev,
1076 struct device_attribute *attr,
1077 const char *buf, size_t count)
1078{
1079 int rc = 0;
1080
1081 mpu_sensors_reset = -1;
1082 sscanf(buf, "%d", &mpu_sensors_reset);
1083
1084 D("%s: mpu_sensors_reset = %d\n", __func__, mpu_sensors_reset);
1085
1086 if ((mpu_sensors_reset == 1) && g_sensors_reset) {
1087 rc = g_sensors_reset();
1088 if (rc)
1089 E("G-Sensor, Compass, Gyro reset error\n");
1090 }
1091
1092 return count;
1093}
1094
1095static DEVICE_ATTR(mpu_sensors_reset, 0664, mpu_sensors_reset_show, \
1096 mpu_sensors_reset_store);
1097
1098
1099static ssize_t mpu_lpm_flag_show(struct device *dev,
1100 struct device_attribute *attr, char *buf)
1101{
1102 char *s = buf;
1103
1104 s += sprintf(s, "%d", mpu_lpm_flag);
1105
1106 return s - buf;
1107}
Flemmard8923f4a2014-01-07 12:43:27 -08001108#ifdef CONFIG_CIR_ALWAYS_READY
1109extern int cir_flag;
1110#endif
Flemmard0604a8e2013-05-23 16:15:48 -07001111static ssize_t mpu_lpm_flag_store(struct device *dev,
1112 struct device_attribute *attr,
1113 const char *buf, size_t count)
1114{
1115 struct mpu_private_data *mpu =
1116 (struct mpu_private_data *) i2c_get_clientdata(this_client);
1117 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
1118
1119 mpu_lpm_flag = -1;
1120 sscanf(buf, "%d", &mpu_lpm_flag);
Flemmard8923f4a2014-01-07 12:43:27 -08001121#ifdef CONFIG_CIR_ALWAYS_READY
1122
1123 if ((mpu_lpm_flag == 1) && mldl_cfg->pdata->power_LPM && !cir_flag)
1124#else
Flemmard0604a8e2013-05-23 16:15:48 -07001125 if ((mpu_lpm_flag == 1) && mldl_cfg->pdata->power_LPM)
Flemmard8923f4a2014-01-07 12:43:27 -08001126#endif
Flemmard0604a8e2013-05-23 16:15:48 -07001127 mldl_cfg->pdata->power_LPM(1);
1128 else if (mldl_cfg->pdata->power_LPM)
1129 mldl_cfg->pdata->power_LPM(0);
1130
1131 D("%s: mpu_lpm_flag = %d\n", __func__, mpu_lpm_flag);
1132
1133 return count;
1134}
1135
1136static DEVICE_ATTR(mpu_lpm_flag, 0664, mpu_lpm_flag_show, \
1137 mpu_lpm_flag_store);
1138
1139
1140int mpu3050_probe(struct i2c_client *client,
1141 const struct i2c_device_id *devid)
1142{
1143 struct mpu3050_platform_data *pdata;
1144 struct mpu_private_data *mpu;
1145 struct mldl_cfg *mldl_cfg;
1146 int res = 0;
1147 struct i2c_adapter *accel_adapter = NULL;
1148 struct i2c_adapter *compass_adapter = NULL;
1149 struct i2c_adapter *pressure_adapter = NULL;
1150
1151 dev_dbg(&client->adapter->dev, "%s\n", __func__);
1152
1153 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1154 res = -ENODEV;
1155 goto out_check_functionality_failed;
1156 }
1157
1158 mpu = kzalloc(sizeof(struct mpu_private_data), GFP_KERNEL);
1159 if (!mpu) {
1160 res = -ENOMEM;
1161 goto out_alloc_data_failed;
1162 }
1163
1164 i2c_set_clientdata(client, mpu);
1165 this_client = client;
1166 mldl_cfg = &mpu->mldl_cfg;
1167 pdata = (struct mpu3050_platform_data *) client->dev.platform_data;
1168 if (!pdata) {
1169 dev_warn(&this_client->adapter->dev,
1170 "Warning no platform data for mpu3050\n");
1171 } else {
1172 mldl_cfg->pdata = pdata;
1173
1174 g_sensors_reset = pdata->g_sensors_reset;
1175
1176#if defined(CONFIG_MPU_SENSORS_MPU3050_MODULE) || \
1177 defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)
1178 pdata->accel.get_slave_descr = get_accel_slave_descr;
1179 pdata->compass.get_slave_descr = get_compass_slave_descr;
1180 pdata->pressure.get_slave_descr = get_pressure_slave_descr;
1181#endif
1182
1183 if (pdata->accel.get_slave_descr) {
1184 mldl_cfg->accel =
1185 pdata->accel.get_slave_descr();
1186 dev_info(&this_client->adapter->dev,
1187 "%s: +%s\n", MPU_NAME,
1188 mldl_cfg->accel->name);
1189 accel_adapter =
1190 i2c_get_adapter(pdata->accel.adapt_num);
1191 if (pdata->accel.irq > 0) {
1192 dev_info(&this_client->adapter->dev,
1193 "Installing Accel irq using %d\n",
1194 pdata->accel.irq);
1195 res = slaveirq_init(accel_adapter,
Flemmard8923f4a2014-01-07 12:43:27 -08001196
1197#ifdef CONFIG_CIR_ALWAYS_READY
1198 this_client,
1199#endif
Flemmard0604a8e2013-05-23 16:15:48 -07001200 &pdata->accel,
1201 "accelirq");
1202 if (res)
1203 goto out_accelirq_failed;
1204 } else {
1205 dev_info(&this_client->adapter->dev,
1206 "Accel irq not needed\n");
1207 }
1208 } else {
1209 dev_warn(&this_client->adapter->dev,
1210 "%s: No Accel Present\n", MPU_NAME);
1211 }
1212
1213 if (pdata->compass.get_slave_descr) {
1214 mldl_cfg->compass =
1215 pdata->compass.get_slave_descr();
1216 dev_info(&this_client->adapter->dev,
1217 "%s: +%s\n", MPU_NAME,
1218 mldl_cfg->compass->name);
1219 compass_adapter =
1220 i2c_get_adapter(pdata->compass.adapt_num);
1221 if (pdata->compass.irq > 0) {
1222 dev_info(&this_client->adapter->dev,
1223 "Installing Compass irq using %d\n",
1224 pdata->compass.irq);
1225 res = slaveirq_init(compass_adapter,
Flemmard8923f4a2014-01-07 12:43:27 -08001226#ifdef CONFIG_CIR_ALWAYS_READY
1227 NULL,
1228#endif
Flemmard0604a8e2013-05-23 16:15:48 -07001229 &pdata->compass,
1230 "compassirq");
1231 if (res)
1232 goto out_compassirq_failed;
1233 } else {
1234 dev_info(&this_client->adapter->dev,
1235 "Compass irq not needed\n");
1236 }
1237 } else {
1238 dev_warn(&this_client->adapter->dev,
1239 "%s: No Compass Present\n", MPU_NAME);
1240 }
1241
1242 if (pdata->pressure.get_slave_descr) {
1243 mldl_cfg->pressure =
1244 pdata->pressure.get_slave_descr();
1245 dev_info(&this_client->adapter->dev,
1246 "%s: +%s\n", MPU_NAME,
1247 mldl_cfg->pressure->name);
1248 pressure_adapter =
1249 i2c_get_adapter(pdata->pressure.adapt_num);
1250
1251 if (pdata->pressure.irq > 0) {
1252 dev_info(&this_client->adapter->dev,
1253 "Installing Pressure irq using %d\n",
1254 pdata->pressure.irq);
1255 res = slaveirq_init(pressure_adapter,
Flemmard8923f4a2014-01-07 12:43:27 -08001256#ifdef CONFIG_CIR_ALWAYS_READY
1257 NULL,
1258#endif
Flemmard0604a8e2013-05-23 16:15:48 -07001259 &pdata->pressure,
1260 "pressureirq");
1261 if (res)
1262 goto out_pressureirq_failed;
1263 } else {
1264 dev_warn(&this_client->adapter->dev,
1265 "WARNING: Pressure irq not assigned\n");
1266 }
1267 } else {
1268 dev_info(&this_client->adapter->dev,
1269 "%s: No Pressure Present\n", MPU_NAME);
1270 }
1271 }
1272
1273 mldl_cfg->addr = client->addr;
1274 res = mpu3050_open(&mpu->mldl_cfg, client->adapter,
1275 accel_adapter, compass_adapter, pressure_adapter);
1276
1277 if (res) {
1278 dev_err(&this_client->adapter->dev,
1279 "[mpu_err] Unable to open %s %d\n", MPU_NAME, res);
1280 res = -ENODEV;
1281 goto out_whoami_failed;
1282 }
1283
1284 g_handler = client->adapter;
1285
1286 res = misc_register(&i2c_mpu_device);
1287 if (res < 0) {
1288 dev_err(&this_client->adapter->dev,
1289 "[mpu_err] ERROR: misc_register returned %d\n", res);
1290 goto out_misc_register_failed;
1291 }
1292
1293 if (this_client->irq > 0) {
1294 dev_info(&this_client->adapter->dev,
1295 "Installing irq using %d\n", this_client->irq);
1296 res = mpuirq_init(this_client);
1297 if (res)
1298 goto out_mpuirq_failed;
1299 } else {
1300 dev_warn(&this_client->adapter->dev,
1301 "WARNING: %s irq not assigned\n", MPU_NAME);
1302 }
1303
1304
1305#ifdef CONFIG_HAS_EARLYSUSPEND
1306 mpu->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
1307 mpu->early_suspend.suspend = mpu3050_early_suspend;
1308 mpu->early_suspend.resume = mpu3050_early_resume;
1309 register_early_suspend(&mpu->early_suspend);
1310#endif
1311
1312 mpu3050_class = class_create(THIS_MODULE, "gyro_sensors");
1313 if (IS_ERR(mpu3050_class)) {
1314 res = PTR_ERR(mpu3050_class);
1315 mpu3050_class = NULL;
1316 E("%s, create mpu3050_class fail!\n", __func__);
1317 goto out_mpuirq_failed;
1318 }
1319
1320 mpu3050_dev = device_create(mpu3050_class,
1321 NULL, 0, "%s", "gyro");
1322 if (unlikely(IS_ERR(mpu3050_dev))) {
1323 res = PTR_ERR(mpu3050_dev);
1324 mpu3050_dev = NULL;
1325 E("%s, create mpu3050_dev fail!\n", __func__);
1326 goto err_create_mpu_device;
1327 }
1328
1329
1330 res = device_create_file(mpu3050_dev, &dev_attr_pwr_reg);
1331 if (res) {
1332 E("%s, create mpu3050_device_create_file fail!\n", __func__);
1333 goto err_create_mpu_device_file;
1334 }
1335
1336
1337 res = device_create_file(mpu3050_dev, &dev_attr_mpu_debug_flag);
1338 if (res) {
1339 E("%s, create mpu3050_device_create_file fail!\n", __func__);
1340 goto err_create_mpu_device_mpu_debug_flag_file;
1341 }
1342
1343
1344 res = device_create_file(mpu3050_dev, &dev_attr_mpu_sensors_reset);
1345 if (res) {
1346 E("%s, create mpu3050_device_create_file fail!\n", __func__);
1347 goto err_create_mpu_device_sensors_reset_flag_file;
1348 }
1349
1350
1351 res = device_create_file(mpu3050_dev, &dev_attr_mpu_lpm_flag);
1352 if (res) {
1353 E("%s, create mpu3050_device_create_file fail!\n", __func__);
1354 goto err_create_mpu_device_mpu_lpm_flag_file;
1355 }
1356
1357 mpu_debug_flag = 0;
1358 mpu_sensors_reset = 0;
1359 mpu_lpm_flag = 0;
Flemmard8923f4a2014-01-07 12:43:27 -08001360 D("%s: MPU3050 probe success v02-Fix set ODR G-Sensor issue\n",
1361 __func__);
Flemmard0604a8e2013-05-23 16:15:48 -07001362
1363 return res;
1364
1365err_create_mpu_device_mpu_lpm_flag_file:
1366 device_remove_file(mpu3050_dev, &dev_attr_mpu_sensors_reset);
1367err_create_mpu_device_sensors_reset_flag_file:
1368 device_remove_file(mpu3050_dev, &dev_attr_mpu_debug_flag);
1369err_create_mpu_device_mpu_debug_flag_file:
1370 device_remove_file(mpu3050_dev, &dev_attr_pwr_reg);
1371err_create_mpu_device_file:
1372 device_unregister(mpu3050_dev);
1373err_create_mpu_device:
1374 class_destroy(mpu3050_class);
1375out_mpuirq_failed:
1376 misc_deregister(&i2c_mpu_device);
1377out_misc_register_failed:
1378 mpu3050_close(&mpu->mldl_cfg, client->adapter,
1379 accel_adapter, compass_adapter, pressure_adapter);
1380out_whoami_failed:
1381 if (pdata &&
1382 pdata->pressure.get_slave_descr &&
1383 pdata->pressure.irq)
1384 slaveirq_exit(&pdata->pressure);
1385out_pressureirq_failed:
1386 if (pdata &&
1387 pdata->compass.get_slave_descr &&
1388 pdata->compass.irq)
1389 slaveirq_exit(&pdata->compass);
1390out_compassirq_failed:
1391 if (pdata &&
1392 pdata->accel.get_slave_descr &&
1393 pdata->accel.irq)
1394 slaveirq_exit(&pdata->accel);
1395out_accelirq_failed:
1396 kfree(mpu);
1397out_alloc_data_failed:
1398out_check_functionality_failed:
1399 dev_err(&this_client->adapter->dev, "[mpu_err]%s failed %d\n", __func__,
1400 res);
1401 return res;
1402
1403}
1404
1405static int mpu3050_remove(struct i2c_client *client)
1406{
1407 struct mpu_private_data *mpu = i2c_get_clientdata(client);
1408 struct i2c_adapter *accel_adapter;
1409 struct i2c_adapter *compass_adapter;
1410 struct i2c_adapter *pressure_adapter;
1411 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
1412 struct mpu3050_platform_data *pdata = mldl_cfg->pdata;
1413
1414 accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
1415 compass_adapter =
1416 i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
1417 pressure_adapter =
1418 i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
1419
1420 dev_dbg(&client->adapter->dev, "%s\n", __func__);
1421
1422#ifdef CONFIG_HAS_EARLYSUSPEND
1423 unregister_early_suspend(&mpu->early_suspend);
1424#endif
1425 mpu3050_close(mldl_cfg, client->adapter,
1426 accel_adapter, compass_adapter, pressure_adapter);
1427
1428 if (client->irq)
1429 mpuirq_exit();
1430
1431 if (pdata &&
1432 pdata->pressure.get_slave_descr &&
1433 pdata->pressure.irq)
1434 slaveirq_exit(&pdata->pressure);
1435
1436 if (pdata &&
1437 pdata->compass.get_slave_descr &&
1438 pdata->compass.irq)
1439 slaveirq_exit(&pdata->compass);
1440
1441 if (pdata &&
1442 pdata->accel.get_slave_descr &&
1443 pdata->accel.irq)
1444 slaveirq_exit(&pdata->accel);
1445
1446 misc_deregister(&i2c_mpu_device);
1447 kfree(mpu);
1448
1449 return 0;
1450}
1451
1452static const struct i2c_device_id mpu3050_id[] = {
1453 {MPU_NAME, 0},
1454 {}
1455};
1456
1457MODULE_DEVICE_TABLE(i2c, mpu3050_id);
1458
1459static struct i2c_driver mpu3050_driver = {
1460 .class = I2C_CLASS_HWMON,
1461 .probe = mpu3050_probe,
1462 .remove = mpu3050_remove,
1463 .id_table = mpu3050_id,
1464 .driver = {
1465 .owner = THIS_MODULE,
1466 .name = MPU_NAME,
1467 },
1468 .address_list = normal_i2c,
1469 .shutdown = mpu_shutdown,
1470 .suspend = mpu_suspend,
1471 .resume = mpu_resume,
1472
1473};
1474
1475static int __init mpu_init(void)
1476{
1477 int res = i2c_add_driver(&mpu3050_driver);
1478 pid = 0;
1479 printk(KERN_DEBUG "%s\n", __func__);
1480 if (res)
1481 dev_err(&this_client->adapter->dev, "[mpu_err]%s failed\n",
1482 __func__);
1483 return res;
1484}
1485
1486static void __exit mpu_exit(void)
1487{
1488 printk(KERN_DEBUG "%s\n", __func__);
1489 i2c_del_driver(&mpu3050_driver);
1490}
1491
1492module_init(mpu_init);
1493module_exit(mpu_exit);
1494
1495MODULE_AUTHOR("Invensense Corporation");
1496MODULE_DESCRIPTION("User space character device interface for MPU3050");
1497MODULE_LICENSE("GPL");
1498MODULE_ALIAS(MPU_NAME);