aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/inv_mpu/mpu6050/mpu-dev.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/misc/inv_mpu/mpu6050/mpu-dev.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/misc/inv_mpu/mpu6050/mpu-dev.c')
-rw-r--r--drivers/misc/inv_mpu/mpu6050/mpu-dev.c1309
1 files changed, 1309 insertions, 0 deletions
diff --git a/drivers/misc/inv_mpu/mpu6050/mpu-dev.c b/drivers/misc/inv_mpu/mpu6050/mpu-dev.c
new file mode 100644
index 00000000000..e171dc2a7ef
--- /dev/null
+++ b/drivers/misc/inv_mpu/mpu6050/mpu-dev.c
@@ -0,0 +1,1309 @@
1/*
2 $License:
3 Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 $
18 */
19#include <linux/i2c.h>
20#include <linux/i2c-dev.h>
21#include <linux/interrupt.h>
22#include <linux/module.h>
23#include <linux/moduleparam.h>
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/stat.h>
27#include <linux/irq.h>
28#include <linux/gpio.h>
29#include <linux/signal.h>
30#include <linux/miscdevice.h>
31#include <linux/slab.h>
32#include <linux/version.h>
33#include <linux/pm.h>
34#include <linux/mutex.h>
35#include <linux/suspend.h>
36#include <linux/poll.h>
37
38#include <linux/errno.h>
39#include <linux/fs.h>
40#include <linux/mm.h>
41#include <linux/sched.h>
42#include <linux/wait.h>
43#include <linux/uaccess.h>
44#include <linux/io.h>
45
46#include "mpuirq.h"
47#include "slaveirq.h"
48#include "mlsl.h"
49#include "mldl_cfg.h"
50#include <linux/mpu.h>
51
52#include "accel/mpu6050.h"
53
54/* Platform data for the MPU */
55struct mpu_private_data {
56 struct miscdevice dev;
57 struct i2c_client *client;
58
59 /* mldl_cfg data */
60 struct mldl_cfg mldl_cfg;
61 struct mpu_ram mpu_ram;
62 struct mpu_gyro_cfg mpu_gyro_cfg;
63 struct mpu_offsets mpu_offsets;
64 struct mpu_chip_info mpu_chip_info;
65 struct inv_mpu_cfg inv_mpu_cfg;
66 struct inv_mpu_state inv_mpu_state;
67
68 struct mutex mutex;
69 wait_queue_head_t mpu_event_wait;
70 struct completion completion;
71 struct timer_list timeout;
72 struct notifier_block nb;
73 struct mpuirq_data mpu_pm_event;
74 int response_timeout; /* In seconds */
75 unsigned long event;
76 int pid;
77 struct module *slave_modules[EXT_SLAVE_NUM_TYPES];
78};
79
80struct mpu_private_data *mpu_private_data;
81
82static void mpu_pm_timeout(u_long data)
83{
84 struct mpu_private_data *mpu = (struct mpu_private_data *)data;
85 struct i2c_client *client = mpu->client;
86 dev_dbg(&client->adapter->dev, "%s\n", __func__);
87 complete(&mpu->completion);
88}
89
90static int mpu_pm_notifier_callback(struct notifier_block *nb,
91 unsigned long event, void *unused)
92{
93 struct mpu_private_data *mpu =
94 container_of(nb, struct mpu_private_data, nb);
95 struct i2c_client *client = mpu->client;
96 struct timeval event_time;
97 dev_dbg(&client->adapter->dev, "%s: %ld\n", __func__, event);
98
99 /* Prevent the file handle from being closed before we initialize
100 the completion event */
101 mutex_lock(&mpu->mutex);
102 if (!(mpu->pid) ||
103 (event != PM_SUSPEND_PREPARE && event != PM_POST_SUSPEND)) {
104 mutex_unlock(&mpu->mutex);
105 return NOTIFY_OK;
106 }
107
108 if (event == PM_SUSPEND_PREPARE)
109 mpu->event = MPU_PM_EVENT_SUSPEND_PREPARE;
110 if (event == PM_POST_SUSPEND)
111 mpu->event = MPU_PM_EVENT_POST_SUSPEND;
112
113 do_gettimeofday(&event_time);
114 mpu->mpu_pm_event.interruptcount++;
115 mpu->mpu_pm_event.irqtime =
116 (((long long)event_time.tv_sec) << 32) + event_time.tv_usec;
117 mpu->mpu_pm_event.data_type = MPUIRQ_DATA_TYPE_PM_EVENT;
118 mpu->mpu_pm_event.data = mpu->event;
119
120 if (mpu->response_timeout > 0) {
121 mpu->timeout.expires = jiffies + mpu->response_timeout * HZ;
122 add_timer(&mpu->timeout);
123 }
124 INIT_COMPLETION(mpu->completion);
125 mutex_unlock(&mpu->mutex);
126
127 wake_up_interruptible(&mpu->mpu_event_wait);
128 wait_for_completion(&mpu->completion);
129 del_timer_sync(&mpu->timeout);
130 dev_dbg(&client->adapter->dev, "%s: %ld DONE\n", __func__, event);
131 return NOTIFY_OK;
132}
133
134static int mpu_dev_open(struct inode *inode, struct file *file)
135{
136 struct mpu_private_data *mpu =
137 container_of(file->private_data, struct mpu_private_data, dev);
138 struct i2c_client *client = mpu->client;
139 int result;
140 int ii;
141 dev_dbg(&client->adapter->dev, "%s\n", __func__);
142 dev_dbg(&client->adapter->dev, "current->pid %d\n", current->pid);
143
144 result = mutex_lock_interruptible(&mpu->mutex);
145 if (mpu->pid) {
146 mutex_unlock(&mpu->mutex);
147 return -EBUSY;
148 }
149 mpu->pid = current->pid;
150
151 /* Reset the sensors to the default */
152 if (result) {
153 dev_err(&client->adapter->dev,
154 "%s: mutex_lock_interruptible returned %d\n",
155 __func__, result);
156 return result;
157 }
158
159 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++)
160 __module_get(mpu->slave_modules[ii]);
161
162 mutex_unlock(&mpu->mutex);
163 return 0;
164}
165
166/* close function - called when the "file" /dev/mpu is closed in userspace */
167static int mpu_release(struct inode *inode, struct file *file)
168{
169 struct mpu_private_data *mpu =
170 container_of(file->private_data, struct mpu_private_data, dev);
171 struct i2c_client *client = mpu->client;
172 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
173 int result = 0;
174 int ii;
175 struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
176 struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
177
178 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
179 if (!pdata_slave[ii])
180 slave_adapter[ii] = NULL;
181 else
182 slave_adapter[ii] =
183 i2c_get_adapter(pdata_slave[ii]->adapt_num);
184 }
185 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
186
187 mutex_lock(&mpu->mutex);
188 mldl_cfg->inv_mpu_cfg->requested_sensors = 0;
189 result = inv_mpu_suspend(mldl_cfg,
190 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
191 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
192 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
193 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
194 INV_ALL_SENSORS);
195 mpu->pid = 0;
196 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++)
197 module_put(mpu->slave_modules[ii]);
198
199 mutex_unlock(&mpu->mutex);
200 complete(&mpu->completion);
201 dev_dbg(&client->adapter->dev, "mpu_release\n");
202
203 return result;
204}
205
206/* read function called when from /dev/mpu is read. Read from the FIFO */
207static ssize_t mpu_read(struct file *file,
208 char __user *buf, size_t count, loff_t *offset)
209{
210 struct mpu_private_data *mpu =
211 container_of(file->private_data, struct mpu_private_data, dev);
212 struct i2c_client *client = mpu->client;
213 size_t len = sizeof(mpu->mpu_pm_event) + sizeof(unsigned long);
214 int err;
215
216 if (!mpu->event && (!(file->f_flags & O_NONBLOCK)))
217 wait_event_interruptible(mpu->mpu_event_wait, mpu->event);
218
219 if (!mpu->event || !buf
220 || count < sizeof(mpu->mpu_pm_event))
221 return 0;
222
223 err = copy_to_user(buf, &mpu->mpu_pm_event, sizeof(mpu->mpu_pm_event));
224 if (err) {
225 dev_err(&client->adapter->dev,
226 "Copy to user returned %d\n", err);
227 return -EFAULT;
228 }
229 mpu->event = 0;
230 return len;
231}
232
233static unsigned int mpu_poll(struct file *file, struct poll_table_struct *poll)
234{
235 struct mpu_private_data *mpu =
236 container_of(file->private_data, struct mpu_private_data, dev);
237 int mask = 0;
238
239 poll_wait(file, &mpu->mpu_event_wait, poll);
240 if (mpu->event)
241 mask |= POLLIN | POLLRDNORM;
242 return mask;
243}
244
245static int mpu_dev_ioctl_get_ext_slave_platform_data(
246 struct i2c_client *client,
247 struct ext_slave_platform_data __user *arg)
248{
249 struct mpu_private_data *mpu =
250 (struct mpu_private_data *)i2c_get_clientdata(client);
251 struct ext_slave_platform_data *pdata_slave;
252 struct ext_slave_platform_data local_pdata_slave;
253
254 if (copy_from_user(&local_pdata_slave, arg, sizeof(local_pdata_slave)))
255 return -EFAULT;
256
257 if (local_pdata_slave.type >= EXT_SLAVE_NUM_TYPES)
258 return -EINVAL;
259
260 pdata_slave = mpu->mldl_cfg.pdata_slave[local_pdata_slave.type];
261 /* All but private data and irq_data */
262 if (!pdata_slave)
263 return -ENODEV;
264 if (copy_to_user(arg, pdata_slave, sizeof(*pdata_slave)))
265 return -EFAULT;
266 return 0;
267}
268
269static int mpu_dev_ioctl_get_mpu_platform_data(
270 struct i2c_client *client,
271 struct mpu_platform_data __user *arg)
272{
273 struct mpu_private_data *mpu =
274 (struct mpu_private_data *)i2c_get_clientdata(client);
275 struct mpu_platform_data *pdata = mpu->mldl_cfg.pdata;
276
277 if (copy_to_user(arg, pdata, sizeof(*pdata)))
278 return -EFAULT;
279 return 0;
280}
281
282static int mpu_dev_ioctl_get_ext_slave_descr(
283 struct i2c_client *client,
284 struct ext_slave_descr __user *arg)
285{
286 struct mpu_private_data *mpu =
287 (struct mpu_private_data *)i2c_get_clientdata(client);
288 struct ext_slave_descr *slave;
289 struct ext_slave_descr local_slave;
290
291 if (copy_from_user(&local_slave, arg, sizeof(local_slave)))
292 return -EFAULT;
293
294 if (local_slave.type >= EXT_SLAVE_NUM_TYPES)
295 return -EINVAL;
296
297 slave = mpu->mldl_cfg.slave[local_slave.type];
298 /* All but private data and irq_data */
299 if (!slave)
300 return -ENODEV;
301 if (copy_to_user(arg, slave, sizeof(*slave)))
302 return -EFAULT;
303 return 0;
304}
305
306
307/**
308 * slave_config() - Pass a requested slave configuration to the slave sensor
309 *
310 * @adapter the adaptor to use to communicate with the slave
311 * @mldl_cfg the mldl configuration structuer
312 * @slave pointer to the slave descriptor
313 * @usr_config The configuration to pass to the slave sensor
314 *
315 * returns 0 or non-zero error code
316 */
317static int inv_mpu_config(struct mldl_cfg *mldl_cfg,
318 void *gyro_adapter,
319 struct ext_slave_config __user *usr_config)
320{
321 int retval = 0;
322 struct ext_slave_config config;
323
324 retval = copy_from_user(&config, usr_config, sizeof(config));
325 if (retval)
326 return -EFAULT;
327
328 if (config.len && config.data) {
329 void *data;
330 data = kmalloc(config.len, GFP_KERNEL);
331 if (!data)
332 return -ENOMEM;
333
334 retval = copy_from_user(data,
335 (void __user *)config.data, config.len);
336 if (retval) {
337 retval = -EFAULT;
338 kfree(data);
339 return retval;
340 }
341 config.data = data;
342 }
343 retval = gyro_config(gyro_adapter, mldl_cfg, &config);
344 kfree(config.data);
345 return retval;
346}
347
348static int inv_mpu_get_config(struct mldl_cfg *mldl_cfg,
349 void *gyro_adapter,
350 struct ext_slave_config __user *usr_config)
351{
352 int retval = 0;
353 struct ext_slave_config config;
354 void *user_data;
355
356 retval = copy_from_user(&config, usr_config, sizeof(config));
357 if (retval)
358 return -EFAULT;
359
360 user_data = config.data;
361 if (config.len && config.data) {
362 void *data;
363 data = kmalloc(config.len, GFP_KERNEL);
364 if (!data)
365 return -ENOMEM;
366
367 retval = copy_from_user(data,
368 (void __user *)config.data, config.len);
369 if (retval) {
370 retval = -EFAULT;
371 kfree(data);
372 return retval;
373 }
374 config.data = data;
375 }
376 retval = gyro_get_config(gyro_adapter, mldl_cfg, &config);
377 if (!retval)
378 retval = copy_to_user((unsigned char __user *)user_data,
379 config.data, config.len);
380 kfree(config.data);
381 return retval;
382}
383
384static int slave_config(struct mldl_cfg *mldl_cfg,
385 void *gyro_adapter,
386 void *slave_adapter,
387 struct ext_slave_descr *slave,
388 struct ext_slave_platform_data *pdata,
389 struct ext_slave_config __user *usr_config)
390{
391 int retval = 0;
392 struct ext_slave_config config;
393 if ((!slave) || (!slave->config))
394 return -ENODEV;
395
396 retval = copy_from_user(&config, usr_config, sizeof(config));
397 if (retval)
398 return -EFAULT;
399
400 if (config.len && config.data) {
401 void *data;
402 data = kmalloc(config.len, GFP_KERNEL);
403 if (!data)
404 return -ENOMEM;
405
406 retval = copy_from_user(data,
407 (void __user *)config.data, config.len);
408 if (retval) {
409 retval = -EFAULT;
410 kfree(data);
411 return retval;
412 }
413 config.data = data;
414 }
415 retval = inv_mpu_slave_config(mldl_cfg, gyro_adapter, slave_adapter,
416 &config, slave, pdata);
417 kfree(config.data);
418 return retval;
419}
420
421static int slave_get_config(struct mldl_cfg *mldl_cfg,
422 void *gyro_adapter,
423 void *slave_adapter,
424 struct ext_slave_descr *slave,
425 struct ext_slave_platform_data *pdata,
426 struct ext_slave_config __user *usr_config)
427{
428 int retval = 0;
429 struct ext_slave_config config;
430 void *user_data;
431 if (!(slave) || !(slave->get_config))
432 return -ENODEV;
433
434 retval = copy_from_user(&config, usr_config, sizeof(config));
435 if (retval)
436 return -EFAULT;
437
438 user_data = config.data;
439 if (config.len && config.data) {
440 void *data;
441 data = kmalloc(config.len, GFP_KERNEL);
442 if (!data)
443 return -ENOMEM;
444
445 retval = copy_from_user(data,
446 (void __user *)config.data, config.len);
447 if (retval) {
448 retval = -EFAULT;
449 kfree(data);
450 return retval;
451 }
452 config.data = data;
453 }
454 retval = inv_mpu_get_slave_config(mldl_cfg, gyro_adapter,
455 slave_adapter, &config, slave, pdata);
456 if (retval) {
457 kfree(config.data);
458 return retval;
459 }
460 retval = copy_to_user((unsigned char __user *)user_data,
461 config.data, config.len);
462 kfree(config.data);
463 return retval;
464}
465
466static int inv_slave_read(struct mldl_cfg *mldl_cfg,
467 void *gyro_adapter,
468 void *slave_adapter,
469 struct ext_slave_descr *slave,
470 struct ext_slave_platform_data *pdata,
471 void __user *usr_data)
472{
473 int retval;
474 unsigned char *data;
475 data = kzalloc(slave->read_len, GFP_KERNEL);
476 if (!data)
477 return -EFAULT;
478
479 retval = inv_mpu_slave_read(mldl_cfg, gyro_adapter, slave_adapter,
480 slave, pdata, data);
481
482 if ((!retval) &&
483 (copy_to_user((unsigned char __user *)usr_data,
484 data, slave->read_len)))
485 retval = -EFAULT;
486
487 kfree(data);
488 return retval;
489}
490
491static int mpu_handle_mlsl(void *sl_handle,
492 unsigned char addr,
493 unsigned int cmd,
494 struct mpu_read_write __user *usr_msg)
495{
496 int retval = 0;
497 struct mpu_read_write msg;
498 unsigned char *user_data;
499 retval = copy_from_user(&msg, usr_msg, sizeof(msg));
500 if (retval)
501 return -EFAULT;
502
503 user_data = msg.data;
504 if (msg.length && msg.data) {
505 unsigned char *data;
506 data = kmalloc(msg.length, GFP_KERNEL);
507 if (!data)
508 return -ENOMEM;
509
510 retval = copy_from_user(data,
511 (void __user *)msg.data, msg.length);
512 if (retval) {
513 retval = -EFAULT;
514 kfree(data);
515 return retval;
516 }
517 msg.data = data;
518 } else {
519 return -EPERM;
520 }
521
522 switch (cmd) {
523 case MPU_READ:
524 retval = inv_serial_read(sl_handle, addr,
525 msg.address, msg.length, msg.data);
526 break;
527 case MPU_WRITE:
528 retval = inv_serial_write(sl_handle, addr,
529 msg.length, msg.data);
530 break;
531 case MPU_READ_MEM:
532 retval = inv_serial_read_mem(sl_handle, addr,
533 msg.address, msg.length, msg.data);
534 break;
535 case MPU_WRITE_MEM:
536 retval = inv_serial_write_mem(sl_handle, addr,
537 msg.address, msg.length,
538 msg.data);
539 break;
540 case MPU_READ_FIFO:
541 retval = inv_serial_read_fifo(sl_handle, addr,
542 msg.length, msg.data);
543 break;
544 case MPU_WRITE_FIFO:
545 retval = inv_serial_write_fifo(sl_handle, addr,
546 msg.length, msg.data);
547 break;
548
549 };
550 if (retval) {
551 dev_err(&((struct i2c_adapter *)sl_handle)->dev,
552 "%s: i2c %d error %d\n",
553 __func__, cmd, retval);
554 kfree(msg.data);
555 return retval;
556 }
557 retval = copy_to_user((unsigned char __user *)user_data,
558 msg.data, msg.length);
559 kfree(msg.data);
560 return retval;
561}
562
563/* ioctl - I/O control */
564static long mpu_dev_ioctl(struct file *file,
565 unsigned int cmd, unsigned long arg)
566{
567 struct mpu_private_data *mpu =
568 container_of(file->private_data, struct mpu_private_data, dev);
569 struct i2c_client *client = mpu->client;
570 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
571 int retval = 0;
572 struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
573 struct ext_slave_descr **slave = mldl_cfg->slave;
574 struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
575 int ii;
576
577 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
578 if (!pdata_slave[ii])
579 slave_adapter[ii] = NULL;
580 else
581 slave_adapter[ii] =
582 i2c_get_adapter(pdata_slave[ii]->adapt_num);
583 }
584 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
585
586 retval = mutex_lock_interruptible(&mpu->mutex);
587 if (retval) {
588 dev_err(&client->adapter->dev,
589 "%s: mutex_lock_interruptible returned %d\n",
590 __func__, retval);
591 return retval;
592 }
593
594 switch (cmd) {
595 case MPU_GET_EXT_SLAVE_PLATFORM_DATA:
596 retval = mpu_dev_ioctl_get_ext_slave_platform_data(
597 client,
598 (struct ext_slave_platform_data __user *)arg);
599 break;
600 case MPU_GET_MPU_PLATFORM_DATA:
601 retval = mpu_dev_ioctl_get_mpu_platform_data(
602 client,
603 (struct mpu_platform_data __user *)arg);
604 break;
605 case MPU_GET_EXT_SLAVE_DESCR:
606 retval = mpu_dev_ioctl_get_ext_slave_descr(
607 client,
608 (struct ext_slave_descr __user *)arg);
609 break;
610 case MPU_READ:
611 case MPU_WRITE:
612 case MPU_READ_MEM:
613 case MPU_WRITE_MEM:
614 case MPU_READ_FIFO:
615 case MPU_WRITE_FIFO:
616 retval = mpu_handle_mlsl(
617 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
618 mldl_cfg->mpu_chip_info->addr, cmd,
619 (struct mpu_read_write __user *)arg);
620 break;
621 case MPU_CONFIG_GYRO:
622 retval = inv_mpu_config(
623 mldl_cfg,
624 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
625 (struct ext_slave_config __user *)arg);
626 break;
627 case MPU_CONFIG_ACCEL:
628 retval = slave_config(
629 mldl_cfg,
630 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
631 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
632 slave[EXT_SLAVE_TYPE_ACCEL],
633 pdata_slave[EXT_SLAVE_TYPE_ACCEL],
634 (struct ext_slave_config __user *)arg);
635 break;
636 case MPU_CONFIG_COMPASS:
637 retval = slave_config(
638 mldl_cfg,
639 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
640 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
641 slave[EXT_SLAVE_TYPE_COMPASS],
642 pdata_slave[EXT_SLAVE_TYPE_COMPASS],
643 (struct ext_slave_config __user *)arg);
644 break;
645 case MPU_CONFIG_PRESSURE:
646 retval = slave_config(
647 mldl_cfg,
648 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
649 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
650 slave[EXT_SLAVE_TYPE_PRESSURE],
651 pdata_slave[EXT_SLAVE_TYPE_PRESSURE],
652 (struct ext_slave_config __user *)arg);
653 break;
654 case MPU_GET_CONFIG_GYRO:
655 retval = inv_mpu_get_config(
656 mldl_cfg,
657 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
658 (struct ext_slave_config __user *)arg);
659 break;
660 case MPU_GET_CONFIG_ACCEL:
661 retval = slave_get_config(
662 mldl_cfg,
663 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
664 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
665 slave[EXT_SLAVE_TYPE_ACCEL],
666 pdata_slave[EXT_SLAVE_TYPE_ACCEL],
667 (struct ext_slave_config __user *)arg);
668 break;
669 case MPU_GET_CONFIG_COMPASS:
670 retval = slave_get_config(
671 mldl_cfg,
672 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
673 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
674 slave[EXT_SLAVE_TYPE_COMPASS],
675 pdata_slave[EXT_SLAVE_TYPE_COMPASS],
676 (struct ext_slave_config __user *)arg);
677 break;
678 case MPU_GET_CONFIG_PRESSURE:
679 retval = slave_get_config(
680 mldl_cfg,
681 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
682 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
683 slave[EXT_SLAVE_TYPE_PRESSURE],
684 pdata_slave[EXT_SLAVE_TYPE_PRESSURE],
685 (struct ext_slave_config __user *)arg);
686 break;
687 case MPU_SUSPEND:
688 retval = inv_mpu_suspend(
689 mldl_cfg,
690 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
691 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
692 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
693 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
694 arg);
695 break;
696 case MPU_RESUME:
697 retval = inv_mpu_resume(
698 mldl_cfg,
699 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
700 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
701 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
702 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
703 arg);
704 break;
705 case MPU_PM_EVENT_HANDLED:
706 dev_dbg(&client->adapter->dev, "%s: %d\n", __func__, cmd);
707 complete(&mpu->completion);
708 break;
709 case MPU_READ_ACCEL:
710 retval = inv_slave_read(
711 mldl_cfg,
712 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
713 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
714 slave[EXT_SLAVE_TYPE_ACCEL],
715 pdata_slave[EXT_SLAVE_TYPE_ACCEL],
716 (unsigned char __user *)arg);
717 break;
718 case MPU_READ_COMPASS:
719 retval = inv_slave_read(
720 mldl_cfg,
721 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
722 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
723 slave[EXT_SLAVE_TYPE_COMPASS],
724 pdata_slave[EXT_SLAVE_TYPE_COMPASS],
725 (unsigned char __user *)arg);
726 break;
727 case MPU_READ_PRESSURE:
728 retval = inv_slave_read(
729 mldl_cfg,
730 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
731 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
732 slave[EXT_SLAVE_TYPE_PRESSURE],
733 pdata_slave[EXT_SLAVE_TYPE_PRESSURE],
734 (unsigned char __user *)arg);
735 break;
736 case MPU_GET_REQUESTED_SENSORS:
737 if (copy_to_user(
738 (__u32 __user *)arg,
739 &mldl_cfg->inv_mpu_cfg->requested_sensors,
740 sizeof(mldl_cfg->inv_mpu_cfg->requested_sensors)))
741 retval = -EFAULT;
742 break;
743 case MPU_SET_REQUESTED_SENSORS:
744 mldl_cfg->inv_mpu_cfg->requested_sensors = arg;
745 break;
746 case MPU_GET_IGNORE_SYSTEM_SUSPEND:
747 if (copy_to_user(
748 (unsigned char __user *)arg,
749 &mldl_cfg->inv_mpu_cfg->ignore_system_suspend,
750 sizeof(mldl_cfg->inv_mpu_cfg->ignore_system_suspend)))
751 retval = -EFAULT;
752 break;
753 case MPU_SET_IGNORE_SYSTEM_SUSPEND:
754 mldl_cfg->inv_mpu_cfg->ignore_system_suspend = arg;
755 break;
756 case MPU_GET_MLDL_STATUS:
757 if (copy_to_user(
758 (unsigned char __user *)arg,
759 &mldl_cfg->inv_mpu_state->status,
760 sizeof(mldl_cfg->inv_mpu_state->status)))
761 retval = -EFAULT;
762 break;
763 case MPU_GET_I2C_SLAVES_ENABLED:
764 if (copy_to_user(
765 (unsigned char __user *)arg,
766 &mldl_cfg->inv_mpu_state->i2c_slaves_enabled,
767 sizeof(mldl_cfg->inv_mpu_state->i2c_slaves_enabled)))
768 retval = -EFAULT;
769 break;
770 default:
771 dev_err(&client->adapter->dev,
772 "%s: Unknown cmd %x, arg %lu\n",
773 __func__, cmd, arg);
774 retval = -EINVAL;
775 };
776
777 mutex_unlock(&mpu->mutex);
778 dev_dbg(&client->adapter->dev, "%s: %08x, %08lx, %d\n",
779 __func__, cmd, arg, retval);
780
781 if (retval > 0)
782 retval = -retval;
783
784 return retval;
785}
786
787void mpu_shutdown(struct i2c_client *client)
788{
789 struct mpu_private_data *mpu =
790 (struct mpu_private_data *)i2c_get_clientdata(client);
791 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
792 struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
793 struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
794 int ii;
795
796 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
797 if (!pdata_slave[ii])
798 slave_adapter[ii] = NULL;
799 else
800 slave_adapter[ii] =
801 i2c_get_adapter(pdata_slave[ii]->adapt_num);
802 }
803 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
804
805 mutex_lock(&mpu->mutex);
806 (void)inv_mpu_suspend(mldl_cfg,
807 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
808 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
809 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
810 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
811 INV_ALL_SENSORS);
812 mutex_unlock(&mpu->mutex);
813 dev_dbg(&client->adapter->dev, "%s\n", __func__);
814}
815
816int mpu_dev_suspend(struct i2c_client *client, pm_message_t mesg)
817{
818 struct mpu_private_data *mpu =
819 (struct mpu_private_data *)i2c_get_clientdata(client);
820 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
821 struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
822 struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
823 int ii;
824
825 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
826 if (!pdata_slave[ii])
827 slave_adapter[ii] = NULL;
828 else
829 slave_adapter[ii] =
830 i2c_get_adapter(pdata_slave[ii]->adapt_num);
831 }
832 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
833
834 mutex_lock(&mpu->mutex);
835 if (!mldl_cfg->inv_mpu_cfg->ignore_system_suspend) {
836 dev_dbg(&client->adapter->dev,
837 "%s: suspending on event %d\n", __func__, mesg.event);
838 (void)inv_mpu_suspend(mldl_cfg,
839 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
840 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
841 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
842 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
843 INV_ALL_SENSORS);
844 } else {
845 dev_dbg(&client->adapter->dev,
846 "%s: Already suspended %d\n", __func__, mesg.event);
847 }
848 mutex_unlock(&mpu->mutex);
849 return 0;
850}
851
852int mpu_dev_resume(struct i2c_client *client)
853{
854 struct mpu_private_data *mpu =
855 (struct mpu_private_data *)i2c_get_clientdata(client);
856 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
857 struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
858 struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
859 int ii;
860
861 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
862 if (!pdata_slave[ii])
863 slave_adapter[ii] = NULL;
864 else
865 slave_adapter[ii] =
866 i2c_get_adapter(pdata_slave[ii]->adapt_num);
867 }
868 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
869
870 mutex_lock(&mpu->mutex);
871 if (mpu->pid && !mldl_cfg->inv_mpu_cfg->ignore_system_suspend) {
872 (void)inv_mpu_resume(mldl_cfg,
873 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
874 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
875 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
876 slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
877 mldl_cfg->inv_mpu_cfg->requested_sensors);
878 dev_dbg(&client->adapter->dev,
879 "%s for pid %d\n", __func__, mpu->pid);
880 }
881 mutex_unlock(&mpu->mutex);
882 return 0;
883}
884
885/* define which file operations are supported */
886static const struct file_operations mpu_fops = {
887 .owner = THIS_MODULE,
888 .read = mpu_read,
889 .poll = mpu_poll,
890 .unlocked_ioctl = mpu_dev_ioctl,
891 .open = mpu_dev_open,
892 .release = mpu_release,
893};
894
895int inv_mpu_register_slave(struct module *slave_module,
896 struct i2c_client *slave_client,
897 struct ext_slave_platform_data *slave_pdata,
898 struct ext_slave_descr *(*get_slave_descr)(void))
899{
900 struct mpu_private_data *mpu = mpu_private_data;
901 struct mldl_cfg *mldl_cfg;
902 struct ext_slave_descr *slave_descr;
903 struct ext_slave_platform_data **pdata_slave;
904 char *irq_name = NULL;
905 int result = 0;
906
907 if (!slave_client || !slave_pdata || !get_slave_descr)
908 return -EINVAL;
909
910 if (!mpu) {
911 dev_err(&slave_client->adapter->dev,
912 "%s: Null mpu_private_data\n", __func__);
913 return -EINVAL;
914 }
915 mldl_cfg = &mpu->mldl_cfg;
916 pdata_slave = mldl_cfg->pdata_slave;
917 slave_descr = get_slave_descr();
918
919 if (!slave_descr) {
920 dev_err(&slave_client->adapter->dev,
921 "%s: Null ext_slave_descr\n", __func__);
922 return -EINVAL;
923 }
924
925 mutex_lock(&mpu->mutex);
926 if (mpu->pid) {
927 mutex_unlock(&mpu->mutex);
928 return -EBUSY;
929 }
930
931 if (pdata_slave[slave_descr->type]) {
932 result = -EBUSY;
933 goto out_unlock_mutex;
934 }
935
936 slave_pdata->address = slave_client->addr;
937 slave_pdata->irq = slave_client->irq;
938 slave_pdata->adapt_num = i2c_adapter_id(slave_client->adapter);
939
940 dev_info(&slave_client->adapter->dev,
941 "%s: +%s Type %d: Addr: %2x IRQ: %2d, Adapt: %2d\n",
942 __func__,
943 slave_descr->name,
944 slave_descr->type,
945 slave_pdata->address,
946 slave_pdata->irq,
947 slave_pdata->adapt_num);
948
949 switch (slave_descr->type) {
950 case EXT_SLAVE_TYPE_ACCEL:
951 irq_name = "accelirq";
952 break;
953 case EXT_SLAVE_TYPE_COMPASS:
954 irq_name = "compassirq";
955 break;
956 case EXT_SLAVE_TYPE_PRESSURE:
957 irq_name = "pressureirq";
958 break;
959 default:
960 irq_name = "none";
961 };
962 if (slave_descr->init) {
963 result = slave_descr->init(slave_client->adapter,
964 slave_descr,
965 slave_pdata);
966 if (result) {
967 dev_err(&slave_client->adapter->dev,
968 "%s init failed %d\n",
969 slave_descr->name, result);
970 goto out_unlock_mutex;
971 }
972 }
973
974 if (slave_descr->type == EXT_SLAVE_TYPE_ACCEL &&
975 slave_descr->id == ACCEL_ID_MPU6050 &&
976 slave_descr->config) {
977 /* pass a reference to the mldl_cfg data
978 structure to the mpu6050 accel "class" */
979 struct ext_slave_config config;
980 config.key = MPU_SLAVE_CONFIG_INTERNAL_REFERENCE;
981 config.len = sizeof(struct mldl_cfg *);
982 config.apply = true;
983 config.data = mldl_cfg;
984 result = slave_descr->config(
985 slave_client->adapter, slave_descr,
986 slave_pdata, &config);
987 if (result) {
988 LOG_RESULT_LOCATION(result);
989 goto out_slavedescr_exit;
990 }
991 }
992 pdata_slave[slave_descr->type] = slave_pdata;
993 mpu->slave_modules[slave_descr->type] = slave_module;
994 mldl_cfg->slave[slave_descr->type] = slave_descr;
995
996 goto out_unlock_mutex;
997
998out_slavedescr_exit:
999 if (slave_descr->exit)
1000 slave_descr->exit(slave_client->adapter,
1001 slave_descr, slave_pdata);
1002out_unlock_mutex:
1003 mutex_unlock(&mpu->mutex);
1004
1005 if (!result && irq_name && (slave_pdata->irq > 0)) {
1006 int warn_result;
1007 dev_info(&slave_client->adapter->dev,
1008 "Installing %s irq using %d\n",
1009 irq_name,
1010 slave_pdata->irq);
1011 warn_result = slaveirq_init(slave_client->adapter,
1012 slave_pdata, irq_name);
1013 if (result)
1014 dev_WARN(&slave_client->adapter->dev,
1015 "%s irq assigned error: %d\n",
1016 slave_descr->name, warn_result);
1017 } else {
1018 dev_WARN(&slave_client->adapter->dev,
1019 "%s irq not assigned: %d %d %d\n",
1020 slave_descr->name,
1021 result, (int)irq_name, slave_pdata->irq);
1022 }
1023
1024 return result;
1025}
1026EXPORT_SYMBOL(inv_mpu_register_slave);
1027
1028void inv_mpu_unregister_slave(struct i2c_client *slave_client,
1029 struct ext_slave_platform_data *slave_pdata,
1030 struct ext_slave_descr *(*get_slave_descr)(void))
1031{
1032 struct mpu_private_data *mpu = mpu_private_data;
1033 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
1034 struct ext_slave_descr *slave_descr;
1035 int result;
1036
1037 dev_info(&slave_client->adapter->dev, "%s\n", __func__);
1038
1039 if (!slave_client || !slave_pdata || !get_slave_descr)
1040 return;
1041
1042 if (slave_pdata->irq)
1043 slaveirq_exit(slave_pdata);
1044
1045 slave_descr = get_slave_descr();
1046 if (!slave_descr)
1047 return;
1048
1049 mutex_lock(&mpu->mutex);
1050
1051 if (slave_descr->exit) {
1052 result = slave_descr->exit(slave_client->adapter,
1053 slave_descr,
1054 slave_pdata);
1055 if (result)
1056 dev_err(&slave_client->adapter->dev,
1057 "Accel exit failed %d\n", result);
1058 }
1059 mldl_cfg->slave[slave_descr->type] = NULL;
1060 mldl_cfg->pdata_slave[slave_descr->type] = NULL;
1061 mpu->slave_modules[slave_descr->type] = NULL;
1062
1063 mutex_unlock(&mpu->mutex);
1064
1065}
1066EXPORT_SYMBOL(inv_mpu_unregister_slave);
1067
1068static unsigned short normal_i2c[] = { I2C_CLIENT_END };
1069
1070static const struct i2c_device_id mpu_id[] = {
1071 {"mpu3050", 0},
1072 {"mpu6050", 0},
1073 {"mpu6050_no_accel", 0},
1074 {}
1075};
1076MODULE_DEVICE_TABLE(i2c, mpu_id);
1077
1078int mpu_probe(struct i2c_client *client, const struct i2c_device_id *devid)
1079{
1080 struct mpu_platform_data *pdata;
1081 struct mpu_private_data *mpu;
1082 struct mldl_cfg *mldl_cfg;
1083 int res = 0;
1084 int ii = 0;
1085 unsigned long irq_flags;
1086
1087 dev_info(&client->adapter->dev, "%s: %d\n", __func__, ii++);
1088
1089 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1090 res = -ENODEV;
1091 goto out_check_functionality_failed;
1092 }
1093
1094 mpu = kzalloc(sizeof(struct mpu_private_data), GFP_KERNEL);
1095 if (!mpu) {
1096 res = -ENOMEM;
1097 goto out_alloc_data_failed;
1098 }
1099 mldl_cfg = &mpu->mldl_cfg;
1100 mldl_cfg->mpu_ram = &mpu->mpu_ram;
1101 mldl_cfg->mpu_gyro_cfg = &mpu->mpu_gyro_cfg;
1102 mldl_cfg->mpu_offsets = &mpu->mpu_offsets;
1103 mldl_cfg->mpu_chip_info = &mpu->mpu_chip_info;
1104 mldl_cfg->inv_mpu_cfg = &mpu->inv_mpu_cfg;
1105 mldl_cfg->inv_mpu_state = &mpu->inv_mpu_state;
1106
1107 mldl_cfg->mpu_ram->length = MPU_MEM_NUM_RAM_BANKS * MPU_MEM_BANK_SIZE;
1108 mldl_cfg->mpu_ram->ram = kzalloc(mldl_cfg->mpu_ram->length, GFP_KERNEL);
1109 if (!mldl_cfg->mpu_ram->ram) {
1110 res = -ENOMEM;
1111 goto out_alloc_ram_failed;
1112 }
1113 mpu_private_data = mpu;
1114 i2c_set_clientdata(client, mpu);
1115 mpu->client = client;
1116
1117 init_waitqueue_head(&mpu->mpu_event_wait);
1118 mutex_init(&mpu->mutex);
1119 init_completion(&mpu->completion);
1120
1121 mpu->response_timeout = 60; /* Seconds */
1122 mpu->timeout.function = mpu_pm_timeout;
1123 mpu->timeout.data = (u_long) mpu;
1124 init_timer(&mpu->timeout);
1125
1126 mpu->nb.notifier_call = mpu_pm_notifier_callback;
1127 mpu->nb.priority = 0;
1128 res = register_pm_notifier(&mpu->nb);
1129 if (res) {
1130 dev_err(&client->adapter->dev,
1131 "Unable to register pm_notifier %d\n", res);
1132 goto out_register_pm_notifier_failed;
1133 }
1134
1135 pdata = (struct mpu_platform_data *)client->dev.platform_data;
1136 if (!pdata) {
1137 dev_WARN(&client->adapter->dev,
1138 "Missing platform data for mpu\n");
1139 }
1140 mldl_cfg->pdata = pdata;
1141
1142 mldl_cfg->mpu_chip_info->addr = client->addr;
1143 res = inv_mpu_open(&mpu->mldl_cfg, client->adapter, NULL, NULL, NULL);
1144
1145 if (res) {
1146 dev_err(&client->adapter->dev,
1147 "Unable to open %s %d\n", MPU_NAME, res);
1148 res = -ENODEV;
1149 goto out_whoami_failed;
1150 }
1151
1152 mpu->dev.minor = MISC_DYNAMIC_MINOR;
1153 mpu->dev.name = "mpu";
1154 mpu->dev.fops = &mpu_fops;
1155 res = misc_register(&mpu->dev);
1156 if (res < 0) {
1157 dev_err(&client->adapter->dev,
1158 "ERROR: misc_register returned %d\n", res);
1159 goto out_misc_register_failed;
1160 }
1161
1162 if (client->irq) {
1163 dev_info(&client->adapter->dev,
1164 "Installing irq using %d\n", client->irq);
1165 if (BIT_ACTL_LOW == ((mldl_cfg->pdata->int_config) & BIT_ACTL))
1166 irq_flags = IRQF_TRIGGER_FALLING;
1167 else
1168 irq_flags = IRQF_TRIGGER_RISING;
1169 res = mpuirq_init(client, mldl_cfg, irq_flags);
1170
1171 if (res)
1172 goto out_mpuirq_failed;
1173 } else {
1174 dev_WARN(&client->adapter->dev,
1175 "Missing %s IRQ\n", MPU_NAME);
1176 }
1177 if (!strcmp(mpu_id[1].name, devid->name)) {
1178 /* Special case to re-use the inv_mpu_register_slave */
1179 struct ext_slave_platform_data *slave_pdata;
1180 slave_pdata = kzalloc(sizeof(*slave_pdata), GFP_KERNEL);
1181 if (!slave_pdata) {
1182 res = -ENOMEM;
1183 goto out_slave_pdata_kzalloc_failed;
1184 }
1185 slave_pdata->bus = EXT_SLAVE_BUS_PRIMARY;
1186 for (ii = 0; ii < 9; ii++)
1187 slave_pdata->orientation[ii] = pdata->orientation[ii];
1188 res = inv_mpu_register_slave(
1189 NULL, client,
1190 slave_pdata,
1191 mpu6050_get_slave_descr);
1192 if (res) {
1193 /* if inv_mpu_register_slave fails there are no pointer
1194 references to the memory allocated to slave_pdata */
1195 kfree(slave_pdata);
1196 goto out_slave_pdata_kzalloc_failed;
1197 }
1198 }
1199 return res;
1200
1201out_slave_pdata_kzalloc_failed:
1202 if (client->irq)
1203 mpuirq_exit();
1204out_mpuirq_failed:
1205 misc_deregister(&mpu->dev);
1206out_misc_register_failed:
1207 inv_mpu_close(&mpu->mldl_cfg, client->adapter, NULL, NULL, NULL);
1208out_whoami_failed:
1209 unregister_pm_notifier(&mpu->nb);
1210out_register_pm_notifier_failed:
1211 kfree(mldl_cfg->mpu_ram->ram);
1212 mpu_private_data = NULL;
1213out_alloc_ram_failed:
1214 kfree(mpu);
1215out_alloc_data_failed:
1216out_check_functionality_failed:
1217 dev_err(&client->adapter->dev, "%s failed %d\n", __func__, res);
1218 return res;
1219
1220}
1221
1222static int mpu_remove(struct i2c_client *client)
1223{
1224 struct mpu_private_data *mpu = i2c_get_clientdata(client);
1225 struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
1226 struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
1227 struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
1228 int ii;
1229
1230 for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
1231 if (!pdata_slave[ii])
1232 slave_adapter[ii] = NULL;
1233 else
1234 slave_adapter[ii] =
1235 i2c_get_adapter(pdata_slave[ii]->adapt_num);
1236 }
1237
1238 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
1239 dev_dbg(&client->adapter->dev, "%s\n", __func__);
1240
1241 inv_mpu_close(mldl_cfg,
1242 slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
1243 slave_adapter[EXT_SLAVE_TYPE_ACCEL],
1244 slave_adapter[EXT_SLAVE_TYPE_COMPASS],
1245 slave_adapter[EXT_SLAVE_TYPE_PRESSURE]);
1246
1247 if (mldl_cfg->slave[EXT_SLAVE_TYPE_ACCEL] &&
1248 (mldl_cfg->slave[EXT_SLAVE_TYPE_ACCEL]->id ==
1249 ACCEL_ID_MPU6050)) {
1250 struct ext_slave_platform_data *slave_pdata =
1251 mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_ACCEL];
1252 inv_mpu_unregister_slave(
1253 client,
1254 mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_ACCEL],
1255 mpu6050_get_slave_descr);
1256 kfree(slave_pdata);
1257 }
1258
1259 if (client->irq)
1260 mpuirq_exit();
1261
1262 misc_deregister(&mpu->dev);
1263
1264 unregister_pm_notifier(&mpu->nb);
1265
1266 kfree(mpu->mldl_cfg.mpu_ram->ram);
1267 kfree(mpu);
1268
1269 return 0;
1270}
1271
1272static struct i2c_driver mpu_driver = {
1273 .class = I2C_CLASS_HWMON,
1274 .probe = mpu_probe,
1275 .remove = mpu_remove,
1276 .id_table = mpu_id,
1277 .driver = {
1278 .owner = THIS_MODULE,
1279 .name = MPU_NAME,
1280 },
1281 .address_list = normal_i2c,
1282 .shutdown = mpu_shutdown, /* optional */
1283 .suspend = mpu_dev_suspend, /* optional */
1284 .resume = mpu_dev_resume, /* optional */
1285
1286};
1287
1288static int __init mpu_init(void)
1289{
1290 int res = i2c_add_driver(&mpu_driver);
1291 pr_info("%s: Probe name %s\n", __func__, MPU_NAME);
1292 if (res)
1293 pr_err("%s failed\n", __func__);
1294 return res;
1295}
1296
1297static void __exit mpu_exit(void)
1298{
1299 pr_info("%s\n", __func__);
1300 i2c_del_driver(&mpu_driver);
1301}
1302
1303module_init(mpu_init);
1304module_exit(mpu_exit);
1305
1306MODULE_AUTHOR("Invensense Corporation");
1307MODULE_DESCRIPTION("User space character device interface for MPU");
1308MODULE_LICENSE("GPL");
1309MODULE_ALIAS(MPU_NAME);