input: mpu3050: Add HTC version of MPU3050 sensor

HTC kernel version: evitaul-jb-crc-3.4.10-ec474a3

Change-Id: I53903035d40fe4eae1b4240068765c3e32a31ddd
diff --git a/drivers/input/misc/mpu3050/Kconfig b/drivers/input/misc/mpu3050/Kconfig
new file mode 100644
index 0000000..91f1939
--- /dev/null
+++ b/drivers/input/misc/mpu3050/Kconfig
@@ -0,0 +1,176 @@
+config MPU_SENSORS_MPU3050
+    tristate "MPU3050"
+    depends on I2C
+    help
+      If you say yes here you get support for the MPU3050 Gyroscope driver
+      This driver can also be built as a module.  If so, the module
+      will be called mpu3050.
+
+choice
+    prompt "Accelerometer Type"
+    depends on MPU_SENSORS_MPU3050
+    default MPU_SENSORS_BMA150
+
+config MPU_SENSORS_ACCELEROMETER_NONE
+    bool "NONE"
+    depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6000
+    help
+      This disables accelerometer support for the MPU3050
+
+config MPU_SENSORS_ADXL346
+    bool "ADI adxl346"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ADI adxl346 accelerometer
+
+config MPU_SENSORS_BMA150
+    bool "Bosch BMA150"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Bosch BMA150 accelerometer
+
+config MPU_SENSORS_BMA250
+    bool "Bosch BMA250"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Bosch BMA250 accelerometer
+
+config MPU_SENSORS_BMA222
+    bool "Bosch BMA222"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Bosch BMA222 accelerometer
+
+config MPU_SENSORS_KXSD9
+    bool "Kionix KXSD9"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Kionix KXSD9 accelerometer
+
+config MPU_SENSORS_KXTF9
+    bool "Kionix KXTF9"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Kionix KXFT9 accelerometer
+
+config MPU_SENSORS_LIS331DLH
+    bool "ST lis331dlh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lis331dlh accelerometer
+
+config MPU_SENSORS_LIS3DH
+    bool "ST lis3dh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lis3dh accelerometer
+
+config MPU_SENSORS_LSM303DLHA
+    bool "ST lsm303dlh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lsm303dlh accelerometer
+
+config MPU_SENSORS_MMA8450
+    bool "Freescale mma8450"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Freescale mma8450 accelerometer
+
+config MPU_SENSORS_MMA845X
+    bool "Freescale mma8451/8452/8453"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Freescale mma8451/8452/8453 accelerometer
+
+endchoice
+
+choice
+    prompt "Compass Type"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    default MPU_SENSORS_AK8963
+
+config MPU_SENSORS_COMPASS_NONE
+    bool "NONE"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    help
+      This disables compass support for the MPU6000
+
+config MPU_SENSORS_AK8975
+    bool "AKM ak8975"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    help
+      This enables support for the AKM ak8975 compass
+
+config MPU_SENSORS_AK8963
+    bool "AKM ak8963"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    help
+      This enables support for the AKM ak8963 compass
+
+config MPU_SENSORS_MMC314X
+    bool "MEMSIC mmc314x"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the MEMSIC mmc314x compass
+
+config MPU_SENSORS_AMI30X
+    bool "Aichi Steel ami30X"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Aichi Steel ami304/ami305 compass
+
+config MPU_SENSORS_HMC5883
+    bool "Honeywell hmc5883"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Honeywell hmc5883 compass
+
+config MPU_SENSORS_LSM303DLHM
+    bool "ST lsm303dlh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lsm303dlh compass
+
+config MPU_SENSORS_MMC314X
+    bool "MEMSIC mmc314xMS"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the MEMSIC mmc314xMS compass
+
+config MPU_SENSORS_YAS529
+    bool "Yamaha yas529"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Yamaha yas529 compass
+
+config MPU_SENSORS_HSCDTD002B
+    bool "Alps hscdtd002b"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Alps hscdtd002b compass
+
+config MPU_SENSORS_HSCDTD004A
+    bool "Alps hscdtd004a"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Alps hscdtd004a compass
+
+endchoice
+
+config MPU_SENSORS_TIMERIRQ
+    tristate "Timer IRQ"
+    help
+      If you say yes here you get access to the timerirq device handle which
+      can be used to select on.  This can be used instead of IRQ's, sleeping,
+      or timer threads.  Reading from this device returns the same type of
+      information as reading from the MPU and slave IRQ's.
+
+config MPU_SENSORS_DEBUG
+    bool "MPU debug"
+    depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6000 || MPU_SENSORS_TIMERIRQ
+    help
+      If you say yes here you get extra debug messages from the MPU3050
+      and other slave sensors.
+
+
diff --git a/drivers/input/misc/mpu3050/Makefile b/drivers/input/misc/mpu3050/Makefile
new file mode 100644
index 0000000..94dc4be
--- /dev/null
+++ b/drivers/input/misc/mpu3050/Makefile
@@ -0,0 +1,140 @@
+
+# Kernel makefile for motions sensors
+#
+#
+
+# MPU
+obj-$(CONFIG_MPU_SENSORS_MPU3050)	+= mpu3050.o
+mpu3050-objs += mpuirq.o \
+	slaveirq.o \
+	mpu-dev.o \
+	mpu-i2c.o \
+	mlsl-kernel.o \
+	mlos-kernel.o \
+	$(MLLITE_DIR)mldl_cfg.o
+
+#
+# Accel options
+#
+ifdef CONFIG_MPU_SENSORS_ADXL346
+mpu3050-objs += $(MLLITE_DIR)accel/adxl346.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_BMA150
+mpu3050-objs += $(MLLITE_DIR)accel/bma150.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_BMA250
+mpu3050-objs += $(MLLITE_DIR)accel/bma250.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_BMA222
+mpu3050-objs += $(MLLITE_DIR)accel/bma222.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_KXSD9
+mpu3050-objs += $(MLLITE_DIR)accel/kxsd9.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_KXTF9
+mpu3050-objs += $(MLLITE_DIR)accel/kxtf9.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LIS331DLH
+mpu3050-objs += $(MLLITE_DIR)accel/lis331.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LIS3DH
+mpu3050-objs += $(MLLITE_DIR)accel/lis3dh.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LSM303DLHA
+mpu3050-objs += $(MLLITE_DIR)accel/lsm303a.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MMA8450
+mpu3050-objs += $(MLLITE_DIR)accel/mma8450.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MMA845X
+mpu3050-objs += $(MLLITE_DIR)accel/mma845x.o
+endif
+
+#
+# Compass options
+#
+ifdef CONFIG_MPU_SENSORS_AK8975
+mpu3050-objs += $(MLLITE_DIR)compass/ak8975.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_AK8963
+mpu3050-objs += $(MLLITE_DIR)compass/ak8963.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_AMI30X
+mpu3050-objs += $(MLLITE_DIR)compass/ami30x.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_HMC5883
+mpu3050-objs += $(MLLITE_DIR)compass/hmc5883.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LSM303DLHM
+mpu3050-objs += $(MLLITE_DIR)compass/lsm303m.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MMC314X
+mpu3050-objs += $(MLLITE_DIR)compass/mmc314x.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_YAS529
+mpu3050-objs += $(MLLITE_DIR)compass/yas529-kernel.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_HSCDTD002B
+mpu3050-objs += $(MLLITE_DIR)compass/hscdtd002b.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_HSCDTD004A
+mpu3050-objs += $(MLLITE_DIR)compass/hscdtd004a.o
+endif
+#
+# Pressure options
+#
+ifdef CONFIG_MPU_SENSORS_BMA085
+mpu3050-objs += $(MLLITE_DIR)pressure/bma085.o
+endif
+
+EXTRA_CFLAGS += -I$(M)/$(MLLITE_DIR) \
+                -I$(M)/../../include \
+		-Idrivers/input/misc/mpu3050 \
+                -Iinclude/linux
+
+obj-$(CONFIG_MPU_SENSORS_MPU6000)+= mpu6000.o
+mpu6000-objs += mpuirq.o \
+	slaveirq.o \
+	mpu-dev.o \
+	mpu-i2c.o \
+	mlsl-kernel.o \
+	mlos-kernel.o \
+	$(MLLITE_DIR)mldl_cfg.o \
+	$(MLLITE_DIR)accel/mantis.o
+
+ifdef CONFIG_MPU_SENSORS_AK8975
+mpu6000-objs += $(MLLITE_DIR)compass/ak8975.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_AK8963
+mpu6000-objs += $(MLLITE_DIR)compass/ak8963.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MPU6000
+EXTRA_CFLAGS += -DM_HW
+endif
+
+obj-$(CONFIG_MPU_SENSORS_TIMERIRQ)+= timerirq.o
+
+ifdef CONFIG_MPU_SENSORS_DEBUG
+EXTRA_CFLAGS += -DDEBUG
+endif
+
diff --git a/drivers/input/misc/mpu3050/accel/bma250.c b/drivers/input/misc/mpu3050/accel/bma250.c
new file mode 100644
index 0000000..3f6a8ae
--- /dev/null
+++ b/drivers/input/misc/mpu3050/accel/bma250.c
@@ -0,0 +1,574 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+#include <linux/delay.h>
+
+#include "mpu.h"
+#include "mlos.h"
+#include "mlsl.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+#define BOSCH_CTRL_REG      (0x0F)
+#define BOSCH_INT_REG       (0x16)
+#define BOSCH_PWR_REG       (0x11)
+#define BMA250_REG_SOFT_RESET (0x14)
+#define BMA250_BW_REG        (0x10)    
+
+#define ACCEL_BOSCH_CTRL_MASK              (0x0F)
+#define ACCEL_BOSCH_CTRL_MASK_FSR          (0xF8)
+#define ACCEL_BOSCH_INT_MASK_WUP           (0xF8)
+#define ACCEL_BOSCH_INT_MASK_IRQ           (0xDF)
+#define BMA250_BW_MASK      (0xE0)    
+
+#define D(x...) printk(KERN_DEBUG "[GSNR][BMA250] " x)
+#define I(x...) printk(KERN_INFO "[GSNR][BMA250] " x)
+#define E(x...) printk(KERN_ERR "[GSNR][BMA250 ERROR] " x)
+#define DIF(x...) \
+	if (debug_flag) \
+		printk(KERN_DEBUG "[GSNR][BMA250 DEBUG] " x)
+
+
+struct bma250_config {
+	unsigned int odr; 
+	unsigned int fsr; 
+	unsigned int irq_type;
+	unsigned int power_mode;
+	unsigned char ctrl_reg; 
+	unsigned char bw_reg; 
+	unsigned char int_reg;
+};
+
+struct bma250_private_data {
+	struct bma250_config suspend;
+	struct bma250_config resume;
+	unsigned char state;
+};
+
+static int set_normal_mode(void *mlsl_handle,
+			 struct ext_slave_platform_data *pdata)
+{
+	int result = 0;
+
+	result = MLSLSerialWriteSingle(mlsl_handle,
+		pdata->address,	BOSCH_PWR_REG, 0x00);
+	ERROR_CHECK(result);
+
+	usleep(2000);
+
+	return 0;
+}
+
+static int bma250_set_irq(void *mlsl_handle,
+			struct ext_slave_platform_data *pdata,
+			struct bma250_config *config,
+			int apply,
+			long irq_type)
+{
+	unsigned char irq_bits = 0;
+	int result = ML_SUCCESS;
+
+	
+	return ML_SUCCESS;
+
+	if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION)
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+	config->irq_type = (unsigned char)irq_type;
+
+	if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+		irq_bits = 0x20;
+		config->int_reg &= ACCEL_BOSCH_INT_MASK_WUP;
+	} else {
+		irq_bits = 0x00;
+		config->int_reg &= ACCEL_BOSCH_INT_MASK_WUP;
+	}
+
+	config->int_reg &= ACCEL_BOSCH_INT_MASK_IRQ;
+	config->int_reg |= irq_bits;
+
+	if (apply) {
+
+		if (!config->power_mode) {
+			
+			result = MLSLSerialWriteSingle(mlsl_handle,
+					pdata->address, BMA250_REG_SOFT_RESET,
+					0xB6);
+			ERROR_CHECK(result);
+			MLOSSleep(1);
+		}
+
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+			BOSCH_CTRL_REG, config->ctrl_reg);
+		ERROR_CHECK(result);
+
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+			BOSCH_INT_REG, config->int_reg);
+		ERROR_CHECK(result);
+
+		if (!config->power_mode) {
+			result = MLSLSerialWriteSingle(mlsl_handle,
+				pdata->address, BOSCH_PWR_REG, 0x80);
+			ERROR_CHECK(result);
+			MLOSSleep(1);
+		} else {
+			result = set_normal_mode(mlsl_handle, pdata);
+			ERROR_CHECK(result);
+		}
+	}
+	return result;
+}
+
+static int bma250_set_odr(void *mlsl_handle,
+			struct ext_slave_platform_data *pdata,
+			struct bma250_config *config,
+			int apply,
+			long odr)
+{
+	unsigned char odr_bits = 0;
+	unsigned char wup_bits = 0;
+	int result = ML_SUCCESS;
+
+	
+	if (odr > 100000) {
+		config->odr = 31250;
+		odr_bits = 0x0A;
+		config->power_mode = 1;
+	} else if (odr > 50000) {
+		config->odr = 31250;
+		odr_bits = 0x0A;
+		config->power_mode = 1;
+	} else if (odr > 20000) {
+		config->odr = 31250;
+		odr_bits = 0x0A;
+		config->power_mode = 1;
+	} else if (odr > 15000) {
+		config->odr = 31250;
+		odr_bits = 0x0A;
+		config->power_mode = 1;
+	} else if (odr > 0) {
+		config->odr = 31250;
+		odr_bits = 0x0A;
+		config->power_mode = 1;
+	} else {
+		config->odr = 0;
+		wup_bits = 0x00;
+		config->power_mode = 0;
+	}
+
+	switch (config->power_mode) {
+	case 1:
+		config->bw_reg &= BMA250_BW_MASK;
+		config->bw_reg |= odr_bits;
+		config->int_reg &= ACCEL_BOSCH_INT_MASK_WUP;
+		break;
+	case 0:
+		config->int_reg &= ACCEL_BOSCH_INT_MASK_WUP;
+		config->int_reg |= wup_bits;
+		break;
+	default:
+		break;
+	}
+
+	MPL_LOGV("ODR: %d \n", config->odr);
+	if (apply) {
+			
+			result = MLSLSerialWriteSingle(mlsl_handle,
+					pdata->address, BMA250_REG_SOFT_RESET,
+					0xB6);
+			ERROR_CHECK(result);
+			MLOSSleep(1);
+
+			result = MLSLSerialWriteSingle(mlsl_handle,
+					pdata->address, BMA250_BW_REG,
+					config->bw_reg);
+			ERROR_CHECK(result);
+
+			
+
+			if (!config->power_mode) {
+				result = MLSLSerialWriteSingle(mlsl_handle,
+						pdata->address,	BOSCH_PWR_REG,
+						0x80);
+				ERROR_CHECK(result);
+				MLOSSleep(1);
+			} else {
+				result = set_normal_mode(mlsl_handle, pdata);
+				ERROR_CHECK(result);
+			}
+	}
+
+	return result;
+}
+
+static int bma250_set_fsr(void *mlsl_handle,
+			struct ext_slave_platform_data *pdata,
+			struct bma250_config *config,
+			int apply,
+			long fsr)
+{
+	unsigned char fsr_bits;
+	int result = ML_SUCCESS;
+
+	
+	if (fsr <= 2048) {
+		fsr_bits = 0x03;
+		config->fsr = 2048;
+	} else if (fsr <= 4096) {
+		fsr_bits = 0x03;
+		config->fsr = 2048;
+	} else if (fsr <= 8192) {
+		fsr_bits = 0x03;
+		config->fsr = 2048;
+	} else if (fsr <= 16384) {
+		fsr_bits = 0x03;
+		config->fsr = 2048;
+	} else {
+		fsr_bits = 0x03;
+		config->fsr = 2048;
+	}
+
+	config->ctrl_reg &= ACCEL_BOSCH_CTRL_MASK_FSR;
+	config->ctrl_reg |= fsr_bits;
+
+	MPL_LOGV("FSR: %d \n", config->fsr);
+	if (apply) {
+
+		if (!config->power_mode) {
+			
+			result = MLSLSerialWriteSingle(mlsl_handle,
+				pdata->address, BMA250_REG_SOFT_RESET, 0xB6);
+			ERROR_CHECK(result);
+			MLOSSleep(1);
+		}
+
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+			BOSCH_CTRL_REG, config->ctrl_reg);
+		ERROR_CHECK(result);
+
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+			BOSCH_CTRL_REG, config->ctrl_reg);
+		ERROR_CHECK(result);
+
+		if (!config->power_mode) {
+			result = MLSLSerialWriteSingle(mlsl_handle,
+				pdata->address,	BOSCH_PWR_REG, 0x80);
+			ERROR_CHECK(result);
+			MLOSSleep(1);
+		} else {
+			result = set_normal_mode(mlsl_handle, pdata);
+			ERROR_CHECK(result);
+		}
+	}
+	return result;
+}
+
+static int bma250_suspend(void *mlsl_handle,
+			  struct ext_slave_descr *slave,
+			  struct ext_slave_platform_data *pdata)
+{
+
+	int result = 0;
+	unsigned char ctrl_reg;
+	unsigned char int_reg;
+
+	struct bma250_private_data *private_data = pdata->private_data;
+	ctrl_reg = private_data->suspend.ctrl_reg;
+	int_reg = private_data->suspend.int_reg;
+
+	private_data->state = 1;
+
+	
+	
+
+	
+
+	if (!private_data->suspend.power_mode) {
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+			BOSCH_PWR_REG, 0x80);
+		ERROR_CHECK(result);
+	}
+
+	return result;
+}
+
+
+static int bma250_resume(void *mlsl_handle,
+			 struct ext_slave_descr *slave,
+			 struct ext_slave_platform_data *pdata)
+{
+
+	int result;
+	unsigned char ctrl_reg;
+	unsigned char bw_reg;
+	unsigned char int_reg;
+
+	struct bma250_private_data *private_data = pdata->private_data;
+	ctrl_reg = private_data->resume.ctrl_reg;
+	bw_reg = private_data->resume.bw_reg;
+	int_reg = private_data->resume.int_reg;
+
+	private_data->state = 0;
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+		BMA250_REG_SOFT_RESET, 0xB6);  
+	ERROR_CHECK(result);
+	MLOSSleep(1);
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+		BOSCH_CTRL_REG, ctrl_reg);
+	ERROR_CHECK(result);
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+		BMA250_BW_REG, bw_reg);
+	ERROR_CHECK(result);
+
+	
+
+	if (!private_data->resume.power_mode) {
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+			BOSCH_PWR_REG, 0x80);
+		ERROR_CHECK(result);
+	} else {
+		result = set_normal_mode(mlsl_handle, pdata);
+		ERROR_CHECK(result);
+	}
+
+	return result;
+}
+
+static int bma250_read(void *mlsl_handle,
+		       struct ext_slave_descr *slave,
+		       struct ext_slave_platform_data *pdata,
+		       unsigned char *data)
+{
+	int result;
+
+	result = MLSLSerialRead(mlsl_handle, pdata->address,
+		slave->reg, slave->len, data);
+
+	return result;
+}
+
+static int bma250_init(void *mlsl_handle,
+			  struct ext_slave_descr *slave,
+			  struct ext_slave_platform_data *pdata)
+{
+	tMLError result;
+	unsigned char reg = 0;
+	unsigned char bw_reg = 0;
+
+	struct bma250_private_data *private_data;
+	private_data = (struct bma250_private_data *)
+		MLOSMalloc(sizeof(struct bma250_private_data));
+
+	printk(KERN_DEBUG "%s\n", __func__);
+
+	if (!private_data)
+		return ML_ERROR_MEMORY_EXAUSTED;
+
+
+
+	pdata->private_data = private_data;
+
+	result =
+	    MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+		BMA250_REG_SOFT_RESET, 0xB6);  
+	ERROR_CHECK(result);
+	MLOSSleep(1);
+
+	result =
+	    MLSLSerialRead(mlsl_handle, pdata->address, BOSCH_CTRL_REG, 1,
+				&reg);
+	ERROR_CHECK(result);
+
+	result =
+	    MLSLSerialRead(mlsl_handle, pdata->address, BMA250_BW_REG, 1,
+				&bw_reg);
+	ERROR_CHECK(result);
+
+	private_data->resume.ctrl_reg = reg;
+	private_data->suspend.ctrl_reg = reg;
+
+	private_data->resume.bw_reg = bw_reg;
+	private_data->suspend.bw_reg = bw_reg;
+
+	
+
+	private_data->resume.int_reg = reg;
+	private_data->suspend.int_reg = reg;
+
+	private_data->resume.power_mode = 1;
+	private_data->suspend.power_mode = 0;
+
+	private_data->state = 0;
+
+	bma250_set_odr(mlsl_handle, pdata, &private_data->suspend,
+			FALSE, 0);
+	bma250_set_odr(mlsl_handle, pdata, &private_data->resume,
+			TRUE, 25000);
+	bma250_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+			FALSE, 2048);
+	bma250_set_fsr(mlsl_handle, pdata, &private_data->resume,
+			FALSE, 2048);
+
+	
+
+	result =
+	    MLSLSerialWriteSingle(mlsl_handle, pdata->address, BOSCH_PWR_REG,
+					0x80);
+	ERROR_CHECK(result);
+
+	return result;
+}
+
+static int bma250_exit(void *mlsl_handle,
+			  struct ext_slave_descr *slave,
+			  struct ext_slave_platform_data *pdata)
+{
+	if (pdata->private_data)
+		return MLOSFree(pdata->private_data);
+	else
+		return ML_SUCCESS;
+}
+
+static int bma250_config(void *mlsl_handle,
+			struct ext_slave_descr *slave,
+			struct ext_slave_platform_data *pdata,
+			struct ext_slave_config *data)
+{
+	struct bma250_private_data *private_data = pdata->private_data;
+	if (!data->data)
+		return ML_ERROR_INVALID_PARAMETER;
+
+	switch (data->key) {
+	case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+		return bma250_set_odr(mlsl_handle, pdata,
+					&private_data->suspend,
+					data->apply,
+					*((long *)data->data));
+	case MPU_SLAVE_CONFIG_ODR_RESUME:
+		return bma250_set_odr(mlsl_handle, pdata,
+					&private_data->resume,
+					data->apply,
+					*((long *)data->data));
+	case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+		return bma250_set_fsr(mlsl_handle, pdata,
+					&private_data->suspend,
+					data->apply,
+					*((long *)data->data));
+	case MPU_SLAVE_CONFIG_FSR_RESUME:
+		return bma250_set_fsr(mlsl_handle, pdata,
+					&private_data->resume,
+					data->apply,
+					*((long *)data->data));
+	case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+		return bma250_set_irq(mlsl_handle, pdata,
+					&private_data->suspend,
+					data->apply,
+					*((long *)data->data));
+	case MPU_SLAVE_CONFIG_IRQ_RESUME:
+		return bma250_set_irq(mlsl_handle, pdata,
+					&private_data->resume,
+					data->apply,
+					*((long *)data->data));
+	default:
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+	};
+	return ML_SUCCESS;
+}
+
+static int bma250_get_config(void *mlsl_handle,
+				struct ext_slave_descr *slave,
+				struct ext_slave_platform_data *pdata,
+				struct ext_slave_config *data)
+{
+	struct bma250_private_data *private_data = pdata->private_data;
+	if (!data->data)
+		return ML_ERROR_INVALID_PARAMETER;
+
+	switch (data->key) {
+	case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+		(*(unsigned long *)data->data) =
+			(unsigned long) private_data->suspend.odr;
+		break;
+	case MPU_SLAVE_CONFIG_ODR_RESUME:
+		(*(unsigned long *)data->data) =
+			(unsigned long) private_data->resume.odr;
+		break;
+	case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+		(*(unsigned long *)data->data) =
+			(unsigned long) private_data->suspend.fsr;
+		break;
+	case MPU_SLAVE_CONFIG_FSR_RESUME:
+		(*(unsigned long *)data->data) =
+			(unsigned long) private_data->resume.fsr;
+		break;
+	case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+		(*(unsigned long *)data->data) =
+			(unsigned long) private_data->suspend.irq_type;
+		break;
+	case MPU_SLAVE_CONFIG_IRQ_RESUME:
+		(*(unsigned long *)data->data) =
+			(unsigned long) private_data->resume.irq_type;
+		break;
+	default:
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+	};
+
+	return ML_SUCCESS;
+}
+
+static struct ext_slave_descr bma250_descr = {
+	 bma250_init,
+	 bma250_exit,
+	 bma250_suspend,
+	 bma250_resume,
+	 bma250_read,
+	 bma250_config,
+	 bma250_get_config,
+	 "bma250",
+	 EXT_SLAVE_TYPE_ACCELEROMETER,
+	 ACCEL_ID_BMA250,
+	 0x02,
+	 6,
+	 EXT_SLAVE_LITTLE_ENDIAN,
+	 {2, 0},
+};
+
+struct ext_slave_descr *bma250_get_slave_descr(void)
+{
+	return &bma250_descr;
+}
+EXPORT_SYMBOL(bma250_get_slave_descr);
+
+#ifdef __KERNEL__
+MODULE_AUTHOR("Invensense");
+MODULE_DESCRIPTION("User space IRQ handler for MPU3xxx devices");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bma");
+#endif
+
diff --git a/drivers/input/misc/mpu3050/compass/ak8975.c b/drivers/input/misc/mpu3050/compass/ak8975.c
new file mode 100644
index 0000000..2a58f56
--- /dev/null
+++ b/drivers/input/misc/mpu3050/compass/ak8975.c
@@ -0,0 +1,205 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+
+
+#include <string.h>
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+
+#define AK8975_REG_ST1  (0x02)
+#define AK8975_REG_HXL  (0x03)
+#define AK8975_REG_ST2  (0x09)
+
+#define AK8975_REG_CNTL (0x0A)
+
+#define AK8975_CNTL_MODE_POWER_DOWN         (0x00)
+#define AK8975_CNTL_MODE_SINGLE_MEASUREMENT (0x01)
+
+int ak8975_suspend(void *mlsl_handle,
+		   struct ext_slave_descr *slave,
+		   struct ext_slave_platform_data *pdata)
+{
+	int result = ML_SUCCESS;
+	result =
+	    MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+				  AK8975_REG_CNTL,
+				  AK8975_CNTL_MODE_POWER_DOWN);
+	MLOSSleep(1);		
+	ERROR_CHECK(result);
+	return result;
+}
+
+int ak8975_resume(void *mlsl_handle,
+		  struct ext_slave_descr *slave,
+		  struct ext_slave_platform_data *pdata)
+{
+	int result = ML_SUCCESS;
+	result =
+	    MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+				  AK8975_REG_CNTL,
+				  AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+	ERROR_CHECK(result);
+	return result;
+}
+
+int ak8975_read(void *mlsl_handle,
+		struct ext_slave_descr *slave,
+		struct ext_slave_platform_data *pdata, unsigned char *data)
+{
+	unsigned char regs[8];
+	unsigned char *stat = &regs[0];
+	unsigned char *stat2 = &regs[7];
+	int result = ML_SUCCESS;
+	int status = ML_SUCCESS;
+
+	result =
+	    MLSLSerialRead(mlsl_handle, pdata->address, AK8975_REG_ST1,
+			   8, regs);
+	ERROR_CHECK(result);
+
+	if (*stat & 0x01) {
+		memcpy(data, &regs[1], 6);
+		status = ML_SUCCESS;
+	}
+
+	if (*stat2 & 0x04)
+		status = ML_ERROR_COMPASS_DATA_ERROR;
+	if (*stat2 & 0x08)
+		status = ML_ERROR_COMPASS_DATA_OVERFLOW;
+	if (*stat & 0x02) {
+		
+		status = ML_SUCCESS;
+	}
+
+	if (*stat != 0x00 || *stat2 != 0x00) {
+		result =
+		    MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+					  AK8975_REG_CNTL,
+					  AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+		ERROR_CHECK(result);
+	}
+
+	return status;
+}
+
+static int ak8975_config(void *mlsl_handle,
+			struct ext_slave_descr *slave,
+			struct ext_slave_platform_data *pdata,
+			struct ext_slave_config *data)
+{
+	int result;
+	if (!data->data)
+		return ML_ERROR_INVALID_PARAMETER;
+
+	switch (data->key) {
+	case MPU_SLAVE_WRITE_REGISTERS:
+		result = MLSLSerialWrite(mlsl_handle, pdata->address,
+					data->len,
+					(unsigned char *)data->data);
+		ERROR_CHECK(result);
+		break;
+	case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+	case MPU_SLAVE_CONFIG_ODR_RESUME:
+	case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+	case MPU_SLAVE_CONFIG_FSR_RESUME:
+	case MPU_SLAVE_CONFIG_MOT_THS:
+	case MPU_SLAVE_CONFIG_NMOT_THS:
+	case MPU_SLAVE_CONFIG_MOT_DUR:
+	case MPU_SLAVE_CONFIG_NMOT_DUR:
+	case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+	case MPU_SLAVE_CONFIG_IRQ_RESUME:
+	default:
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+	};
+
+	return ML_SUCCESS;
+}
+
+static int ak8975_get_config(void *mlsl_handle,
+				struct ext_slave_descr *slave,
+				struct ext_slave_platform_data *pdata,
+				struct ext_slave_config *data)
+{
+	int result;
+	if (!data->data)
+		return ML_ERROR_INVALID_PARAMETER;
+
+	switch (data->key) {
+	case MPU_SLAVE_READ_REGISTERS:
+	{
+		unsigned char *serial_data = (unsigned char *)data->data;
+		result = MLSLSerialRead(mlsl_handle, pdata->address,
+					serial_data[0],
+					data->len - 1,
+					&serial_data[1]);
+		ERROR_CHECK(result);
+		break;
+	}
+	case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+	case MPU_SLAVE_CONFIG_ODR_RESUME:
+	case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+	case MPU_SLAVE_CONFIG_FSR_RESUME:
+	case MPU_SLAVE_CONFIG_MOT_THS:
+	case MPU_SLAVE_CONFIG_NMOT_THS:
+	case MPU_SLAVE_CONFIG_MOT_DUR:
+	case MPU_SLAVE_CONFIG_NMOT_DUR:
+	case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+	case MPU_SLAVE_CONFIG_IRQ_RESUME:
+	default:
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+	};
+
+	return ML_SUCCESS;
+}
+
+struct ext_slave_descr ak8975_descr = {
+	 NULL,
+	 NULL,
+	 ak8975_suspend,
+	 ak8975_resume,
+	 ak8975_read,
+	 ak8975_config,
+	 ak8975_get_config,
+	 "ak8975",
+	 EXT_SLAVE_TYPE_COMPASS,
+	 COMPASS_ID_AKM,
+	 0x01,
+	 9,
+	 EXT_SLAVE_LITTLE_ENDIAN,
+	 {9830, 4000}
+};
+
+struct ext_slave_descr *ak8975_get_slave_descr(void)
+{
+	return &ak8975_descr;
+}
+EXPORT_SYMBOL(ak8975_get_slave_descr);
+
diff --git a/drivers/input/misc/mpu3050/log.h b/drivers/input/misc/mpu3050/log.h
new file mode 100644
index 0000000..7b24aca
--- /dev/null
+++ b/drivers/input/misc/mpu3050/log.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2010 InvenSense Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBS_CUTILS_MPL_LOG_H
+#define _LIBS_CUTILS_MPL_LOG_H
+
+#include <stdarg.h>
+
+#ifdef ANDROID
+#include <utils/Log.h>		
+#endif
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef MPL_LOG_NDEBUG
+#ifdef NDEBUG
+#define MPL_LOG_NDEBUG 1
+#else
+#define MPL_LOG_NDEBUG 0
+#endif
+#endif
+
+#ifdef __KERNEL__
+#define MPL_LOG_UNKNOWN MPL_LOG_VERBOSE
+#define MPL_LOG_DEFAULT KERN_DEFAULT
+#define MPL_LOG_VERBOSE KERN_CONT
+#define MPL_LOG_DEBUG   KERN_NOTICE
+#define MPL_LOG_INFO    KERN_INFO
+#define MPL_LOG_WARN    KERN_WARNING
+#define MPL_LOG_ERROR   KERN_ERR
+#define MPL_LOG_SILENT  MPL_LOG_VERBOSE
+
+#else
+#define MPL_LOG_UNKNOWN (0)
+#define MPL_LOG_DEFAULT (1)
+#define MPL_LOG_VERBOSE (2)
+#define MPL_LOG_DEBUG (3)
+#define MPL_LOG_INFO (4)
+#define MPL_LOG_WARN (5)
+#define MPL_LOG_ERROR (6)
+#define MPL_LOG_SILENT (8)
+#endif
+
+
+#ifndef MPL_LOG_TAG
+#ifdef __KERNEL__
+#define MPL_LOG_TAG
+#else
+#define MPL_LOG_TAG NULL
+#endif
+#endif
+
+
+#ifndef MPL_LOGV
+#if MPL_LOG_NDEBUG
+#define MPL_LOGV(...) ((void)0)
+#else
+#define MPL_LOGV(...) ((void)MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#ifndef CONDITION
+#define CONDITION(cond)     ((cond) != 0)
+#endif
+
+#ifndef MPL_LOGV_IF
+#if MPL_LOG_NDEBUG
+#define MPL_LOGV_IF(cond, ...)   ((void)0)
+#else
+#define MPL_LOGV_IF(cond, ...) \
+	((CONDITION(cond))						\
+		? ((void)MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, __VA_ARGS__)) \
+		: (void)0)
+#endif
+#endif
+
+#ifndef MPL_LOGD
+#define MPL_LOGD(...) ((void)MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef MPL_LOGD_IF
+#define MPL_LOGD_IF(cond, ...) \
+	((CONDITION(cond))					       \
+		? ((void)MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, __VA_ARGS__)) \
+		: (void)0)
+#endif
+
+#ifndef MPL_LOGI
+#define MPL_LOGI(...) ((void)MPL_LOG(LOG_INFO, MPL_LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef MPL_LOGI_IF
+#define MPL_LOGI_IF(cond, ...) \
+	((CONDITION(cond))                                              \
+		? ((void)MPL_LOG(LOG_INFO, MPL_LOG_TAG, __VA_ARGS__))   \
+		: (void)0)
+#endif
+
+#ifndef MPL_LOGW
+#define MPL_LOGW(...) ((void)MPL_LOG(LOG_WARN, MPL_LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef MPL_LOGW_IF
+#define MPL_LOGW_IF(cond, ...) \
+	((CONDITION(cond))					       \
+		? ((void)MPL_LOG(LOG_WARN, MPL_LOG_TAG, __VA_ARGS__))  \
+		: (void)0)
+#endif
+
+#ifndef MPL_LOGE
+#define MPL_LOGE(...) ((void)MPL_LOG(LOG_ERROR, MPL_LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef MPL_LOGE_IF
+#define MPL_LOGE_IF(cond, ...) \
+	((CONDITION(cond))					       \
+		? ((void)MPL_LOG(LOG_ERROR, MPL_LOG_TAG, __VA_ARGS__)) \
+		: (void)0)
+#endif
+
+
+#define MPL_LOG_ALWAYS_FATAL_IF(cond, ...) \
+	((CONDITION(cond))					   \
+		? ((void)android_printAssert(#cond, MPL_LOG_TAG, __VA_ARGS__)) \
+		: (void)0)
+
+#define MPL_LOG_ALWAYS_FATAL(...) \
+	(((void)android_printAssert(NULL, MPL_LOG_TAG, __VA_ARGS__)))
+
+#if MPL_LOG_NDEBUG
+
+#define MPL_LOG_FATAL_IF(cond, ...) ((void)0)
+#define MPL_LOG_FATAL(...)          ((void)0)
+
+#else
+
+#define MPL_LOG_FATAL_IF(cond, ...) MPL_LOG_ALWAYS_FATAL_IF(cond, __VA_ARGS__)
+#define MPL_LOG_FATAL(...)          MPL_LOG_ALWAYS_FATAL(__VA_ARGS__)
+
+#endif
+
+#define MPL_LOG_ASSERT(cond, ...) MPL_LOG_FATAL_IF(!(cond), __VA_ARGS__)
+
+
+#ifndef MPL_LOG
+#define MPL_LOG(priority, tag, ...) \
+    MPL_LOG_PRI(priority, tag, __VA_ARGS__)
+#endif
+
+#ifndef MPL_LOG_PRI
+#ifdef ANDROID
+#define MPL_LOG_PRI(priority, tag, ...) \
+	LOG(priority, tag, __VA_ARGS__)
+#elif defined __KERNEL__
+#define MPL_LOG_PRI(priority, tag, ...) \
+	printk(MPL_##priority tag __VA_ARGS__)
+#else
+#define MPL_LOG_PRI(priority, tag, ...) \
+	_MLPrintLog(MPL_##priority, tag, __VA_ARGS__)
+#endif
+#endif
+
+#ifndef MPL_LOG_PRI_VA
+#ifdef ANDROID
+#define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
+    android_vprintLog(priority, NULL, tag, fmt, args)
+#elif defined __KERNEL__
+#define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
+    vprintk(MPL_##priority tag fmt, args)
+#else
+#define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
+    _MLPrintVaLog(priority, NULL, tag, fmt, args)
+#endif
+#endif
+
+
+
+#ifndef ANDROID
+	int _MLPrintLog(int priority, const char *tag, const char *fmt,
+			...);
+	int _MLPrintVaLog(int priority, const char *tag, const char *fmt,
+			  va_list args);
+	int _MLWriteLog(const char *buf, int buflen);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif				
diff --git a/drivers/input/misc/mpu3050/mldl_cfg.c b/drivers/input/misc/mpu3050/mldl_cfg.c
new file mode 100644
index 0000000..6b12dda
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mldl_cfg.c
@@ -0,0 +1,1434 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+
+
+#include <stddef.h>
+
+#include "mldl_cfg.h"
+#include "mpu.h"
+
+#include "mlsl.h"
+#include "mlos.h"
+
+#include "log.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "mldl_cfg:"
+
+#ifdef M_HW
+#define SLEEP   0
+#define WAKE_UP 7
+#define RESET   1
+#define STANDBY 1
+#else
+#define SLEEP   1
+#define WAKE_UP 0
+#define RESET   1
+#define STANDBY 1
+#endif
+
+#define D(x...) printk(KERN_DEBUG "[GYRO][MPU3050] " x)
+#define I(x...) printk(KERN_INFO "[GYRO][MPU3050] " x)
+#define E(x...) printk(KERN_ERR "[GYRO][MPU3050 ERROR] " x)
+
+
+
+static int dmp_stop(struct mldl_cfg *mldl_cfg, void *gyro_handle)
+{
+	unsigned char userCtrlReg = 0;
+	int result;
+
+	if (!mldl_cfg->dmp_is_running)
+		return ML_SUCCESS;
+
+	result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
+				MPUREG_USER_CTRL, 1, &userCtrlReg);
+	ERROR_CHECK(result);
+	userCtrlReg = (userCtrlReg & (~BIT_FIFO_EN)) | BIT_FIFO_RST;
+	userCtrlReg = (userCtrlReg & (~BIT_DMP_EN)) | BIT_DMP_RST;
+
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				       MPUREG_USER_CTRL, userCtrlReg);
+	ERROR_CHECK(result);
+	mldl_cfg->dmp_is_running = 0;
+
+	return result;
+
+}
+static int dmp_start(struct mldl_cfg *pdata, void *mlsl_handle)
+{
+	unsigned char userCtrlReg = 0;
+	int result;
+
+	if (pdata->dmp_is_running == pdata->dmp_enable)
+		return ML_SUCCESS;
+
+	result = MLSLSerialRead(mlsl_handle, pdata->addr,
+				MPUREG_USER_CTRL, 1, &userCtrlReg);
+	ERROR_CHECK(result);
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+				       MPUREG_USER_CTRL,
+				       ((userCtrlReg & (~BIT_FIFO_EN))
+						|   BIT_FIFO_RST));
+	ERROR_CHECK(result);
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+				       MPUREG_USER_CTRL, userCtrlReg);
+	ERROR_CHECK(result);
+
+	result = MLSLSerialRead(mlsl_handle, pdata->addr,
+				MPUREG_USER_CTRL, 1, &userCtrlReg);
+	ERROR_CHECK(result);
+
+	if (pdata->dmp_enable)
+		userCtrlReg |= BIT_DMP_EN;
+	else
+		userCtrlReg &= ~BIT_DMP_EN;
+
+	if (pdata->fifo_enable)
+		userCtrlReg |= BIT_FIFO_EN;
+	else
+		userCtrlReg &= ~BIT_FIFO_EN;
+
+	userCtrlReg |= BIT_DMP_RST;
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+				       MPUREG_USER_CTRL, userCtrlReg);
+	ERROR_CHECK(result);
+	pdata->dmp_is_running = pdata->dmp_enable;
+
+	return result;
+}
+
+static int MLDLSetI2CBypass(struct mldl_cfg *mldl_cfg,
+			    void *mlsl_handle,
+			    unsigned char enable)
+{
+	unsigned char b = 0;
+	int result;
+
+	if ((mldl_cfg->gyro_is_bypassed && enable) ||
+	    (!mldl_cfg->gyro_is_bypassed && !enable))
+		return ML_SUCCESS;
+
+	
+	result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
+				MPUREG_USER_CTRL, 1, &b);
+	ERROR_CHECK(result);
+
+	b &= ~BIT_AUX_IF_EN;
+
+	if (!enable) {
+		result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+					       MPUREG_USER_CTRL,
+					       (b | BIT_AUX_IF_EN));
+		ERROR_CHECK(result);
+	} else {
+		result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+					       MPUREG_AUX_SLV_ADDR, 0x7F);
+		ERROR_CHECK(result);
+		MLOSSleep(2);
+		result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+					       MPUREG_USER_CTRL, (b));
+		ERROR_CHECK(result);
+		MLOSSleep(SAMPLING_PERIOD_US(mldl_cfg) / 1000);
+		result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+					       MPUREG_AUX_SLV_ADDR,
+					       mldl_cfg->pdata->
+					       accel.address);
+		ERROR_CHECK(result);
+
+#ifdef M_HW
+		result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+					       MPUREG_USER_CTRL,
+					       (b | BIT_I2C_MST_RST));
+
+#else
+		result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+					       MPUREG_USER_CTRL,
+					       (b | BIT_AUX_IF_RST));
+#endif
+		ERROR_CHECK(result);
+		MLOSSleep(2);
+	}
+	mldl_cfg->gyro_is_bypassed = enable;
+
+	return result;
+}
+
+struct tsProdRevMap {
+	unsigned char siliconRev;
+	unsigned short sensTrim;
+};
+
+#define NUM_OF_PROD_REVS (DIM(prodRevsMap))
+
+#ifdef M_HW
+#define OLDEST_PROD_REV_SUPPORTED 1
+static struct tsProdRevMap prodRevsMap[] = {
+	{0, 0},
+	{MPU_SILICON_REV_A1, 131},	
+	{MPU_SILICON_REV_A1, 131},	
+	{MPU_SILICON_REV_A1, 131},	
+	{MPU_SILICON_REV_A1, 131},	
+	{MPU_SILICON_REV_A1, 131},	
+	{MPU_SILICON_REV_A1, 131},	
+	{MPU_SILICON_REV_A1, 131},	
+	{MPU_SILICON_REV_A1, 131},	
+};
+
+#else				
+#define OLDEST_PROD_REV_SUPPORTED 11
+
+static struct tsProdRevMap prodRevsMap[] = {
+	{0, 0},
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_A4, 131},	
+	{MPU_SILICON_REV_B1, 131},	
+	{MPU_SILICON_REV_B1, 131},	
+	{MPU_SILICON_REV_B1, 131},	
+	{MPU_SILICON_REV_B1, 131},	
+	{MPU_SILICON_REV_B4, 131},	
+	{MPU_SILICON_REV_B4, 131},	
+	{MPU_SILICON_REV_B4, 131},	
+	{MPU_SILICON_REV_B4, 131},	
+	{MPU_SILICON_REV_B4, 115},	
+	{MPU_SILICON_REV_B4, 115},	
+	{MPU_SILICON_REV_B6, 131},	
+	{MPU_SILICON_REV_B4, 115},	
+	{MPU_SILICON_REV_B6, 0},	
+	{MPU_SILICON_REV_B6, 0},	
+	{MPU_SILICON_REV_B6, 0},	
+	{MPU_SILICON_REV_B6, 131},	
+};
+#endif				
+
+static int MLDLGetSiliconRev(struct mldl_cfg *pdata,
+			     void *mlsl_handle)
+{
+	int result;
+	unsigned char index = 0x00;
+	unsigned char bank =
+	    (BIT_PRFTCH_EN | BIT_CFG_USER_BANK | MPU_MEM_OTP_BANK_0);
+	unsigned short memAddr = ((bank << 8) | 0x06);
+
+	result = MLSLSerialReadMem(mlsl_handle, pdata->addr,
+				   memAddr, 1, &index);
+	ERROR_CHECK(result)
+	if (result)
+		return result;
+	index >>= 2;
+
+	
+	result =
+	    MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+				  MPUREG_BANK_SEL, 0);
+	ERROR_CHECK(result)
+	if (result)
+		return result;
+
+	if (index < OLDEST_PROD_REV_SUPPORTED || NUM_OF_PROD_REVS <= index) {
+		pdata->silicon_revision = 0;
+		pdata->trim = 0;
+		MPL_LOGE("Unsupported Product Revision Detected : %d\n", index);
+		return ML_ERROR_INVALID_MODULE;
+	}
+
+	pdata->silicon_revision = prodRevsMap[index].siliconRev;
+	pdata->trim = prodRevsMap[index].sensTrim;
+
+	if (pdata->trim == 0) {
+		MPL_LOGE("sensitivity trim is 0"
+			 " - unsupported non production part.\n");
+		return ML_ERROR_INVALID_MODULE;
+	}
+
+	return result;
+}
+
+static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
+				  void *mlsl_handle,
+				  unsigned char enable)
+{
+#ifndef M_HW
+	int result;
+	unsigned char reg;
+	unsigned char mask;
+	unsigned char regval = 0;
+
+	if (0 == pdata->silicon_revision)
+		return ML_ERROR_INVALID_PARAMETER;
+
+	if ((pdata->silicon_revision & 0xf) < MPU_SILICON_REV_B6) {
+		reg = MPUREG_ACCEL_BURST_ADDR;
+		mask = 0x80;
+	} else {
+		reg = MPUREG_FIFO_EN2;
+		mask = 0x04;
+	}
+
+	result = MLSLSerialRead(mlsl_handle, pdata->addr, reg, 1, &regval);
+	if (result)
+		return result;
+
+	if (enable)
+		regval |= mask;
+	else
+		regval &= ~mask;
+
+	result =
+	    MLSLSerialWriteSingle(mlsl_handle, pdata->addr, reg, regval);
+
+	return result;
+#else
+	return ML_SUCCESS;
+#endif
+}
+
+
+#ifdef M_HW
+static tMLError mpu60xx_pwr_mgmt(struct mldl_cfg *pdata,
+				 void *mlsl_handle,
+				 unsigned char reset,
+				 unsigned char powerselection)
+{
+	unsigned char b;
+	tMLError result;
+
+	if (powerselection < 0 || powerselection > 7)
+		return ML_ERROR_INVALID_PARAMETER;
+
+	result =
+	    MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_1, 1,
+			   &b);
+	ERROR_CHECK(result);
+
+	b &= ~(BITS_PWRSEL);
+
+	if (reset) {
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+					       MPUREG_PWR_MGM, b | BIT_H_RESET);
+#define M_HW_RESET_ERRATTA
+#ifndef M_HW_RESET_ERRATTA
+		ERROR_CHECK(result);
+#else
+		MLOSSleep(50);
+#endif
+	}
+
+	b |= (powerselection << 4);
+
+	if (b & BITS_PWRSEL)
+		pdata->gyro_is_suspended = FALSE;
+	else
+		pdata->gyro_is_suspended = TRUE;
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+				       MPUREG_PWR_MGM, b);
+	ERROR_CHECK(result);
+
+	return ML_SUCCESS;
+}
+
+static tMLError MLDLStandByGyros(struct mldl_cfg *pdata,
+				 void *mlsl_handle,
+				 unsigned char disable_gx,
+				 unsigned char disable_gy,
+				 unsigned char disable_gz)
+{
+	unsigned char b;
+	tMLError result;
+
+	result =
+	    MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_2, 1,
+			   &b);
+	ERROR_CHECK(result);
+
+	b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
+	b |= (disable_gx << 2 | disable_gy << 1 | disable_gz);
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+				       MPUREG_PWR_MGMT_2, b);
+	ERROR_CHECK(result);
+
+	return ML_SUCCESS;
+}
+
+static tMLError MLDLStandByAccels(struct mldl_cfg *pdata,
+				  void *mlsl_handle,
+				  unsigned char disable_ax,
+				  unsigned char disable_ay,
+				  unsigned char disable_az)
+{
+	unsigned char b;
+	tMLError result;
+
+	result =
+	    MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_2, 1,
+			   &b);
+	ERROR_CHECK(result);
+
+	b &= ~(BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
+	b |= (disable_ax << 2 | disable_ay << 1 | disable_az);
+
+	result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+				       MPUREG_PWR_MGMT_2, b);
+	ERROR_CHECK(result);
+
+	return ML_SUCCESS;
+}
+
+#else				
+
+static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
+			    void *mlsl_handle,
+			    unsigned char reset,
+			    unsigned char sleep,
+			    unsigned char disable_gx,
+			    unsigned char disable_gy,
+			    unsigned char disable_gz)
+{
+	unsigned char b = 0;
+	int result;
+
+	result =
+	    MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGM, 1,
+			   &b);
+	ERROR_CHECK(result);
+
+	
+	if ((!(b & BIT_SLEEP)) && reset)
+		result = MLDLSetI2CBypass(pdata, mlsl_handle, 1);
+
+	
+	if ((!(b & BIT_SLEEP)) && sleep)
+		dmp_stop(pdata, mlsl_handle);
+
+	
+	if (reset) {
+		MPL_LOGV("Reset MPU3050\n");
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+					MPUREG_PWR_MGM, b | BIT_H_RESET);
+		ERROR_CHECK(result);
+		MLOSSleep(5);
+		pdata->gyro_needs_reset = FALSE;
+		result = MLSLSerialRead(mlsl_handle, pdata->addr,
+					MPUREG_PWR_MGM, 1, &b);
+		ERROR_CHECK(result);
+	}
+
+	
+	if (b & BIT_SLEEP)
+		pdata->gyro_is_suspended = TRUE;
+	else
+		pdata->gyro_is_suspended = FALSE;
+
+	
+	if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
+		(((sleep != 0) * BIT_SLEEP) |
+		((disable_gx != 0) * BIT_STBY_XG) |
+		((disable_gy != 0) * BIT_STBY_YG) |
+		((disable_gz != 0) * BIT_STBY_ZG))) {
+		return ML_SUCCESS;
+	}
+
+	if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
+		 (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)
+		&& ((!sleep) && disable_gx && disable_gy && disable_gz)) {
+		result = MLDLPowerMgmtMPU(pdata, mlsl_handle, 0, 1, 0, 0, 0);
+		if (result)
+			return result;
+		b |= BIT_SLEEP;
+		b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
+	}
+
+	if ((b & BIT_SLEEP) != ((sleep != 0) * BIT_SLEEP)) {
+		if (sleep) {
+			result = MLDLSetI2CBypass(pdata, mlsl_handle, 1);
+			ERROR_CHECK(result);
+			b |= BIT_SLEEP;
+			result =
+			    MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+						  MPUREG_PWR_MGM, b);
+			ERROR_CHECK(result);
+			pdata->gyro_is_suspended = TRUE;
+		} else {
+			b &= ~BIT_SLEEP;
+			result =
+			    MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+						  MPUREG_PWR_MGM, b);
+			ERROR_CHECK(result);
+			pdata->gyro_is_suspended = FALSE;
+			MLOSSleep(5);
+		}
+	}
+	if ((b & BIT_STBY_XG) != ((disable_gx != 0) * BIT_STBY_XG)) {
+		b ^= BIT_STBY_XG;
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+						MPUREG_PWR_MGM, b);
+		ERROR_CHECK(result);
+	}
+	if ((b & BIT_STBY_YG) != ((disable_gy != 0) * BIT_STBY_YG)) {
+		b ^= BIT_STBY_YG;
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+					       MPUREG_PWR_MGM, b);
+		ERROR_CHECK(result);
+	}
+	if ((b & BIT_STBY_ZG) != ((disable_gz != 0) * BIT_STBY_ZG)) {
+		b ^= BIT_STBY_ZG;
+		result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+					       MPUREG_PWR_MGM, b);
+		ERROR_CHECK(result);
+	}
+
+	return ML_SUCCESS;
+}
+#endif				
+
+
+void mpu_print_cfg(struct mldl_cfg *mldl_cfg)
+{
+	struct mpu3050_platform_data *pdata = mldl_cfg->pdata;
+	struct ext_slave_platform_data *accel = &mldl_cfg->pdata->accel;
+	struct ext_slave_platform_data *compass =
+	    &mldl_cfg->pdata->compass;
+	struct ext_slave_platform_data *pressure =
+	    &mldl_cfg->pdata->pressure;
+
+	MPL_LOGD("mldl_cfg.addr             = %02x\n", mldl_cfg->addr);
+	MPL_LOGD("mldl_cfg.int_config       = %02x\n",
+		 mldl_cfg->int_config);
+	MPL_LOGD("mldl_cfg.ext_sync         = %02x\n", mldl_cfg->ext_sync);
+	MPL_LOGD("mldl_cfg.full_scale       = %02x\n",
+		 mldl_cfg->full_scale);
+	MPL_LOGD("mldl_cfg.lpf              = %02x\n", mldl_cfg->lpf);
+	MPL_LOGD("mldl_cfg.clk_src          = %02x\n", mldl_cfg->clk_src);
+	MPL_LOGD("mldl_cfg.divider          = %02x\n", mldl_cfg->divider);
+	MPL_LOGD("mldl_cfg.dmp_enable       = %02x\n",
+		 mldl_cfg->dmp_enable);
+	MPL_LOGD("mldl_cfg.fifo_enable      = %02x\n",
+		 mldl_cfg->fifo_enable);
+	MPL_LOGD("mldl_cfg.dmp_cfg1         = %02x\n", mldl_cfg->dmp_cfg1);
+	MPL_LOGD("mldl_cfg.dmp_cfg2         = %02x\n", mldl_cfg->dmp_cfg2);
+	MPL_LOGD("mldl_cfg.offset_tc[0]     = %02x\n",
+		 mldl_cfg->offset_tc[0]);
+	MPL_LOGD("mldl_cfg.offset_tc[1]     = %02x\n",
+		 mldl_cfg->offset_tc[1]);
+	MPL_LOGD("mldl_cfg.offset_tc[2]     = %02x\n",
+		 mldl_cfg->offset_tc[2]);
+	MPL_LOGD("mldl_cfg.silicon_revision = %02x\n",
+		 mldl_cfg->silicon_revision);
+	MPL_LOGD("mldl_cfg.product_id       = %02x\n",
+		 mldl_cfg->product_id);
+	MPL_LOGD("mldl_cfg.trim             = %02x\n", mldl_cfg->trim);
+	MPL_LOGD("mldl_cfg.requested_sensors= %04lx\n",
+		 mldl_cfg->requested_sensors);
+
+	if (mldl_cfg->accel) {
+		MPL_LOGD("slave_accel->suspend      = %02x\n",
+			 (int) mldl_cfg->accel->suspend);
+		MPL_LOGD("slave_accel->resume       = %02x\n",
+			 (int) mldl_cfg->accel->resume);
+		MPL_LOGD("slave_accel->read         = %02x\n",
+			 (int) mldl_cfg->accel->read);
+		MPL_LOGD("slave_accel->type         = %02x\n",
+			 mldl_cfg->accel->type);
+		MPL_LOGD("slave_accel->reg          = %02x\n",
+			 mldl_cfg->accel->reg);
+		MPL_LOGD("slave_accel->len          = %02x\n",
+			 mldl_cfg->accel->len);
+		MPL_LOGD("slave_accel->endian       = %02x\n",
+			 mldl_cfg->accel->endian);
+		MPL_LOGD("slave_accel->range.mantissa= %02lx\n",
+			 mldl_cfg->accel->range.mantissa);
+		MPL_LOGD("slave_accel->range.fraction= %02lx\n",
+			 mldl_cfg->accel->range.fraction);
+	} else {
+		MPL_LOGD("slave_accel               = NULL\n");
+	}
+
+	if (mldl_cfg->compass) {
+		MPL_LOGD("slave_compass->suspend    = %02x\n",
+			 (int) mldl_cfg->compass->suspend);
+		MPL_LOGD("slave_compass->resume     = %02x\n",
+			 (int) mldl_cfg->compass->resume);
+		MPL_LOGD("slave_compass->read       = %02x\n",
+			 (int) mldl_cfg->compass->read);
+		MPL_LOGD("slave_compass->type       = %02x\n",
+			 mldl_cfg->compass->type);
+		MPL_LOGD("slave_compass->reg        = %02x\n",
+			 mldl_cfg->compass->reg);
+		MPL_LOGD("slave_compass->len        = %02x\n",
+			 mldl_cfg->compass->len);
+		MPL_LOGD("slave_compass->endian     = %02x\n",
+			 mldl_cfg->compass->endian);
+		MPL_LOGD("slave_compass->range.mantissa= %02lx\n",
+			 mldl_cfg->compass->range.mantissa);
+		MPL_LOGD("slave_compass->range.fraction= %02lx\n",
+			 mldl_cfg->compass->range.fraction);
+
+	} else {
+		MPL_LOGD("slave_compass             = NULL\n");
+	}
+
+	if (mldl_cfg->pressure) {
+		MPL_LOGD("slave_pressure->suspend    = %02x\n",
+			 (int) mldl_cfg->pressure->suspend);
+		MPL_LOGD("slave_pressure->resume     = %02x\n",
+			 (int) mldl_cfg->pressure->resume);
+		MPL_LOGD("slave_pressure->read       = %02x\n",
+			 (int) mldl_cfg->pressure->read);
+		MPL_LOGD("slave_pressure->type       = %02x\n",
+			 mldl_cfg->pressure->type);
+		MPL_LOGD("slave_pressure->reg        = %02x\n",
+			 mldl_cfg->pressure->reg);
+		MPL_LOGD("slave_pressure->len        = %02x\n",
+			 mldl_cfg->pressure->len);
+		MPL_LOGD("slave_pressure->endian     = %02x\n",
+			 mldl_cfg->pressure->endian);
+		MPL_LOGD("slave_pressure->range.mantissa= %02lx\n",
+			 mldl_cfg->pressure->range.mantissa);
+		MPL_LOGD("slave_pressure->range.fraction= %02lx\n",
+			 mldl_cfg->pressure->range.fraction);
+
+	} else {
+		MPL_LOGD("slave_pressure             = NULL\n");
+	}
+	MPL_LOGD("accel->get_slave_descr    = %x\n",
+		 (unsigned int) accel->get_slave_descr);
+	MPL_LOGD("accel->irq                = %02x\n", accel->irq);
+	MPL_LOGD("accel->adapt_num          = %02x\n", accel->adapt_num);
+	MPL_LOGD("accel->bus                = %02x\n", accel->bus);
+	MPL_LOGD("accel->address            = %02x\n", accel->address);
+	MPL_LOGD("accel->orientation        =\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n",
+		 accel->orientation[0], accel->orientation[1],
+		 accel->orientation[2], accel->orientation[3],
+		 accel->orientation[4], accel->orientation[5],
+		 accel->orientation[6], accel->orientation[7],
+		 accel->orientation[8]);
+	MPL_LOGD("compass->get_slave_descr  = %x\n",
+		 (unsigned int) compass->get_slave_descr);
+	MPL_LOGD("compass->irq              = %02x\n", compass->irq);
+	MPL_LOGD("compass->adapt_num        = %02x\n", compass->adapt_num);
+	MPL_LOGD("compass->bus              = %02x\n", compass->bus);
+	MPL_LOGD("compass->address          = %02x\n", compass->address);
+	MPL_LOGD("compass->orientation      =\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n",
+		 compass->orientation[0], compass->orientation[1],
+		 compass->orientation[2], compass->orientation[3],
+		 compass->orientation[4], compass->orientation[5],
+		 compass->orientation[6], compass->orientation[7],
+		 compass->orientation[8]);
+	MPL_LOGD("pressure->get_slave_descr  = %x\n",
+		 (unsigned int) pressure->get_slave_descr);
+	MPL_LOGD("pressure->irq             = %02x\n", pressure->irq);
+	MPL_LOGD("pressure->adapt_num       = %02x\n", pressure->adapt_num);
+	MPL_LOGD("pressure->bus             = %02x\n", pressure->bus);
+	MPL_LOGD("pressure->address         = %02x\n", pressure->address);
+	MPL_LOGD("pressure->orientation     =\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n",
+		 pressure->orientation[0], pressure->orientation[1],
+		 pressure->orientation[2], pressure->orientation[3],
+		 pressure->orientation[4], pressure->orientation[5],
+		 pressure->orientation[6], pressure->orientation[7],
+		 pressure->orientation[8]);
+
+	MPL_LOGD("pdata->int_config         = %02x\n", pdata->int_config);
+	MPL_LOGD("pdata->level_shifter      = %02x\n",
+		 pdata->level_shifter);
+	MPL_LOGD("pdata->orientation        =\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n"
+		 "                            %2d %2d %2d\n",
+		 pdata->orientation[0], pdata->orientation[1],
+		 pdata->orientation[2], pdata->orientation[3],
+		 pdata->orientation[4], pdata->orientation[5],
+		 pdata->orientation[6], pdata->orientation[7],
+		 pdata->orientation[8]);
+
+	MPL_LOGD("Struct sizes: mldl_cfg: %d, "
+		 "ext_slave_descr:%d, "
+		 "mpu3050_platform_data:%d: RamOffset: %d\n",
+		 sizeof(struct mldl_cfg), sizeof(struct ext_slave_descr),
+		 sizeof(struct mpu3050_platform_data),
+		 offsetof(struct mldl_cfg, ram));
+}
+
+int mpu_set_slave(struct mldl_cfg *mldl_cfg,
+		void *gyro_handle,
+		struct ext_slave_descr *slave,
+		struct ext_slave_platform_data *slave_pdata)
+{
+	int result;
+	unsigned char reg = 0;
+	unsigned char slave_reg;
+	unsigned char slave_len;
+	unsigned char slave_endian;
+	unsigned char slave_address;
+
+	result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
+
+	if (NULL == slave || NULL == slave_pdata) {
+		slave_reg = 0;
+		slave_len = 0;
+		slave_endian = 0;
+		slave_address = 0;
+	} else {
+		slave_reg = slave->reg;
+		slave_len = slave->len;
+		slave_endian = slave->endian;
+		slave_address = slave_pdata->address;
+	}
+
+	
+	result = MLSLSerialWriteSingle(gyro_handle,
+				mldl_cfg->addr,
+				MPUREG_AUX_SLV_ADDR,
+				slave_address);
+	ERROR_CHECK(result);
+	
+	result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
+				MPUREG_ACCEL_BURST_ADDR, 1,
+				&reg);
+	ERROR_CHECK(result);
+	reg = ((reg & 0x80) | slave_reg);
+	result = MLSLSerialWriteSingle(gyro_handle,
+				mldl_cfg->addr,
+				MPUREG_ACCEL_BURST_ADDR,
+				reg);
+	ERROR_CHECK(result);
+
+#ifdef M_HW
+	
+	if (slave_len > BITS_SLV_LENG) {
+		MPL_LOGW("Limiting slave burst read length to "
+			"the allowed maximum (15B, req. %d)\n",
+			slave_len);
+		slave_len = BITS_SLV_LENG;
+	}
+	reg = slave_len;
+	if (slave_endian == EXT_SLAVE_LITTLE_ENDIAN)
+		reg |= BIT_SLV_BYTE_SW;
+	reg |= BIT_SLV_GRP;
+	reg |= BIT_SLV_ENABLE;
+
+	result = MLSLSerialWriteSingle(gyro_handle,
+				mldl_cfg->addr,
+				MPUREG_I2C_SLV0_CTRL,
+				reg);
+#else
+	
+	result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
+				MPUREG_USER_CTRL, 1, &reg);
+	ERROR_CHECK(result);
+	reg = (reg & ~BIT_AUX_RD_LENG);
+	result = MLSLSerialWriteSingle(gyro_handle,
+				mldl_cfg->addr,
+				MPUREG_USER_CTRL, reg);
+	ERROR_CHECK(result);
+#endif
+
+	if (slave_address) {
+		result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, FALSE);
+		ERROR_CHECK(result);
+	}
+	return result;
+}
+
+static int mpu_was_reset(struct mldl_cfg *mldl_cfg, void *gyro_handle)
+{
+	int result = ML_SUCCESS;
+	unsigned char reg = 0;
+
+	result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
+				MPUREG_DMP_CFG_2, 1, &reg);
+	ERROR_CHECK(result);
+
+	if (mldl_cfg->dmp_cfg2 != reg)
+		return TRUE;
+
+	if (0 != mldl_cfg->dmp_cfg1)
+		return FALSE;
+
+	result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
+				MPUREG_SMPLRT_DIV, 1, &reg);
+	ERROR_CHECK(result);
+	if (reg != mldl_cfg->divider)
+		return TRUE;
+
+	if (0 != mldl_cfg->divider)
+		return FALSE;
+
+	
+	return TRUE;
+}
+
+static int gyro_resume(struct mldl_cfg *mldl_cfg, void *gyro_handle)
+{
+	int result;
+	int ii;
+	int jj;
+	unsigned char reg = 0;
+	unsigned char regs[7];
+
+	
+#ifdef M_HW
+	result = mpu60xx_pwr_mgmt(mldl_cfg, gyro_handle, RESET,
+				WAKE_UP);
+	ERROR_CHECK(result);
+
+	
+	result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, 1);
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_INT_PIN_CFG,
+				(mldl_cfg->pdata->int_config |
+					BIT_BYPASS_EN));
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_INT_ENABLE,
+				(mldl_cfg->int_config));
+	ERROR_CHECK(result);
+#else
+	result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle, 0, 0,
+				mldl_cfg->gyro_power & BIT_STBY_XG,
+				mldl_cfg->gyro_power & BIT_STBY_YG,
+				mldl_cfg->gyro_power & BIT_STBY_ZG);
+
+	if (!mldl_cfg->gyro_needs_reset &&
+	    !mpu_was_reset(mldl_cfg, gyro_handle)) {
+		return ML_SUCCESS;
+	}
+
+	result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle, 1, 0,
+				mldl_cfg->gyro_power & BIT_STBY_XG,
+				mldl_cfg->gyro_power & BIT_STBY_YG,
+				mldl_cfg->gyro_power & BIT_STBY_ZG);
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_INT_CFG,
+				(mldl_cfg->int_config |
+					mldl_cfg->pdata->int_config));
+	ERROR_CHECK(result);
+#endif
+
+	result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
+				MPUREG_PWR_MGM, 1, &reg);
+	ERROR_CHECK(result);
+	reg &= ~BITS_CLKSEL;
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_PWR_MGM,
+				mldl_cfg->clk_src | reg);
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_SMPLRT_DIV,
+				mldl_cfg->divider);
+	ERROR_CHECK(result);
+
+#ifdef M_HW
+	reg = DLPF_FS_SYNC_VALUE(0, mldl_cfg->full_scale, 0);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_GYRO_CONFIG, reg);
+	reg = DLPF_FS_SYNC_VALUE(mldl_cfg->ext_sync, 0, mldl_cfg->lpf);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_CONFIG, reg);
+#else
+	reg = DLPF_FS_SYNC_VALUE(mldl_cfg->ext_sync,
+				mldl_cfg->full_scale, mldl_cfg->lpf);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_DLPF_FS_SYNC, reg);
+#endif
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_DMP_CFG_1,
+				mldl_cfg->dmp_cfg1);
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_DMP_CFG_2,
+				mldl_cfg->dmp_cfg2);
+	ERROR_CHECK(result);
+
+	
+	for (ii = 0; ii < MPU_MEM_NUM_RAM_BANKS; ii++) {
+		unsigned char read[MPU_MEM_BANK_SIZE] = {0};
+
+		result = MLSLSerialWriteMem(gyro_handle,
+					mldl_cfg->addr,
+					((ii << 8) | 0x00),
+					MPU_MEM_BANK_SIZE,
+					mldl_cfg->ram[ii]);
+		ERROR_CHECK(result);
+		result = MLSLSerialReadMem(gyro_handle, mldl_cfg->addr,
+					((ii << 8) | 0x00),
+					MPU_MEM_BANK_SIZE, read);
+		ERROR_CHECK(result);
+
+#ifdef M_HW
+#define ML_SKIP_CHECK 38
+#else
+#define ML_SKIP_CHECK 20
+#endif
+		for (jj = 0; jj < MPU_MEM_BANK_SIZE; jj++) {
+			
+			if (ii == 0 && jj < ML_SKIP_CHECK)
+				continue;
+			if (mldl_cfg->ram[ii][jj] != read[jj]) {
+				result = ML_ERROR_SERIAL_WRITE;
+				break;
+			}
+		}
+		ERROR_CHECK(result);
+	}
+
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_XG_OFFS_TC,
+				mldl_cfg->offset_tc[0]);
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_YG_OFFS_TC,
+				mldl_cfg->offset_tc[1]);
+	ERROR_CHECK(result);
+	result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
+				MPUREG_ZG_OFFS_TC,
+				mldl_cfg->offset_tc[2]);
+	ERROR_CHECK(result);
+
+	regs[0] = MPUREG_X_OFFS_USRH;
+	for (ii = 0; ii < DIM(mldl_cfg->offset); ii++) {
+		regs[1 + ii * 2] =
+			(unsigned char)(mldl_cfg->offset[ii] >> 8)
+			& 0xff;
+		regs[1 + ii * 2 + 1] =
+			(unsigned char)(mldl_cfg->offset[ii] & 0xff);
+	}
+	result = MLSLSerialWrite(gyro_handle, mldl_cfg->addr, 7, regs);
+	ERROR_CHECK(result);
+
+	
+	result = MLDLSetLevelShifterBit(mldl_cfg, gyro_handle,
+					mldl_cfg->pdata->level_shifter);
+	ERROR_CHECK(result);
+	return result;
+}
+
+int mpu3050_open(struct mldl_cfg *mldl_cfg,
+		 void *mlsl_handle,
+		 void *accel_handle,
+		 void *compass_handle,
+		 void *pressure_handle)
+{
+	int result;
+	
+	mldl_cfg->int_config = BIT_INT_ANYRD_2CLEAR | BIT_DMP_INT_EN;
+	mldl_cfg->clk_src = MPU_CLK_SEL_PLLGYROZ;
+	mldl_cfg->lpf = MPU_FILTER_42HZ;
+	mldl_cfg->full_scale = MPU_FS_2000DPS;
+	mldl_cfg->divider = 4;
+	mldl_cfg->dmp_enable = 1;
+	mldl_cfg->fifo_enable = 1;
+	mldl_cfg->ext_sync = 0;
+	mldl_cfg->dmp_cfg1 = 0;
+	mldl_cfg->dmp_cfg2 = 0;
+	mldl_cfg->gyro_power = 0;
+	mldl_cfg->gyro_is_bypassed = TRUE;
+	mldl_cfg->dmp_is_running = FALSE;
+	mldl_cfg->gyro_is_suspended = TRUE;
+	mldl_cfg->accel_is_suspended = TRUE;
+	mldl_cfg->compass_is_suspended = TRUE;
+	mldl_cfg->pressure_is_suspended = TRUE;
+	mldl_cfg->gyro_needs_reset = FALSE;
+	if (mldl_cfg->addr == 0) {
+#ifdef __KERNEL__
+		return ML_ERROR_INVALID_PARAMETER;
+#else
+		mldl_cfg->addr = 0x68;
+#endif
+	}
+
+#ifdef M_HW
+	result = mpu60xx_pwr_mgmt(mldl_cfg, mlsl_handle,
+				  RESET, WAKE_UP);
+#else
+	result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, RESET, 0, 0, 0, 0);
+#endif
+	ERROR_CHECK(result);
+
+	result = MLDLGetSiliconRev(mldl_cfg, mlsl_handle);
+	ERROR_CHECK(result);
+#ifndef M_HW
+	result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
+				MPUREG_PRODUCT_ID, 1,
+				&mldl_cfg->product_id);
+	ERROR_CHECK(result);
+#endif
+
+	
+	result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
+				MPUREG_XG_OFFS_TC, 1,
+				&mldl_cfg->offset_tc[0]);
+	ERROR_CHECK(result);
+	result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
+				MPUREG_YG_OFFS_TC, 1,
+				&mldl_cfg->offset_tc[1]);
+	ERROR_CHECK(result);
+	result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
+				MPUREG_ZG_OFFS_TC, 1,
+				&mldl_cfg->offset_tc[2]);
+	ERROR_CHECK(result);
+
+	
+#ifdef M_HW
+	result = mpu60xx_pwr_mgmt(mldl_cfg, mlsl_handle,
+				  FALSE, SLEEP);
+#else
+	result =
+	    MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 0, SLEEP, 0, 0, 0);
+#endif
+	ERROR_CHECK(result);
+
+	if (mldl_cfg->accel && mldl_cfg->accel->init) {
+		result = mldl_cfg->accel->init(accel_handle,
+					       mldl_cfg->accel,
+					       &mldl_cfg->pdata->accel);
+		ERROR_CHECK(result);
+	}
+
+	if (mldl_cfg->compass && mldl_cfg->compass->init) {
+		result = mldl_cfg->compass->init(compass_handle,
+						 mldl_cfg->compass,
+						 &mldl_cfg->pdata->compass);
+		if (ML_SUCCESS != result) {
+			MPL_LOGE("mldl_cfg->compass->init returned %d\n",
+				result);
+			goto out_accel;
+		}
+	}
+	if (mldl_cfg->pressure && mldl_cfg->pressure->init) {
+		result = mldl_cfg->pressure->init(pressure_handle,
+						  mldl_cfg->pressure,
+						  &mldl_cfg->pdata->pressure);
+		if (ML_SUCCESS != result) {
+			MPL_LOGE("mldl_cfg->pressure->init returned %d\n",
+				result);
+			goto out_compass;
+		}
+	}
+
+	mldl_cfg->requested_sensors = ML_THREE_AXIS_GYRO;
+	if (mldl_cfg->accel && mldl_cfg->accel->resume)
+		mldl_cfg->requested_sensors |= ML_THREE_AXIS_ACCEL;
+
+	if (mldl_cfg->compass && mldl_cfg->compass->resume)
+		mldl_cfg->requested_sensors |= ML_THREE_AXIS_COMPASS;
+
+	if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
+		mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
+
+	return result;
+
+out_compass:
+	if (mldl_cfg->compass->init)
+		mldl_cfg->compass->exit(compass_handle,
+				mldl_cfg->compass,
+				&mldl_cfg->pdata->compass);
+out_accel:
+	if (mldl_cfg->accel->init)
+		mldl_cfg->accel->exit(accel_handle,
+				mldl_cfg->accel,
+				&mldl_cfg->pdata->accel);
+	return result;
+
+}
+
+int mpu3050_close(struct mldl_cfg *mldl_cfg,
+		  void *mlsl_handle,
+		  void *accel_handle,
+		  void *compass_handle,
+		  void *pressure_handle)
+{
+	int result = ML_SUCCESS;
+	int ret_result = ML_SUCCESS;
+
+	if (mldl_cfg->accel && mldl_cfg->accel->exit) {
+		result = mldl_cfg->accel->exit(accel_handle,
+					mldl_cfg->accel,
+					&mldl_cfg->pdata->accel);
+		if (ML_SUCCESS != result)
+			MPL_LOGE("Accel exit failed %d\n", result);
+		ret_result = result;
+	}
+	if (ML_SUCCESS == ret_result)
+		ret_result = result;
+
+	if (mldl_cfg->compass && mldl_cfg->compass->exit) {
+		result = mldl_cfg->compass->exit(compass_handle,
+						mldl_cfg->compass,
+						&mldl_cfg->pdata->compass);
+		if (ML_SUCCESS != result)
+			MPL_LOGE("Compass exit failed %d\n", result);
+	}
+	if (ML_SUCCESS == ret_result)
+		ret_result = result;
+
+	if (mldl_cfg->pressure && mldl_cfg->pressure->exit) {
+		result = mldl_cfg->pressure->exit(pressure_handle,
+						mldl_cfg->pressure,
+						&mldl_cfg->pdata->pressure);
+		if (ML_SUCCESS != result)
+			MPL_LOGE("Pressure exit failed %d\n", result);
+	}
+	if (ML_SUCCESS == ret_result)
+		ret_result = result;
+
+	return ret_result;
+}
+
+int mpu3050_resume(struct mldl_cfg *mldl_cfg,
+		   void *gyro_handle,
+		   void *accel_handle,
+		   void *compass_handle,
+		   void *pressure_handle,
+		   bool resume_gyro,
+		   bool resume_accel,
+		   bool resume_compass,
+		   bool resume_pressure)
+{
+	int result = ML_SUCCESS;
+
+#ifdef CONFIG_MPU_SENSORS_DEBUG
+	mpu_print_cfg(mldl_cfg);
+#endif
+
+	if (resume_accel &&
+	    ((!mldl_cfg->accel) || (!mldl_cfg->accel->resume)))
+		return ML_ERROR_INVALID_PARAMETER;
+	if (resume_compass &&
+	    ((!mldl_cfg->compass) || (!mldl_cfg->compass->resume)))
+		return ML_ERROR_INVALID_PARAMETER;
+	if (resume_pressure &&
+	    ((!mldl_cfg->pressure) || (!mldl_cfg->pressure->resume)))
+		return ML_ERROR_INVALID_PARAMETER;
+
+	if (resume_gyro && mldl_cfg->gyro_is_suspended) {
+		result = gyro_resume(mldl_cfg, gyro_handle);
+		ERROR_CHECK(result);
+	}
+
+	if (resume_accel && mldl_cfg->accel_is_suspended) {
+		if (!mldl_cfg->gyro_is_suspended &&
+		    EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
+			result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
+			ERROR_CHECK(result);
+		}
+		result = mldl_cfg->accel->resume(accel_handle,
+						 mldl_cfg->accel,
+						 &mldl_cfg->pdata->accel);
+		ERROR_CHECK(result);
+		mldl_cfg->accel_is_suspended = FALSE;
+	}
+
+	if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->accel_is_suspended &&
+		EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
+		result = mpu_set_slave(mldl_cfg,
+				gyro_handle,
+				mldl_cfg->accel,
+				&mldl_cfg->pdata->accel);
+		ERROR_CHECK(result);
+	}
+
+	if (resume_compass && mldl_cfg->compass_is_suspended) {
+		if (!mldl_cfg->gyro_is_suspended &&
+		    EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
+			result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
+			ERROR_CHECK(result);
+		}
+		result = mldl_cfg->compass->resume(compass_handle,
+						   mldl_cfg->compass,
+						   &mldl_cfg->pdata->
+						   compass);
+		ERROR_CHECK(result);
+		mldl_cfg->compass_is_suspended = FALSE;
+	}
+
+	if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->compass_is_suspended &&
+		EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
+		result = mpu_set_slave(mldl_cfg,
+				gyro_handle,
+				mldl_cfg->compass,
+				&mldl_cfg->pdata->compass);
+		ERROR_CHECK(result);
+	}
+
+	if (resume_pressure && mldl_cfg->pressure_is_suspended) {
+		if (!mldl_cfg->gyro_is_suspended &&
+		    EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
+			result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
+			ERROR_CHECK(result);
+		}
+		result = mldl_cfg->pressure->resume(pressure_handle,
+						    mldl_cfg->pressure,
+						    &mldl_cfg->pdata->
+						    pressure);
+		ERROR_CHECK(result);
+		mldl_cfg->pressure_is_suspended = FALSE;
+	}
+
+	if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->pressure_is_suspended &&
+		EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
+		result = mpu_set_slave(mldl_cfg,
+				gyro_handle,
+				mldl_cfg->pressure,
+				&mldl_cfg->pdata->pressure);
+		ERROR_CHECK(result);
+	}
+
+	
+	if (resume_gyro) {
+		result = dmp_start(mldl_cfg, gyro_handle);
+		ERROR_CHECK(result);
+	}
+
+	return result;
+}
+
+int mpu3050_suspend(struct mldl_cfg *mldl_cfg,
+		    void *gyro_handle,
+		    void *accel_handle,
+		    void *compass_handle,
+		    void *pressure_handle,
+		    bool suspend_gyro,
+		    bool suspend_accel,
+		    bool suspend_compass,
+		    bool suspend_pressure)
+{
+	int result = ML_SUCCESS;
+
+	if (suspend_gyro && !mldl_cfg->gyro_is_suspended) {
+#ifdef M_HW
+		return ML_SUCCESS;
+		
+		result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, 1);
+		ERROR_CHECK(result);
+		result = mpu60xx_pwr_mgmt(mldl_cfg, gyro_handle, 0, SLEEP);
+#else
+		result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle,
+					0, SLEEP, 0, 0, 0);
+#endif
+		ERROR_CHECK(result);
+	}
+
+	if (!mldl_cfg->accel_is_suspended && suspend_accel &&
+	    mldl_cfg->accel && mldl_cfg->accel->suspend) {
+		if (!mldl_cfg->gyro_is_suspended &&
+		    EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
+			result = mpu_set_slave(mldl_cfg, gyro_handle,
+					       NULL, NULL);
+			ERROR_CHECK(result);
+		}
+		result = mldl_cfg->accel->suspend(accel_handle,
+						  mldl_cfg->accel,
+						  &mldl_cfg->pdata->accel);
+		ERROR_CHECK(result);
+		mldl_cfg->accel_is_suspended = TRUE;
+	}
+
+	if (!mldl_cfg->compass_is_suspended && suspend_compass &&
+	    mldl_cfg->compass && mldl_cfg->compass->suspend) {
+		if (!mldl_cfg->gyro_is_suspended &&
+		    EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
+			result = mpu_set_slave(mldl_cfg, gyro_handle,
+					       NULL, NULL);
+			ERROR_CHECK(result);
+		}
+		result = mldl_cfg->compass->suspend(compass_handle,
+						    mldl_cfg->compass,
+						    &mldl_cfg->
+						    pdata->compass);
+		ERROR_CHECK(result);
+		mldl_cfg->compass_is_suspended = TRUE;
+	}
+
+	if (!mldl_cfg->pressure_is_suspended && suspend_pressure &&
+	    mldl_cfg->pressure && mldl_cfg->pressure->suspend) {
+		if (!mldl_cfg->gyro_is_suspended &&
+		    EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
+			result = mpu_set_slave(mldl_cfg, gyro_handle,
+					       NULL, NULL);
+			ERROR_CHECK(result);
+		}
+		result = mldl_cfg->pressure->suspend(pressure_handle,
+						    mldl_cfg->pressure,
+						    &mldl_cfg->
+						    pdata->pressure);
+		ERROR_CHECK(result);
+		mldl_cfg->pressure_is_suspended = TRUE;
+	}
+	return result;
+}
+
+
+int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
+		       void *accel_handle, unsigned char *data)
+{
+	if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->read)
+		if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus)
+			&& (!mldl_cfg->gyro_is_bypassed))
+			return ML_ERROR_FEATURE_NOT_ENABLED;
+		else
+			return mldl_cfg->accel->read(accel_handle,
+						     mldl_cfg->accel,
+						     &mldl_cfg->pdata->accel,
+						     data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
+			 void *compass_handle, unsigned char *data)
+{
+	if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->read)
+		if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus)
+			&& (!mldl_cfg->gyro_is_bypassed))
+			return ML_ERROR_FEATURE_NOT_ENABLED;
+		else
+			return mldl_cfg->compass->read(compass_handle,
+						mldl_cfg->compass,
+						&mldl_cfg->pdata->compass,
+						data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+int mpu3050_read_pressure(struct mldl_cfg *mldl_cfg,
+			 void *pressure_handle, unsigned char *data)
+{
+	if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->read)
+		if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus)
+			&& (!mldl_cfg->gyro_is_bypassed))
+			return ML_ERROR_FEATURE_NOT_ENABLED;
+		else
+			return mldl_cfg->pressure->read(
+				pressure_handle,
+				mldl_cfg->pressure,
+				&mldl_cfg->pdata->pressure,
+				data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+int mpu3050_config_accel(struct mldl_cfg *mldl_cfg,
+			void *accel_handle,
+			struct ext_slave_config *data)
+{
+	if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->config)
+		return mldl_cfg->accel->config(accel_handle,
+					       mldl_cfg->accel,
+					       &mldl_cfg->pdata->accel,
+					       data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+}
+
+int mpu3050_config_compass(struct mldl_cfg *mldl_cfg,
+			void *compass_handle,
+			struct ext_slave_config *data)
+{
+	if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->config)
+		return mldl_cfg->compass->config(compass_handle,
+						 mldl_cfg->compass,
+						 &mldl_cfg->pdata->compass,
+						 data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+}
+
+int mpu3050_config_pressure(struct mldl_cfg *mldl_cfg,
+			void *pressure_handle,
+			struct ext_slave_config *data)
+{
+	if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->config)
+		return mldl_cfg->pressure->config(pressure_handle,
+						  mldl_cfg->pressure,
+						  &mldl_cfg->pdata->pressure,
+						  data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+int mpu3050_get_config_accel(struct mldl_cfg *mldl_cfg,
+			void *accel_handle,
+			struct ext_slave_config *data)
+{
+	if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->get_config)
+		return mldl_cfg->accel->get_config(accel_handle,
+						mldl_cfg->accel,
+						&mldl_cfg->pdata->accel,
+						data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+}
+
+int mpu3050_get_config_compass(struct mldl_cfg *mldl_cfg,
+			void *compass_handle,
+			struct ext_slave_config *data)
+{
+	if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->get_config)
+		return mldl_cfg->compass->get_config(compass_handle,
+						mldl_cfg->compass,
+						&mldl_cfg->pdata->compass,
+						data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+}
+
+int mpu3050_get_config_pressure(struct mldl_cfg *mldl_cfg,
+				void *pressure_handle,
+				struct ext_slave_config *data)
+{
+	if (NULL != mldl_cfg->pressure &&
+	    NULL != mldl_cfg->pressure->get_config)
+		return mldl_cfg->pressure->get_config(pressure_handle,
+						mldl_cfg->pressure,
+						&mldl_cfg->pdata->pressure,
+						data);
+	else
+		return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+
diff --git a/drivers/input/misc/mpu3050/mldl_cfg.h b/drivers/input/misc/mpu3050/mldl_cfg.h
new file mode 100644
index 0000000..f838565
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mldl_cfg.h
@@ -0,0 +1,178 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+
+#ifndef __MLDL_CFG_H__
+#define __MLDL_CFG_H__
+
+
+#include "mlsl.h"
+#include "mpu.h"
+
+
+    
+    
+    
+
+#define ML_X_GYRO			(0x0001)
+#define ML_Y_GYRO			(0x0002)
+#define ML_Z_GYRO			(0x0004)
+#define ML_DMP_PROCESSOR		(0x0008)
+
+#define ML_X_ACCEL			(0x0010)
+#define ML_Y_ACCEL			(0x0020)
+#define ML_Z_ACCEL			(0x0040)
+
+#define ML_X_COMPASS			(0x0080)
+#define ML_Y_COMPASS			(0x0100)
+#define ML_Z_COMPASS			(0x0200)
+
+#define ML_X_PRESSURE			(0x0300)
+#define ML_Y_PRESSURE			(0x0800)
+#define ML_Z_PRESSURE			(0x1000)
+
+#define ML_TEMPERATURE			(0x2000)
+#define ML_TIME				(0x4000)
+
+#define ML_THREE_AXIS_GYRO		(0x000F)
+#define ML_THREE_AXIS_ACCEL		(0x0070)
+#define ML_THREE_AXIS_COMPASS		(0x0380)
+#define ML_THREE_AXIS_PRESSURE		(0x1C00)
+
+#define ML_FIVE_AXIS			(0x007B)
+#define ML_SIX_AXIS_GYRO_ACCEL		(0x007F)
+#define ML_SIX_AXIS_ACCEL_COMPASS	(0x03F0)
+#define ML_NINE_AXIS			(0x03FF)
+#define ML_ALL_SENSORS			(0x7FFF)
+
+#define SAMPLING_RATE_HZ(mldl_cfg)					\
+	((((((mldl_cfg)->lpf) == 0) || (((mldl_cfg)->lpf) == 7))	\
+		? (8000)						\
+		: (1000))						\
+		/ ((mldl_cfg)->divider + 1))
+
+#define SAMPLING_PERIOD_US(mldl_cfg)					\
+	((1000000L * ((mldl_cfg)->divider + 1)) /			\
+	(((((mldl_cfg)->lpf) == 0) || (((mldl_cfg)->lpf) == 7))		\
+		? (8000)						\
+		: (1000)))
+
+struct mldl_cfg {
+	
+	unsigned long requested_sensors;
+	unsigned char addr;
+	unsigned char int_config;
+	unsigned char ext_sync;
+	unsigned char full_scale;
+	unsigned char lpf;
+	unsigned char clk_src;
+	unsigned char divider;
+	unsigned char dmp_enable;
+	unsigned char fifo_enable;
+	unsigned char dmp_cfg1;
+	unsigned char dmp_cfg2;
+	unsigned char gyro_power;
+	unsigned char offset_tc[MPU_NUM_AXES];
+	unsigned short offset[MPU_NUM_AXES];
+	unsigned char ram[MPU_MEM_NUM_RAM_BANKS][MPU_MEM_BANK_SIZE];
+
+	
+	unsigned char silicon_revision;
+	unsigned char product_id;
+	unsigned short trim;
+
+	
+	int gyro_is_bypassed;
+	int dmp_is_running;
+	int gyro_is_suspended;
+	int accel_is_suspended;
+	int compass_is_suspended;
+	int pressure_is_suspended;
+	int gyro_needs_reset;
+
+	
+	struct ext_slave_descr *accel;
+	struct ext_slave_descr *compass;
+	struct ext_slave_descr *pressure;
+
+	
+	struct mpu3050_platform_data *pdata;
+};
+
+
+int mpu3050_open(struct mldl_cfg *mldl_cfg,
+		 void *mlsl_handle,
+		 void *accel_handle,
+		 void *compass_handle,
+		 void *pressure_handle);
+int mpu3050_close(struct mldl_cfg *mldl_cfg,
+		  void *mlsl_handle,
+		  void *accel_handle,
+		  void *compass_handle,
+		  void *pressure_handle);
+int mpu3050_resume(struct mldl_cfg *mldl_cfg,
+		   void *gyro_handle,
+		   void *accel_handle,
+		   void *compass_handle,
+		   void *pressure_handle,
+		   bool resume_gyro,
+		   bool resume_accel,
+		   bool resume_compass,
+		   bool resume_pressure);
+int mpu3050_suspend(struct mldl_cfg *mldl_cfg,
+		    void *gyro_handle,
+		    void *accel_handle,
+		    void *compass_handle,
+		    void *pressure_handle,
+		    bool suspend_gyro,
+		    bool suspend_accel,
+		    bool suspend_compass,
+		    bool suspend_pressure);
+int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
+		       void *accel_handle,
+		       unsigned char *data);
+int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
+			 void *compass_handle,
+			 unsigned char *data);
+int mpu3050_read_pressure(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+			  unsigned char *data);
+
+int mpu3050_config_accel(struct mldl_cfg *mldl_cfg,
+			 void *accel_handle,
+			 struct ext_slave_config *data);
+int mpu3050_config_compass(struct mldl_cfg *mldl_cfg,
+			   void *compass_handle,
+			   struct ext_slave_config *data);
+int mpu3050_config_pressure(struct mldl_cfg *mldl_cfg,
+			    void *pressure_handle,
+			    struct ext_slave_config *data);
+
+int mpu3050_get_config_accel(struct mldl_cfg *mldl_cfg,
+			     void *accel_handle,
+			     struct ext_slave_config *data);
+int mpu3050_get_config_compass(struct mldl_cfg *mldl_cfg,
+			       void *compass_handle,
+			       struct ext_slave_config *data);
+int mpu3050_get_config_pressure(struct mldl_cfg *mldl_cfg,
+				void *pressure_handle,
+				struct ext_slave_config *data);
+
+
+#endif				
+
diff --git a/drivers/input/misc/mpu3050/mlos-kernel.c b/drivers/input/misc/mpu3050/mlos-kernel.c
new file mode 100644
index 0000000..22c5e07
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mlos-kernel.c
@@ -0,0 +1,79 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#include "mlos.h"
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+void *MLOSMalloc(unsigned int numBytes)
+{
+	return kmalloc(numBytes, GFP_KERNEL);
+}
+
+tMLError MLOSFree(void *ptr)
+{
+	kfree(ptr);
+	return ML_SUCCESS;
+}
+
+tMLError MLOSCreateMutex(HANDLE *mutex)
+{
+	
+	return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+tMLError MLOSLockMutex(HANDLE mutex)
+{
+	
+	return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+tMLError MLOSUnlockMutex(HANDLE mutex)
+{
+	
+	return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+tMLError MLOSDestroyMutex(HANDLE handle)
+{
+	
+	return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+FILE *MLOSFOpen(char *filename)
+{
+	
+	return NULL;
+}
+
+void MLOSFClose(FILE *fp)
+{
+	
+}
+
+void MLOSSleep(int mSecs)
+{
+	msleep(mSecs);
+}
+
+unsigned long MLOSGetTickCount(void)
+{
+	
+	return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
diff --git a/drivers/input/misc/mpu3050/mlos.h b/drivers/input/misc/mpu3050/mlos.h
new file mode 100644
index 0000000..c0668574
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mlos.h
@@ -0,0 +1,73 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef _MLOS_H
+#define _MLOS_H
+
+#ifndef __KERNEL__
+#include <stdio.h>
+#endif
+
+#include "mltypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	
+	
+	
+
+	
+
+#define MLOS_GENERIC_READ         ((unsigned int)0x80000000)
+#define MLOS_GENERIC_WRITE        ((unsigned int)0x40000000)
+#define MLOS_FILE_SHARE_READ      ((unsigned int)0x00000001)
+#define MLOS_FILE_SHARE_WRITE     ((unsigned int)0x00000002)
+#define MLOS_OPEN_EXISTING        ((unsigned int)0x00000003)
+
+	
+	
+	
+
+	
+	
+	
+
+	
+	
+	
+
+	void *MLOSMalloc(unsigned int numBytes);
+	tMLError MLOSFree(void *ptr);
+	tMLError MLOSCreateMutex(HANDLE *mutex);
+	tMLError MLOSLockMutex(HANDLE mutex);
+	tMLError MLOSUnlockMutex(HANDLE mutex);
+	FILE *MLOSFOpen(char *filename);
+	void MLOSFClose(FILE *fp);
+
+	tMLError MLOSDestroyMutex(HANDLE handle);
+
+	void MLOSSleep(int mSecs);
+	unsigned long MLOSGetTickCount(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif				
diff --git a/drivers/input/misc/mpu3050/mlsl-kernel.c b/drivers/input/misc/mpu3050/mlsl-kernel.c
new file mode 100644
index 0000000..d5bc256
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mlsl-kernel.c
@@ -0,0 +1,229 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#include "mlsl.h"
+#include "mpu-i2c.h"
+
+
+
+
+tMLError MLSLSerialOpen(char const *port, void **sl_handle)
+{
+	return ML_SUCCESS;
+}
+
+tMLError MLSLSerialReset(void *sl_handle)
+{
+	return ML_SUCCESS;
+}
+
+tMLError MLSLSerialClose(void *sl_handle)
+{
+	return ML_SUCCESS;
+}
+
+tMLError MLSLSerialWriteSingle(void *sl_handle,
+			       unsigned char slaveAddr,
+			       unsigned char registerAddr,
+			       unsigned char data)
+{
+	return sensor_i2c_write_register((struct i2c_adapter *) sl_handle,
+					 slaveAddr, registerAddr, data);
+}
+
+
+tMLError MLSLSerialWrite(void *sl_handle,
+			 unsigned char slaveAddr,
+			 unsigned short length, unsigned char const *data)
+{
+	tMLError result;
+	const unsigned short dataLength = length - 1;
+	const unsigned char startRegAddr = data[0];
+	unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1];
+	unsigned short bytesWritten = 0;
+
+	while (bytesWritten < dataLength) {
+		unsigned short thisLen = min(SERIAL_MAX_TRANSFER_SIZE,
+					     dataLength - bytesWritten);
+		if (bytesWritten == 0) {
+			result = sensor_i2c_write((struct i2c_adapter *)
+						  sl_handle, slaveAddr,
+						  1 + thisLen, data);
+		} else {
+			
+			i2cWrite[0] = startRegAddr + bytesWritten;
+			memcpy(&i2cWrite[1], &data[1 + bytesWritten],
+			       thisLen);
+			result = sensor_i2c_write((struct i2c_adapter *)
+						  sl_handle, slaveAddr,
+						  1 + thisLen, i2cWrite);
+		}
+		if (ML_SUCCESS != result)
+			return result;
+		bytesWritten += thisLen;
+	}
+	return ML_SUCCESS;
+}
+
+
+tMLError MLSLSerialRead(void *sl_handle,
+			unsigned char slaveAddr,
+			unsigned char registerAddr,
+			unsigned short length, unsigned char *data)
+{
+	tMLError result;
+	unsigned short bytesRead = 0;
+
+	if (registerAddr == MPUREG_FIFO_R_W
+	    || registerAddr == MPUREG_MEM_R_W) {
+		return ML_ERROR_INVALID_PARAMETER;
+	}
+	while (bytesRead < length) {
+		unsigned short thisLen =
+		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
+		result =
+		    sensor_i2c_read((struct i2c_adapter *) sl_handle,
+				    slaveAddr, registerAddr + bytesRead,
+				    thisLen, &data[bytesRead]);
+		if (ML_SUCCESS != result)
+			return result;
+		bytesRead += thisLen;
+	}
+	return ML_SUCCESS;
+}
+
+
+tMLError MLSLSerialWriteMem(void *sl_handle,
+			    unsigned char slaveAddr,
+			    unsigned short memAddr,
+			    unsigned short length,
+			    unsigned char const *data)
+{
+	tMLError result;
+	unsigned short bytesWritten = 0;
+
+	if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
+		printk
+		    ("memory read length (%d B) extends beyond its limits (%d) "
+		     "if started at location %d\n", length,
+		     MPU_MEM_BANK_SIZE, memAddr & 0xFF);
+		return ML_ERROR_INVALID_PARAMETER;
+	}
+	while (bytesWritten < length) {
+		unsigned short thisLen =
+		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytesWritten);
+		result =
+		    mpu_memory_write((struct i2c_adapter *) sl_handle,
+				     slaveAddr, memAddr + bytesWritten,
+				     thisLen, &data[bytesWritten]);
+		if (ML_SUCCESS != result)
+			return result;
+		bytesWritten += thisLen;
+	}
+	return ML_SUCCESS;
+}
+
+
+tMLError MLSLSerialReadMem(void *sl_handle,
+			   unsigned char slaveAddr,
+			   unsigned short memAddr,
+			   unsigned short length, unsigned char *data)
+{
+	tMLError result;
+	unsigned short bytesRead = 0;
+
+	if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
+		printk
+		    ("memory read length (%d B) extends beyond its limits (%d) "
+		     "if started at location %d\n", length,
+		     MPU_MEM_BANK_SIZE, memAddr & 0xFF);
+		return ML_ERROR_INVALID_PARAMETER;
+	}
+	while (bytesRead < length) {
+		unsigned short thisLen =
+		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
+		result =
+		    mpu_memory_read((struct i2c_adapter *) sl_handle,
+				    slaveAddr, memAddr + bytesRead,
+				    thisLen, &data[bytesRead]);
+		if (ML_SUCCESS != result)
+			return result;
+		bytesRead += thisLen;
+	}
+	return ML_SUCCESS;
+}
+
+
+tMLError MLSLSerialWriteFifo(void *sl_handle,
+			     unsigned char slaveAddr,
+			     unsigned short length,
+			     unsigned char const *data)
+{
+	tMLError result;
+	unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1];
+	unsigned short bytesWritten = 0;
+
+	if (length > FIFO_HW_SIZE) {
+		printk(KERN_ERR
+		       "maximum fifo write length is %d\n", FIFO_HW_SIZE);
+		return ML_ERROR_INVALID_PARAMETER;
+	}
+	while (bytesWritten < length) {
+		unsigned short thisLen =
+		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytesWritten);
+		i2cWrite[0] = MPUREG_FIFO_R_W;
+		memcpy(&i2cWrite[1], &data[bytesWritten], thisLen);
+		result = sensor_i2c_write((struct i2c_adapter *) sl_handle,
+					  slaveAddr, thisLen + 1,
+					  i2cWrite);
+		if (ML_SUCCESS != result)
+			return result;
+		bytesWritten += thisLen;
+	}
+	return ML_SUCCESS;
+}
+
+
+tMLError MLSLSerialReadFifo(void *sl_handle,
+			    unsigned char slaveAddr,
+			    unsigned short length, unsigned char *data)
+{
+	tMLError result;
+	unsigned short bytesRead = 0;
+
+	if (length > FIFO_HW_SIZE) {
+		printk(KERN_ERR
+		       "maximum fifo read length is %d\n", FIFO_HW_SIZE);
+		return ML_ERROR_INVALID_PARAMETER;
+	}
+	while (bytesRead < length) {
+		unsigned short thisLen =
+		    min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
+		result =
+		    sensor_i2c_read((struct i2c_adapter *) sl_handle,
+				    slaveAddr, MPUREG_FIFO_R_W, thisLen,
+				    &data[bytesRead]);
+		if (ML_SUCCESS != result)
+			return result;
+		bytesRead += thisLen;
+	}
+
+	return ML_SUCCESS;
+}
+
diff --git a/drivers/input/misc/mpu3050/mlsl.h b/drivers/input/misc/mpu3050/mlsl.h
new file mode 100644
index 0000000..e1e796c
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mlsl.h
@@ -0,0 +1,86 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __MSSL_H__
+#define __MSSL_H__
+
+#include "mltypes.h"
+#include "mpu.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define SERIAL_MAX_TRANSFER_SIZE 128
+
+
+
+	tMLError MLSLSerialOpen(char const *port,
+				void **sl_handle);
+	tMLError MLSLSerialReset(void *sl_handle);
+	tMLError MLSLSerialClose(void *sl_handle);
+
+	tMLError MLSLSerialWriteSingle(void *sl_handle,
+				       unsigned char slaveAddr,
+				       unsigned char registerAddr,
+				       unsigned char data);
+
+	tMLError MLSLSerialRead(void *sl_handle,
+				unsigned char slaveAddr,
+				unsigned char registerAddr,
+				unsigned short length,
+				unsigned char *data);
+
+	tMLError MLSLSerialWrite(void *sl_handle,
+				 unsigned char slaveAddr,
+				 unsigned short length,
+				 unsigned char const *data);
+
+	tMLError MLSLSerialReadMem(void *sl_handle,
+				   unsigned char slaveAddr,
+				   unsigned short memAddr,
+				   unsigned short length,
+				   unsigned char *data);
+
+	tMLError MLSLSerialWriteMem(void *sl_handle,
+				    unsigned char slaveAddr,
+				    unsigned short memAddr,
+				    unsigned short length,
+				    unsigned char const *data);
+
+	tMLError MLSLSerialReadFifo(void *sl_handle,
+				    unsigned char slaveAddr,
+				    unsigned short length,
+				    unsigned char *data);
+
+	tMLError MLSLSerialWriteFifo(void *sl_handle,
+				     unsigned char slaveAddr,
+				     unsigned short length,
+				     unsigned char const *data);
+
+	tMLError MLSLWriteCal(unsigned char *cal, unsigned int len);
+	tMLError MLSLReadCal(unsigned char *cal, unsigned int len);
+	tMLError MLSLGetCalLength(unsigned int *len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif				
diff --git a/drivers/input/misc/mpu3050/mltypes.h b/drivers/input/misc/mpu3050/mltypes.h
new file mode 100644
index 0000000..d3f4acc
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mltypes.h
@@ -0,0 +1,138 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+
+#ifndef MLTYPES_H
+#define MLTYPES_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include "stdint_invensense.h"
+#endif
+#include "log.h"
+
+
+typedef unsigned char tMLError;
+
+#if defined(LINUX) || defined(__KERNEL__)
+typedef unsigned int HANDLE;
+#endif
+
+#ifdef __KERNEL__
+typedef HANDLE FILE;
+#endif
+
+#ifndef __cplusplus
+#ifndef __KERNEL__
+typedef int_fast8_t bool;
+#endif
+#endif
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef DIM
+#define DIM(array) (sizeof(array)/sizeof((array)[0]))
+#endif
+
+#define ERROR_NAME(x)   (#x)
+#define ERROR_CHECK(x)                                                  \
+	{								\
+		if (ML_SUCCESS != x) {					\
+			MPL_LOGE("[mpu_err]%s|%s|%d returning %d\n",	\
+				__FILE__, __func__, __LINE__, x);	\
+			return x;					\
+		}							\
+	}
+
+#define ERROR_CHECK_FIRST(first, x)                                     \
+	{ if (ML_SUCCESS == first) first = x; }
+
+#define ML_SUCCESS                       (0)
+#define ML_ERROR                         (1)
+
+#define ML_ERROR_INVALID_PARAMETER       (2)
+#define ML_ERROR_FEATURE_NOT_ENABLED     (3)
+#define ML_ERROR_FEATURE_NOT_IMPLEMENTED (4)
+#define ML_ERROR_DMP_NOT_STARTED         (6)
+#define ML_ERROR_DMP_STARTED             (7)
+#define ML_ERROR_NOT_OPENED              (8)
+#define ML_ERROR_OPENED                  (9)
+#define ML_ERROR_INVALID_MODULE         (10)
+#define ML_ERROR_MEMORY_EXAUSTED        (11)
+#define ML_ERROR_DIVIDE_BY_ZERO         (12)
+#define ML_ERROR_ASSERTION_FAILURE      (13)
+#define ML_ERROR_FILE_OPEN              (14)
+#define ML_ERROR_FILE_READ              (15)
+#define ML_ERROR_FILE_WRITE             (16)
+#define ML_ERROR_INVALID_CONFIGURATION  (17)
+
+#define ML_ERROR_SERIAL_CLOSED          (20)
+#define ML_ERROR_SERIAL_OPEN_ERROR      (21)
+#define ML_ERROR_SERIAL_READ            (22)
+#define ML_ERROR_SERIAL_WRITE           (23)
+#define ML_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED  (24)
+
+#define ML_ERROR_SM_TRANSITION          (25)
+#define ML_ERROR_SM_IMPROPER_STATE      (26)
+
+#define ML_ERROR_FIFO_OVERFLOW          (30)
+#define ML_ERROR_FIFO_FOOTER            (31)
+#define ML_ERROR_FIFO_READ_COUNT        (32)
+#define ML_ERROR_FIFO_READ_DATA         (33)
+
+#define ML_ERROR_MEMORY_SET             (40)
+
+#define ML_ERROR_LOG_MEMORY_ERROR       (50)
+#define ML_ERROR_LOG_OUTPUT_ERROR       (51)
+
+#define ML_ERROR_OS_BAD_PTR             (60)
+#define ML_ERROR_OS_BAD_HANDLE          (61)
+#define ML_ERROR_OS_CREATE_FAILED       (62)
+#define ML_ERROR_OS_LOCK_FAILED         (63)
+
+#define ML_ERROR_COMPASS_DATA_OVERFLOW  (70)
+#define ML_ERROR_COMPASS_DATA_UNDERFLOW (71)
+#define ML_ERROR_COMPASS_DATA_NOT_READY (72)
+#define ML_ERROR_COMPASS_DATA_ERROR     (73)
+
+#define ML_ERROR_CALIBRATION_LOAD       (75)
+#define ML_ERROR_CALIBRATION_STORE      (76)
+#define ML_ERROR_CALIBRATION_LEN        (77)
+#define ML_ERROR_CALIBRATION_CHECKSUM   (78)
+
+#define ML_ERROR_ACCEL_DATA_OVERFLOW    (79)
+#define ML_ERROR_ACCEL_DATA_UNDERFLOW   (80)
+#define ML_ERROR_ACCEL_DATA_NOT_READY   (81)
+#define ML_ERROR_ACCEL_DATA_ERROR       (82)
+
+
+
+#endif				
diff --git a/drivers/input/misc/mpu3050/mpu-dev.c b/drivers/input/misc/mpu3050/mpu-dev.c
new file mode 100644
index 0000000..a641af8
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mpu-dev.c
@@ -0,0 +1,1480 @@
+/*
+    mpu-dev.c - mpu3050 char device interface
+
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+    Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include "mpuirq.h"
+#include "slaveirq.h"
+#include "mlsl.h"
+#include "mpu-i2c.h"
+#include "mldl_cfg.h"
+#include "mpu.h"
+
+#define MPU3050_EARLY_SUSPEND_IN_DRIVER 0
+
+#define D(x...) printk(KERN_DEBUG "[GYRO][MPU3050] " x)
+#define I(x...) printk(KERN_INFO "[GYRO][MPU3050] " x)
+#define E(x...) printk(KERN_ERR "[GYRO][MPU3050 ERROR] " x)
+
+struct mpu_private_data {
+	struct mldl_cfg mldl_cfg;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct early_suspend early_suspend;
+#endif
+};
+
+static int pid;
+
+static struct i2c_client *this_client;
+
+int mpu_debug_flag;
+int mpu_sensors_reset;
+int mpu_lpm_flag;
+
+static int mpu_open(struct inode *inode, struct file *file)
+{
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(this_client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+
+	dev_dbg(&this_client->adapter->dev, "mpu_open\n");
+	dev_dbg(&this_client->adapter->dev, "current->pid %d\n",
+		current->pid);
+	pid = current->pid;
+	file->private_data = this_client;
+	
+	
+	
+
+	
+	mldl_cfg->requested_sensors = ML_THREE_AXIS_GYRO;
+	if (mldl_cfg->accel && mldl_cfg->accel->resume)
+		mldl_cfg->requested_sensors |= ML_THREE_AXIS_ACCEL;
+
+	if (mldl_cfg->compass && mldl_cfg->compass->resume)
+		mldl_cfg->requested_sensors |= ML_THREE_AXIS_COMPASS;
+
+	if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
+		mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
+
+	return 0;
+}
+
+static int mpu_release(struct inode *inode, struct file *file)
+{
+	struct i2c_client *client =
+	    (struct i2c_client *) file->private_data;
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+	int result = 0;
+
+	pid = 0;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter = i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter = i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+	result = mpu3050_suspend(mldl_cfg, client->adapter,
+				 accel_adapter, compass_adapter,
+				 pressure_adapter,
+				 TRUE, TRUE, TRUE, TRUE);
+
+	dev_dbg(&this_client->adapter->dev, "mpu_release\n");
+	return result;
+}
+
+static noinline int mpudev_ioctl_rdrw(struct i2c_client *client,
+				      unsigned long arg)
+{
+	struct i2c_rdwr_ioctl_data rdwr_arg;
+	struct i2c_msg *rdwr_pa;
+	u8 __user **data_ptrs;
+	int i, res;
+
+	if (copy_from_user(&rdwr_arg,
+			   (struct i2c_rdwr_ioctl_data __user *) arg,
+			   sizeof(rdwr_arg)))
+		return -EFAULT;
+
+	if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
+		return -EINVAL;
+
+	rdwr_pa = (struct i2c_msg *)
+	    kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);
+	if (!rdwr_pa)
+		return -ENOMEM;
+
+	if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
+			   rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
+		kfree(rdwr_pa);
+		return -EFAULT;
+	}
+
+	data_ptrs =
+	    kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+	if (data_ptrs == NULL) {
+		kfree(rdwr_pa);
+		return -ENOMEM;
+	}
+
+	res = 0;
+	for (i = 0; i < rdwr_arg.nmsgs; i++) {
+		if ((rdwr_pa[i].len > 8192) ||
+		    (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
+			res = -EINVAL;
+			break;
+		}
+		data_ptrs[i] = (u8 __user *) rdwr_pa[i].buf;
+		rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
+		if (rdwr_pa[i].buf == NULL) {
+			res = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i],
+				   rdwr_pa[i].len)) {
+			++i;	
+			res = -EFAULT;
+			break;
+		}
+	}
+	if (res < 0) {
+		int j;
+		for (j = 0; j < i; ++j)
+			kfree(rdwr_pa[j].buf);
+		kfree(data_ptrs);
+		kfree(rdwr_pa);
+		return res;
+	}
+
+	res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
+	while (i-- > 0) {
+		if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
+			if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
+					 rdwr_pa[i].len))
+				res = -EFAULT;
+		}
+		kfree(rdwr_pa[i].buf);
+	}
+	kfree(data_ptrs);
+	kfree(rdwr_pa);
+	return res;
+}
+
+static ssize_t mpu_read(struct file *file,
+			char __user *buf, size_t count, loff_t *offset)
+{
+	char *tmp;
+	int ret;
+
+	struct i2c_client *client =
+	    (struct i2c_client *) file->private_data;
+
+	if (count > 8192)
+		count = 8192;
+
+	tmp = kmalloc(count, GFP_KERNEL);
+	if (tmp == NULL)
+		return -ENOMEM;
+
+	pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",
+		 iminor(file->f_path.dentry->d_inode), count);
+
+	ret = i2c_master_recv(client, tmp, count);
+	if (ret >= 0) {
+		ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
+		if (ret)
+			ret = -EFAULT;
+	}
+	kfree(tmp);
+	return ret;
+}
+
+static int
+mpu_ioctl_set_mpu_pdata(struct i2c_client *client, unsigned long arg)
+{
+	int ii;
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mpu3050_platform_data *pdata = mpu->mldl_cfg.pdata;
+	struct mpu3050_platform_data local_pdata;
+
+	if (copy_from_user(&local_pdata, (unsigned char __user *) arg,
+				sizeof(local_pdata)))
+		return -EFAULT;
+
+	pdata->int_config = local_pdata.int_config;
+	for (ii = 0; ii < DIM(pdata->orientation); ii++)
+		pdata->orientation[ii] = local_pdata.orientation[ii];
+	pdata->level_shifter = local_pdata.level_shifter;
+
+	pdata->accel.address = local_pdata.accel.address;
+	for (ii = 0; ii < DIM(pdata->accel.orientation); ii++)
+		pdata->accel.orientation[ii] =
+			local_pdata.accel.orientation[ii];
+
+	pdata->compass.address = local_pdata.compass.address;
+	for (ii = 0; ii < DIM(pdata->compass.orientation); ii++)
+		pdata->compass.orientation[ii] =
+			local_pdata.compass.orientation[ii];
+
+	pdata->pressure.address = local_pdata.pressure.address;
+	for (ii = 0; ii < DIM(pdata->pressure.orientation); ii++)
+		pdata->pressure.orientation[ii] =
+			local_pdata.pressure.orientation[ii];
+
+	dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+	return ML_SUCCESS;
+}
+
+static int
+mpu_ioctl_set_mpu_config(struct i2c_client *client, unsigned long arg)
+{
+	int ii;
+	int result = ML_SUCCESS;
+	struct mpu_private_data *mpu =
+		(struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct mldl_cfg *temp_mldl_cfg;
+
+	dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
+
+	temp_mldl_cfg = kzalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
+	if (NULL == temp_mldl_cfg)
+		return -ENOMEM;
+
+	if (copy_from_user(temp_mldl_cfg, (struct mldl_cfg __user *) arg,
+				offsetof(struct mldl_cfg, silicon_revision))) {
+		result = -EFAULT;
+		goto out;
+	}
+
+	if (mldl_cfg->gyro_is_suspended) {
+		if (mldl_cfg->addr != temp_mldl_cfg->addr)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->int_config != temp_mldl_cfg->int_config)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->ext_sync != temp_mldl_cfg->ext_sync)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->full_scale != temp_mldl_cfg->full_scale)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->lpf != temp_mldl_cfg->lpf)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->clk_src != temp_mldl_cfg->clk_src)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->divider != temp_mldl_cfg->divider)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->dmp_enable != temp_mldl_cfg->dmp_enable)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->fifo_enable != temp_mldl_cfg->fifo_enable)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->dmp_cfg1 != temp_mldl_cfg->dmp_cfg1)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->dmp_cfg2 != temp_mldl_cfg->dmp_cfg2)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (mldl_cfg->gyro_power != temp_mldl_cfg->gyro_power)
+			mldl_cfg->gyro_needs_reset = TRUE;
+
+		for (ii = 0; ii < MPU_NUM_AXES; ii++)
+			if (mldl_cfg->offset_tc[ii] !=
+			    temp_mldl_cfg->offset_tc[ii])
+				mldl_cfg->gyro_needs_reset = TRUE;
+
+		for (ii = 0; ii < MPU_NUM_AXES; ii++)
+			if (mldl_cfg->offset[ii] != temp_mldl_cfg->offset[ii])
+				mldl_cfg->gyro_needs_reset = TRUE;
+
+		if (memcmp(mldl_cfg->ram, temp_mldl_cfg->ram,
+				MPU_MEM_NUM_RAM_BANKS * MPU_MEM_BANK_SIZE *
+				sizeof(unsigned char)))
+			mldl_cfg->gyro_needs_reset = TRUE;
+	}
+
+	memcpy(mldl_cfg, temp_mldl_cfg,
+		offsetof(struct mldl_cfg, silicon_revision));
+
+out:
+	kfree(temp_mldl_cfg);
+	return result;
+}
+
+static int
+mpu_ioctl_get_mpu_config(struct i2c_client *client, unsigned long arg)
+{
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct mldl_cfg *local_mldl_cfg;
+	int retval = 0;
+
+	local_mldl_cfg = kzalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
+	if (NULL == local_mldl_cfg)
+		return -ENOMEM;
+
+	retval =
+	    copy_from_user(local_mldl_cfg, (struct mldl_cfg __user *) arg,
+			   sizeof(struct mldl_cfg));
+	if (retval) {
+		dev_err(&this_client->adapter->dev,
+			"%s|%s:%d: EFAULT on arg\n",
+			__FILE__, __func__, __LINE__);
+		retval = -EFAULT;
+		goto out;
+	}
+
+	
+	if (mldl_cfg->accel) {
+		retval = copy_to_user((void __user *)local_mldl_cfg->accel,
+				      mldl_cfg->accel,
+				      sizeof(*mldl_cfg->accel));
+		if (retval) {
+			dev_err(&this_client->adapter->dev,
+				"%s|%s:%d: EFAULT on accel\n",
+				__FILE__, __func__, __LINE__);
+			retval = -EFAULT;
+			goto out;
+		}
+	}
+
+	if (mldl_cfg->compass) {
+		retval = copy_to_user((void __user *)local_mldl_cfg->compass,
+				      mldl_cfg->compass,
+				      sizeof(*mldl_cfg->compass));
+		if (retval) {
+			dev_err(&this_client->adapter->dev,
+				"%s|%s:%d: EFAULT on compass\n",
+				__FILE__, __func__, __LINE__);
+			retval = -EFAULT;
+			goto out;
+		}
+	}
+
+	if (mldl_cfg->pressure) {
+		retval = copy_to_user((void __user *)local_mldl_cfg->pressure,
+				      mldl_cfg->pressure,
+				      sizeof(*mldl_cfg->pressure));
+		if (retval) {
+			dev_err(&this_client->adapter->dev,
+				"%s|%s:%d: EFAULT on pressure\n",
+				__FILE__, __func__, __LINE__);
+			retval = -EFAULT;
+			goto out;
+		}
+	}
+
+	if (mldl_cfg->pdata) {
+		retval = copy_to_user((void __user *)local_mldl_cfg->pdata,
+				      mldl_cfg->pdata,
+				      sizeof(*mldl_cfg->pdata));
+		if (retval) {
+			dev_err(&this_client->adapter->dev,
+				"%s|%s:%d: EFAULT on pdata\n",
+				__FILE__, __func__, __LINE__);
+			retval = -EFAULT;
+			goto out;
+		}
+	}
+
+	
+	retval = copy_to_user((struct mldl_cfg __user *) arg,
+			      mldl_cfg, offsetof(struct mldl_cfg, accel));
+
+	if (retval)
+		retval = -EFAULT;
+out:
+	kfree(local_mldl_cfg);
+	return retval;
+}
+
+static int slave_config(void *adapter,
+			struct mldl_cfg *mldl_cfg,
+			struct ext_slave_descr *slave,
+			struct ext_slave_platform_data *pdata,
+			struct ext_slave_config __user *usr_config)
+{
+	int retval = ML_SUCCESS;
+	if ((slave) && (slave->config)) {
+		struct ext_slave_config config;
+		retval = copy_from_user(
+			&config,
+			usr_config,
+			sizeof(config));
+		if (retval)
+			return -EFAULT;
+
+		if (config.len && config.data) {
+			int *data;
+			data = kzalloc(config.len, GFP_KERNEL);
+			if (!data)
+				return ML_ERROR_MEMORY_EXAUSTED;
+
+			retval = copy_from_user(data,
+						(void __user *)config.data,
+						config.len);
+			if (retval) {
+				retval = -EFAULT;
+				kfree(data);
+				return retval;
+			}
+			config.data = data;
+		}
+		retval = slave->config(adapter,
+				slave,
+				pdata,
+				&config);
+		kfree(config.data);
+	}
+	return retval;
+}
+
+static int slave_get_config(void *adapter,
+			struct mldl_cfg *mldl_cfg,
+			struct ext_slave_descr *slave,
+			struct ext_slave_platform_data *pdata,
+			struct ext_slave_config __user *usr_config)
+{
+	int retval = ML_SUCCESS;
+	if ((slave) && (slave->get_config)) {
+		struct ext_slave_config config;
+		void *user_data;
+		retval = copy_from_user(
+			&config,
+			usr_config,
+			sizeof(config));
+		if (retval)
+			return -EFAULT;
+
+		user_data = config.data;
+		if (config.len && config.data) {
+			int *data;
+			data = kzalloc(config.len, GFP_KERNEL);
+			if (!data)
+				return ML_ERROR_MEMORY_EXAUSTED;
+
+			retval = copy_from_user(data,
+						(void __user *)config.data,
+						config.len);
+			if (retval) {
+				retval = -EFAULT;
+				kfree(data);
+				return retval;
+			}
+			config.data = data;
+		}
+		retval = slave->get_config(adapter,
+				slave,
+				pdata,
+				&config);
+		if (retval) {
+			kfree(config.data);
+			return retval;
+		}
+		retval = copy_to_user((unsigned char __user *) user_data,
+				      config.data,
+				      config.len);
+		kfree(config.data);
+	}
+	return retval;
+}
+
+static long mpu_ioctl(struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct i2c_client *client =
+	    (struct i2c_client *) file->private_data;
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	int retval = 0;
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+	switch (cmd) {
+	case I2C_RDWR:
+		mpudev_ioctl_rdrw(client, arg);
+		break;
+	case I2C_SLAVE:
+		if ((arg & 0x7E) != (client->addr & 0x7E)) {
+			dev_err(&this_client->adapter->dev,
+				"[mpu_err]%s: Invalid I2C_SLAVE arg %lu\n",
+				__func__, arg);
+		}
+		break;
+	case MPU_SET_MPU_CONFIG:
+		retval = mpu_ioctl_set_mpu_config(client, arg);
+		break;
+	case MPU_SET_INT_CONFIG:
+		mldl_cfg->int_config = (unsigned char) arg;
+		break;
+	case MPU_SET_EXT_SYNC:
+		mldl_cfg->ext_sync = (enum mpu_ext_sync) arg;
+		break;
+	case MPU_SET_FULL_SCALE:
+		mldl_cfg->full_scale = (enum mpu_fullscale) arg;
+		break;
+	case MPU_SET_LPF:
+		mldl_cfg->lpf = (enum mpu_filter) arg;
+		break;
+	case MPU_SET_CLK_SRC:
+		mldl_cfg->clk_src = (enum mpu_clock_sel) arg;
+		break;
+	case MPU_SET_DIVIDER:
+		mldl_cfg->divider = (unsigned char) arg;
+		break;
+	case MPU_SET_LEVEL_SHIFTER:
+		mldl_cfg->pdata->level_shifter = (unsigned char) arg;
+		break;
+	case MPU_SET_DMP_ENABLE:
+		mldl_cfg->dmp_enable = (unsigned char) arg;
+		break;
+	case MPU_SET_FIFO_ENABLE:
+		mldl_cfg->fifo_enable = (unsigned char) arg;
+		break;
+	case MPU_SET_DMP_CFG1:
+		mldl_cfg->dmp_cfg1 = (unsigned char) arg;
+		break;
+	case MPU_SET_DMP_CFG2:
+		mldl_cfg->dmp_cfg2 = (unsigned char) arg;
+		break;
+	case MPU_SET_OFFSET_TC:
+		retval = copy_from_user(mldl_cfg->offset_tc,
+					(unsigned char __user *) arg,
+					sizeof(mldl_cfg->offset_tc));
+		if (retval)
+			retval = -EFAULT;
+
+		break;
+	case MPU_SET_RAM:
+		retval = copy_from_user(mldl_cfg->ram,
+					(unsigned char __user *) arg,
+					sizeof(mldl_cfg->ram));
+		if (retval)
+			retval = -EFAULT;
+		break;
+	case MPU_SET_PLATFORM_DATA:
+		retval = mpu_ioctl_set_mpu_pdata(client, arg);
+		break;
+	case MPU_GET_MPU_CONFIG:
+		retval = mpu_ioctl_get_mpu_config(client, arg);
+		break;
+	case MPU_GET_INT_CONFIG:
+		retval = put_user(mldl_cfg->int_config,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_EXT_SYNC:
+		retval = put_user(mldl_cfg->ext_sync,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_FULL_SCALE:
+		retval = put_user(mldl_cfg->full_scale,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_LPF:
+		retval = put_user(mldl_cfg->lpf,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_CLK_SRC:
+		retval = put_user(mldl_cfg->clk_src,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_DIVIDER:
+		retval = put_user(mldl_cfg->divider,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_LEVEL_SHIFTER:
+		retval = put_user(mldl_cfg->pdata->level_shifter,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_DMP_ENABLE:
+		retval = put_user(mldl_cfg->dmp_enable,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_FIFO_ENABLE:
+		retval = put_user(mldl_cfg->fifo_enable,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_DMP_CFG1:
+		retval = put_user(mldl_cfg->dmp_cfg1,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_DMP_CFG2:
+		retval = put_user(mldl_cfg->dmp_cfg2,
+				  (unsigned char __user *) arg);
+		break;
+	case MPU_GET_OFFSET_TC:
+		retval = copy_to_user((unsigned char __user *) arg,
+				      mldl_cfg->offset_tc,
+				      sizeof(mldl_cfg->offset_tc));
+		if (retval)
+			retval = -EFAULT;
+		break;
+	case MPU_GET_RAM:
+		retval = copy_to_user((unsigned char __user *) arg,
+				      mldl_cfg->ram,
+				      sizeof(mldl_cfg->ram));
+		if (retval)
+			retval = -EFAULT;
+		break;
+	case MPU_CONFIG_ACCEL:
+		retval = slave_config(accel_adapter, mldl_cfg,
+				mldl_cfg->accel,
+				&mldl_cfg->pdata->accel,
+				(struct ext_slave_config __user *) arg);
+		break;
+	case MPU_CONFIG_COMPASS:
+		retval = slave_config(compass_adapter, mldl_cfg,
+				mldl_cfg->compass,
+				&mldl_cfg->pdata->compass,
+				(struct ext_slave_config __user *) arg);
+		break;
+	case MPU_CONFIG_PRESSURE:
+		retval = slave_config(pressure_adapter, mldl_cfg,
+				mldl_cfg->pressure,
+				&mldl_cfg->pdata->pressure,
+				(struct ext_slave_config __user *) arg);
+		break;
+	case MPU_GET_CONFIG_ACCEL:
+		retval = slave_get_config(accel_adapter, mldl_cfg,
+					mldl_cfg->accel,
+					&mldl_cfg->pdata->accel,
+					(struct ext_slave_config __user *) arg);
+		break;
+	case MPU_GET_CONFIG_COMPASS:
+		retval = slave_get_config(compass_adapter, mldl_cfg,
+					mldl_cfg->compass,
+					&mldl_cfg->pdata->compass,
+					(struct ext_slave_config __user *) arg);
+		break;
+	case MPU_GET_CONFIG_PRESSURE:
+		retval = slave_get_config(pressure_adapter, mldl_cfg,
+					mldl_cfg->pressure,
+					&mldl_cfg->pdata->pressure,
+					(struct ext_slave_config __user *) arg);
+		break;
+	case MPU_SUSPEND:
+	{
+		unsigned long sensors;
+		sensors = ~(mldl_cfg->requested_sensors);
+		retval = mpu3050_suspend(mldl_cfg,
+					client->adapter,
+					accel_adapter,
+					compass_adapter,
+					pressure_adapter,
+					((sensors & ML_THREE_AXIS_GYRO)
+						== ML_THREE_AXIS_GYRO),
+					((sensors & ML_THREE_AXIS_ACCEL)
+						== ML_THREE_AXIS_ACCEL),
+					((sensors & ML_THREE_AXIS_COMPASS)
+						== ML_THREE_AXIS_COMPASS),
+					((sensors & ML_THREE_AXIS_PRESSURE)
+						== ML_THREE_AXIS_PRESSURE));
+	}
+	break;
+	case MPU_RESUME:
+	{
+		unsigned long sensors;
+
+
+		sensors = mldl_cfg->requested_sensors;
+		retval = mpu3050_resume(mldl_cfg,
+					client->adapter,
+					accel_adapter,
+					compass_adapter,
+					pressure_adapter,
+					sensors & ML_THREE_AXIS_GYRO,
+					sensors & ML_THREE_AXIS_ACCEL,
+					sensors & ML_THREE_AXIS_COMPASS,
+					sensors & ML_THREE_AXIS_PRESSURE);
+	}
+	break;
+	case MPU_READ_ACCEL:
+	{
+		unsigned char data[6];
+		retval = mpu3050_read_accel(mldl_cfg, client->adapter,
+					    data);
+		if ((ML_SUCCESS == retval) &&
+		    (copy_to_user((unsigned char __user *) arg,
+			    data, sizeof(data))))
+			retval = -EFAULT;
+	}
+	break;
+	case MPU_READ_COMPASS:
+	{
+		unsigned char data[6];
+		struct i2c_adapter *compass_adapt =
+			i2c_get_adapter(mldl_cfg->pdata->compass.
+					adapt_num);
+		retval = mpu3050_read_compass(mldl_cfg, compass_adapt,
+						 data);
+		if ((ML_SUCCESS == retval) &&
+			(copy_to_user((unsigned char *) arg,
+				data, sizeof(data))))
+			retval = -EFAULT;
+	}
+	break;
+	case MPU_READ_PRESSURE:
+	{
+		unsigned char data[3];
+		struct i2c_adapter *pressure_adapt =
+			i2c_get_adapter(mldl_cfg->pdata->pressure.
+					adapt_num);
+		retval =
+			mpu3050_read_pressure(mldl_cfg, pressure_adapt,
+					data);
+		if ((ML_SUCCESS == retval) &&
+		    (copy_to_user((unsigned char __user *) arg,
+			    data, sizeof(data))))
+			retval = -EFAULT;
+	}
+	break;
+#ifdef HTC_READ_CAL_DATA
+	case MPU_READ_CAL_DATA:
+	{
+		int index;
+		unsigned char mpu_gyro_gsensor_kvalue[37];
+
+		for (index = 0;
+		     index < sizeof(mpu_gyro_gsensor_kvalue);
+		     index++) {
+			mpu_gyro_gsensor_kvalue[index] =
+				gyro_gsensor_kvalue[index];
+			printk(KERN_DEBUG "gyro_gsensor_kvalue[%d] = 0x%x\n",
+			       index, gyro_gsensor_kvalue[index]);
+		}
+
+		retval =
+			copy_to_user((unsigned char *) arg,
+				     mpu_gyro_gsensor_kvalue,
+				     sizeof(mpu_gyro_gsensor_kvalue));
+	}
+	break;
+#endif
+	case MPU_READ_MEMORY:
+	case MPU_WRITE_MEMORY:
+	default:
+		dev_err(&this_client->adapter->dev,
+			"[mpu_err]%s: Unknown cmd %d, arg %lu\n", __func__, cmd,
+			arg);
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+void mpu3050_early_suspend(struct early_suspend *h)
+{
+	struct mpu_private_data *mpu = container_of(h,
+						    struct
+						    mpu_private_data,
+						    early_suspend);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+	dev_dbg(&this_client->adapter->dev, "%s: %d, %d\n", __func__,
+		h->level, mpu->mldl_cfg.gyro_is_suspended);
+	if (MPU3050_EARLY_SUSPEND_IN_DRIVER)
+		(void) mpu3050_suspend(mldl_cfg, this_client->adapter,
+				accel_adapter, compass_adapter,
+				pressure_adapter, TRUE, TRUE, TRUE, TRUE);
+}
+
+void mpu3050_early_resume(struct early_suspend *h)
+{
+	struct mpu_private_data *mpu = container_of(h,
+						    struct
+						    mpu_private_data,
+						    early_suspend);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+	if (MPU3050_EARLY_SUSPEND_IN_DRIVER) {
+		if (pid) {
+			unsigned long sensors = mldl_cfg->requested_sensors;
+			(void) mpu3050_resume(mldl_cfg,
+					this_client->adapter,
+					accel_adapter,
+					compass_adapter,
+					pressure_adapter,
+					sensors & ML_THREE_AXIS_GYRO,
+					sensors & ML_THREE_AXIS_ACCEL,
+					sensors & ML_THREE_AXIS_COMPASS,
+					sensors & ML_THREE_AXIS_PRESSURE);
+			dev_dbg(&this_client->adapter->dev,
+				"%s for pid %d\n", __func__, pid);
+		}
+	}
+	dev_dbg(&this_client->adapter->dev, "%s: %d\n", __func__, h->level);
+}
+#endif
+
+void mpu_shutdown(struct i2c_client *client)
+{
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+	(void) mpu3050_suspend(mldl_cfg, this_client->adapter,
+			       accel_adapter, compass_adapter, pressure_adapter,
+			       TRUE, TRUE, TRUE, TRUE);
+	dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
+}
+
+int mpu_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+	if (!mpu->mldl_cfg.gyro_is_suspended) {
+		dev_dbg(&this_client->adapter->dev,
+			"%s: suspending on event %d\n", __func__,
+			mesg.event);
+		(void) mpu3050_suspend(mldl_cfg, this_client->adapter,
+				       accel_adapter, compass_adapter,
+				       pressure_adapter,
+				       TRUE, TRUE, TRUE, TRUE);
+	} else {
+		dev_dbg(&this_client->adapter->dev,
+			"%s: Already suspended %d\n", __func__,
+			mesg.event);
+	}
+
+	return 0;
+}
+
+int mpu_resume(struct i2c_client *client)
+{
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+	if (pid) {
+		unsigned long sensors = mldl_cfg->requested_sensors;
+		(void) mpu3050_resume(mldl_cfg, this_client->adapter,
+				      accel_adapter,
+				      compass_adapter,
+				      pressure_adapter,
+				      sensors & ML_THREE_AXIS_GYRO,
+				      sensors & ML_THREE_AXIS_ACCEL,
+				      sensors & ML_THREE_AXIS_COMPASS,
+				      sensors & ML_THREE_AXIS_PRESSURE);
+		dev_dbg(&this_client->adapter->dev,
+			"%s for pid %d\n", __func__, pid);
+	}
+
+	return 0;
+}
+
+static const struct file_operations mpu_fops = {
+	.owner = THIS_MODULE,
+	.read = mpu_read,
+#if HAVE_COMPAT_IOCTL
+	.compat_ioctl = mpu_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+	.unlocked_ioctl = mpu_ioctl,
+#endif
+	.open = mpu_open,
+	.release = mpu_release,
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static struct miscdevice i2c_mpu_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "mpu", 
+	.fops = &mpu_fops,
+};
+
+void *g_handler;
+int (*g_sensors_reset)(void);
+
+struct class *mpu3050_class;
+struct device *mpu3050_dev;
+
+static ssize_t pwr_reg_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	unsigned char b[2] = "";
+	int result;
+
+	unsigned char bma[8] = "";
+
+	result = MLSLSerialRead(g_handler, 0x68,
+				MPUREG_USER_CTRL, 2, b);
+
+	result = MLSLSerialRead(g_handler, 0x18,
+				0x0F, 3, bma);
+
+	result = sprintf(buf, "MPUREG_USER_CTRL = 0x%x, MPUREG_PWR_MGM = "
+			      "0x%x.\n"
+			      "BMA register 0x0F = 0x%x, "
+			      "BMA register 0x10 = 0x%x, "
+			      "BMA register 0x11 = 0x%x\n"
+			      "",
+			      b[0], b[1],
+			      bma[0], bma[1], bma[2]);
+
+	return result;
+}
+
+static ssize_t pwr_reg_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	return count;
+}
+
+static DEVICE_ATTR(pwr_reg, 0664, pwr_reg_show, pwr_reg_store);
+
+static ssize_t mpu_debug_flag_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	char *s = buf;
+
+	s += sprintf(s, "mpu_debug_flag = 0x%x\n", mpu_debug_flag);
+
+	return s - buf;
+}
+
+static ssize_t mpu_debug_flag_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	mpu_debug_flag = -1;
+	sscanf(buf, "%d", &mpu_debug_flag);
+
+	D("%s: mpu_debug_flag = %d\n", __func__, mpu_debug_flag);
+
+	return count;
+}
+
+static DEVICE_ATTR(mpu_debug_flag, 0664, mpu_debug_flag_show, \
+		mpu_debug_flag_store);
+
+static ssize_t mpu_sensors_reset_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	char *s = buf;
+
+	s += sprintf(s, "mpu_sensors_reset = 0x%x\n", mpu_sensors_reset);
+
+	return s - buf;
+}
+
+static ssize_t mpu_sensors_reset_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int rc = 0;
+
+	mpu_sensors_reset = -1;
+	sscanf(buf, "%d", &mpu_sensors_reset);
+
+	D("%s: mpu_sensors_reset = %d\n", __func__, mpu_sensors_reset);
+
+	if ((mpu_sensors_reset == 1) && g_sensors_reset) {
+		rc = g_sensors_reset();
+		if (rc)
+			E("G-Sensor, Compass, Gyro reset error\n");
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(mpu_sensors_reset, 0664, mpu_sensors_reset_show, \
+		mpu_sensors_reset_store);
+
+
+static ssize_t mpu_lpm_flag_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	char *s = buf;
+
+	s += sprintf(s, "%d", mpu_lpm_flag);
+
+	return s - buf;
+}
+
+static ssize_t mpu_lpm_flag_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct mpu_private_data *mpu =
+	    (struct mpu_private_data *) i2c_get_clientdata(this_client);
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+
+	mpu_lpm_flag = -1;
+	sscanf(buf, "%d", &mpu_lpm_flag);
+
+	if ((mpu_lpm_flag == 1) && mldl_cfg->pdata->power_LPM)
+		mldl_cfg->pdata->power_LPM(1);
+	else if (mldl_cfg->pdata->power_LPM)
+		mldl_cfg->pdata->power_LPM(0);
+
+	D("%s: mpu_lpm_flag = %d\n", __func__, mpu_lpm_flag);
+
+	return count;
+}
+
+static DEVICE_ATTR(mpu_lpm_flag, 0664, mpu_lpm_flag_show, \
+		mpu_lpm_flag_store);
+
+
+int mpu3050_probe(struct i2c_client *client,
+		  const struct i2c_device_id *devid)
+{
+	struct mpu3050_platform_data *pdata;
+	struct mpu_private_data *mpu;
+	struct mldl_cfg *mldl_cfg;
+	int res = 0;
+	struct i2c_adapter *accel_adapter = NULL;
+	struct i2c_adapter *compass_adapter = NULL;
+	struct i2c_adapter *pressure_adapter = NULL;
+
+	dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		res = -ENODEV;
+		goto out_check_functionality_failed;
+	}
+
+	mpu = kzalloc(sizeof(struct mpu_private_data), GFP_KERNEL);
+	if (!mpu) {
+		res = -ENOMEM;
+		goto out_alloc_data_failed;
+	}
+
+	i2c_set_clientdata(client, mpu);
+	this_client = client;
+	mldl_cfg = &mpu->mldl_cfg;
+	pdata = (struct mpu3050_platform_data *) client->dev.platform_data;
+	if (!pdata) {
+		dev_warn(&this_client->adapter->dev,
+			 "Warning no platform data for mpu3050\n");
+	} else {
+		mldl_cfg->pdata = pdata;
+
+	g_sensors_reset = pdata->g_sensors_reset;
+
+#if defined(CONFIG_MPU_SENSORS_MPU3050_MODULE) || \
+    defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)
+		pdata->accel.get_slave_descr = get_accel_slave_descr;
+		pdata->compass.get_slave_descr = get_compass_slave_descr;
+		pdata->pressure.get_slave_descr = get_pressure_slave_descr;
+#endif
+
+		if (pdata->accel.get_slave_descr) {
+			mldl_cfg->accel =
+			    pdata->accel.get_slave_descr();
+			dev_info(&this_client->adapter->dev,
+				 "%s: +%s\n", MPU_NAME,
+				 mldl_cfg->accel->name);
+			accel_adapter =
+				i2c_get_adapter(pdata->accel.adapt_num);
+			if (pdata->accel.irq > 0) {
+				dev_info(&this_client->adapter->dev,
+					"Installing Accel irq using %d\n",
+					pdata->accel.irq);
+				res = slaveirq_init(accel_adapter,
+						&pdata->accel,
+						"accelirq");
+				if (res)
+					goto out_accelirq_failed;
+			} else {
+				dev_info(&this_client->adapter->dev,
+					"Accel irq not needed\n");
+			}
+		} else {
+			dev_warn(&this_client->adapter->dev,
+				 "%s: No Accel Present\n", MPU_NAME);
+		}
+
+		if (pdata->compass.get_slave_descr) {
+			mldl_cfg->compass =
+			    pdata->compass.get_slave_descr();
+			dev_info(&this_client->adapter->dev,
+				 "%s: +%s\n", MPU_NAME,
+				 mldl_cfg->compass->name);
+			compass_adapter =
+				i2c_get_adapter(pdata->compass.adapt_num);
+			if (pdata->compass.irq > 0) {
+				dev_info(&this_client->adapter->dev,
+					"Installing Compass irq using %d\n",
+					pdata->compass.irq);
+				res = slaveirq_init(compass_adapter,
+						&pdata->compass,
+						"compassirq");
+				if (res)
+					goto out_compassirq_failed;
+			} else {
+				dev_info(&this_client->adapter->dev,
+					"Compass irq not needed\n");
+			}
+		} else {
+			dev_warn(&this_client->adapter->dev,
+				 "%s: No Compass Present\n", MPU_NAME);
+		}
+
+		if (pdata->pressure.get_slave_descr) {
+			mldl_cfg->pressure =
+			    pdata->pressure.get_slave_descr();
+			dev_info(&this_client->adapter->dev,
+				 "%s: +%s\n", MPU_NAME,
+				 mldl_cfg->pressure->name);
+			pressure_adapter =
+				i2c_get_adapter(pdata->pressure.adapt_num);
+
+			if (pdata->pressure.irq > 0) {
+				dev_info(&this_client->adapter->dev,
+					"Installing Pressure irq using %d\n",
+					pdata->pressure.irq);
+				res = slaveirq_init(pressure_adapter,
+						&pdata->pressure,
+						"pressureirq");
+				if (res)
+					goto out_pressureirq_failed;
+			} else {
+				dev_warn(&this_client->adapter->dev,
+					"WARNING: Pressure irq not assigned\n");
+			}
+		} else {
+			dev_info(&this_client->adapter->dev,
+				 "%s: No Pressure Present\n", MPU_NAME);
+		}
+	}
+
+	mldl_cfg->addr = client->addr;
+	res = mpu3050_open(&mpu->mldl_cfg, client->adapter,
+			accel_adapter, compass_adapter, pressure_adapter);
+
+	if (res) {
+		dev_err(&this_client->adapter->dev,
+			"[mpu_err] Unable to open %s %d\n", MPU_NAME, res);
+		res = -ENODEV;
+		goto out_whoami_failed;
+	}
+
+	g_handler = client->adapter;
+
+	res = misc_register(&i2c_mpu_device);
+	if (res < 0) {
+		dev_err(&this_client->adapter->dev,
+			"[mpu_err] ERROR: misc_register returned %d\n", res);
+		goto out_misc_register_failed;
+	}
+
+	if (this_client->irq > 0) {
+		dev_info(&this_client->adapter->dev,
+			 "Installing irq using %d\n", this_client->irq);
+		res = mpuirq_init(this_client);
+		if (res)
+			goto out_mpuirq_failed;
+	} else {
+		dev_warn(&this_client->adapter->dev,
+			 "WARNING: %s irq not assigned\n", MPU_NAME);
+	}
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	mpu->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	mpu->early_suspend.suspend = mpu3050_early_suspend;
+	mpu->early_suspend.resume = mpu3050_early_resume;
+	register_early_suspend(&mpu->early_suspend);
+#endif
+
+	mpu3050_class = class_create(THIS_MODULE, "gyro_sensors");
+	if (IS_ERR(mpu3050_class)) {
+		res = PTR_ERR(mpu3050_class);
+		mpu3050_class = NULL;
+		E("%s, create mpu3050_class fail!\n", __func__);
+		goto out_mpuirq_failed;
+	}
+
+	mpu3050_dev = device_create(mpu3050_class,
+				NULL, 0, "%s", "gyro");
+	if (unlikely(IS_ERR(mpu3050_dev))) {
+		res = PTR_ERR(mpu3050_dev);
+		mpu3050_dev = NULL;
+		E("%s, create mpu3050_dev fail!\n", __func__);
+		goto err_create_mpu_device;
+	}
+
+	
+	res = device_create_file(mpu3050_dev, &dev_attr_pwr_reg);
+	if (res) {
+		E("%s, create mpu3050_device_create_file fail!\n", __func__);
+		goto err_create_mpu_device_file;
+	}
+
+	
+	res = device_create_file(mpu3050_dev, &dev_attr_mpu_debug_flag);
+	if (res) {
+		E("%s, create mpu3050_device_create_file fail!\n", __func__);
+		goto err_create_mpu_device_mpu_debug_flag_file;
+	}
+
+	
+	res = device_create_file(mpu3050_dev, &dev_attr_mpu_sensors_reset);
+	if (res) {
+		E("%s, create mpu3050_device_create_file fail!\n", __func__);
+		goto err_create_mpu_device_sensors_reset_flag_file;
+	}
+
+	
+	res = device_create_file(mpu3050_dev, &dev_attr_mpu_lpm_flag);
+	if (res) {
+		E("%s, create mpu3050_device_create_file fail!\n", __func__);
+		goto err_create_mpu_device_mpu_lpm_flag_file;
+	}
+
+	mpu_debug_flag = 0;
+	mpu_sensors_reset = 0;
+	mpu_lpm_flag = 0;
+
+	return res;
+
+err_create_mpu_device_mpu_lpm_flag_file:
+	device_remove_file(mpu3050_dev, &dev_attr_mpu_sensors_reset);
+err_create_mpu_device_sensors_reset_flag_file:
+	device_remove_file(mpu3050_dev, &dev_attr_mpu_debug_flag);
+err_create_mpu_device_mpu_debug_flag_file:
+	device_remove_file(mpu3050_dev, &dev_attr_pwr_reg);
+err_create_mpu_device_file:
+	device_unregister(mpu3050_dev);
+err_create_mpu_device:
+	class_destroy(mpu3050_class);
+out_mpuirq_failed:
+	misc_deregister(&i2c_mpu_device);
+out_misc_register_failed:
+	mpu3050_close(&mpu->mldl_cfg, client->adapter,
+		accel_adapter, compass_adapter, pressure_adapter);
+out_whoami_failed:
+	if (pdata &&
+	    pdata->pressure.get_slave_descr &&
+	    pdata->pressure.irq)
+		slaveirq_exit(&pdata->pressure);
+out_pressureirq_failed:
+	if (pdata &&
+	    pdata->compass.get_slave_descr &&
+	    pdata->compass.irq)
+		slaveirq_exit(&pdata->compass);
+out_compassirq_failed:
+	if (pdata &&
+	    pdata->accel.get_slave_descr &&
+	    pdata->accel.irq)
+		slaveirq_exit(&pdata->accel);
+out_accelirq_failed:
+	kfree(mpu);
+out_alloc_data_failed:
+out_check_functionality_failed:
+	dev_err(&this_client->adapter->dev, "[mpu_err]%s failed %d\n", __func__,
+		res);
+	return res;
+
+}
+
+static int mpu3050_remove(struct i2c_client *client)
+{
+	struct mpu_private_data *mpu = i2c_get_clientdata(client);
+	struct i2c_adapter *accel_adapter;
+	struct i2c_adapter *compass_adapter;
+	struct i2c_adapter *pressure_adapter;
+	struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+	struct mpu3050_platform_data *pdata = mldl_cfg->pdata;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	compass_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+	pressure_adapter =
+	    i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+	dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	unregister_early_suspend(&mpu->early_suspend);
+#endif
+	mpu3050_close(mldl_cfg, client->adapter,
+		accel_adapter, compass_adapter, pressure_adapter);
+
+	if (client->irq)
+		mpuirq_exit();
+
+	if (pdata &&
+	    pdata->pressure.get_slave_descr &&
+	    pdata->pressure.irq)
+		slaveirq_exit(&pdata->pressure);
+
+	if (pdata &&
+	    pdata->compass.get_slave_descr &&
+	    pdata->compass.irq)
+		slaveirq_exit(&pdata->compass);
+
+	if (pdata &&
+	    pdata->accel.get_slave_descr &&
+	    pdata->accel.irq)
+		slaveirq_exit(&pdata->accel);
+
+	misc_deregister(&i2c_mpu_device);
+	kfree(mpu);
+
+	return 0;
+}
+
+static const struct i2c_device_id mpu3050_id[] = {
+	{MPU_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, mpu3050_id);
+
+static struct i2c_driver mpu3050_driver = {
+	.class = I2C_CLASS_HWMON,
+	.probe = mpu3050_probe,
+	.remove = mpu3050_remove,
+	.id_table = mpu3050_id,
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = MPU_NAME,
+		   },
+	.address_list = normal_i2c,
+	.shutdown = mpu_shutdown,	
+	.suspend = mpu_suspend,	
+	.resume = mpu_resume,	
+
+};
+
+static int __init mpu_init(void)
+{
+	int res = i2c_add_driver(&mpu3050_driver);
+	pid = 0;
+	printk(KERN_DEBUG "%s\n", __func__);
+	if (res)
+		dev_err(&this_client->adapter->dev, "[mpu_err]%s failed\n",
+			__func__);
+	return res;
+}
+
+static void __exit mpu_exit(void)
+{
+	printk(KERN_DEBUG "%s\n", __func__);
+	i2c_del_driver(&mpu3050_driver);
+}
+
+module_init(mpu_init);
+module_exit(mpu_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("User space character device interface for MPU3050");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(MPU_NAME);
diff --git a/drivers/input/misc/mpu3050/mpu-i2c.c b/drivers/input/misc/mpu3050/mpu-i2c.c
new file mode 100644
index 0000000..0953e6a
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mpu-i2c.c
@@ -0,0 +1,252 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include "mpu.h"
+#define MPU_I2C_RETRY_ENABLE 1
+#define MPU_I2C_RETRY_TIMES 10
+#define MPU_I2C_DELAY_TIMES_MS 10
+
+int sensor_i2c_write(struct i2c_adapter *i2c_adap,
+		     unsigned char address,
+		     unsigned int len, unsigned char const *data)
+{
+	struct i2c_msg msgs[1];
+	int res;
+	int i;
+
+	if (NULL == data || NULL == i2c_adap)
+		return -EINVAL;
+
+	msgs[0].addr = address;
+	msgs[0].flags = 0;	
+	msgs[0].buf = (unsigned char *) data;
+	msgs[0].len = len;
+
+#if MPU_I2C_RETRY_ENABLE
+		for (i = 0; i < MPU_I2C_RETRY_TIMES; i++) {
+			res = i2c_transfer(i2c_adap, msgs, 1);
+			if (res < 1) {
+				printk(KERN_ERR "I2c Slave address: %x,\
+				sensor_i2c_write fail,\
+				retry:%d\n", address, i);
+				mdelay(MPU_I2C_DELAY_TIMES_MS);
+			} else
+				return 0;
+
+		}
+		return res;
+#else
+	res = i2c_transfer(i2c_adap, msgs, 1);
+	if (res < 1)
+		return res;
+	else
+		return 0;
+#endif
+}
+
+int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
+			      unsigned char address,
+			      unsigned char reg, unsigned char value)
+{
+	unsigned char data[2];
+
+	data[0] = reg;
+	data[1] = value;
+	return sensor_i2c_write(i2c_adap, address, 2, data);
+}
+
+int sensor_i2c_read(struct i2c_adapter *i2c_adap,
+		    unsigned char address,
+		    unsigned char reg,
+		    unsigned int len, unsigned char *data)
+{
+	struct i2c_msg msgs[2];
+	int res;
+	int i;
+
+	if (NULL == data || NULL == i2c_adap)
+		return -EINVAL;
+
+	msgs[0].addr = address;
+	msgs[0].flags = 0;	
+	msgs[0].buf = &reg;
+	msgs[0].len = 1;
+
+	msgs[1].addr = address;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].buf = data;
+	msgs[1].len = len;
+
+#if MPU_I2C_RETRY_ENABLE
+		for (i = 0; i < MPU_I2C_RETRY_TIMES; i++) {
+			res = i2c_transfer(i2c_adap, msgs, 2);
+			if (res < 2) {
+				printk(KERN_ERR "I2c Slave address: %x,\
+				sensor_i2c_read fail,\
+				retry:%d\n", address, i);
+				mdelay(MPU_I2C_DELAY_TIMES_MS);
+			} else
+				return 0;
+
+		}
+		return res;
+#else
+	res = i2c_transfer(i2c_adap, msgs, 2);
+	if (res < 2)
+		return res;
+	else
+		return 0;
+#endif
+}
+
+int mpu_memory_read(struct i2c_adapter *i2c_adap,
+		    unsigned char mpu_addr,
+		    unsigned short mem_addr,
+		    unsigned int len, unsigned char *data)
+{
+	unsigned char bank[2];
+	unsigned char addr[2];
+	unsigned char buf;
+
+	struct i2c_msg msgs[4];
+	int ret;
+	int i;
+
+	if (NULL == data || NULL == i2c_adap)
+		return -EINVAL;
+
+	bank[0] = MPUREG_BANK_SEL;
+	bank[1] = mem_addr >> 8;
+
+	addr[0] = MPUREG_MEM_START_ADDR;
+	addr[1] = mem_addr & 0xFF;
+
+	buf = MPUREG_MEM_R_W;
+
+	
+	msgs[0].addr = mpu_addr;
+	msgs[0].flags = 0;
+	msgs[0].buf = bank;
+	msgs[0].len = sizeof(bank);
+
+	msgs[1].addr = mpu_addr;
+	msgs[1].flags = 0;
+	msgs[1].buf = addr;
+	msgs[1].len = sizeof(addr);
+
+	msgs[2].addr = mpu_addr;
+	msgs[2].flags = 0;
+	msgs[2].buf = &buf;
+	msgs[2].len = 1;
+
+	msgs[3].addr = mpu_addr;
+	msgs[3].flags = I2C_M_RD;
+	msgs[3].buf = data;
+	msgs[3].len = len;
+
+#if MPU_I2C_RETRY_ENABLE
+		for (i = 0; i < MPU_I2C_RETRY_TIMES; i++) {
+			ret = i2c_transfer(i2c_adap, msgs, 4);
+			if (ret != 4) {
+				printk(KERN_ERR "I2c Slave address: %x,\
+				mpu_memory_read,\
+				retry:%d\n", mpu_addr, i);
+				mdelay(MPU_I2C_DELAY_TIMES_MS);
+			} else
+				return 0;
+
+		}
+		return ret;
+#else
+	ret = i2c_transfer(i2c_adap, msgs, 4);
+	if (ret != 4)
+		return ret;
+	else
+		return 0;
+#endif
+}
+
+int mpu_memory_write(struct i2c_adapter *i2c_adap,
+		     unsigned char mpu_addr,
+		     unsigned short mem_addr,
+		     unsigned int len, unsigned char const *data)
+{
+	unsigned char bank[2];
+	unsigned char addr[2];
+	unsigned char buf[513];
+
+	struct i2c_msg msgs[3];
+	int ret;
+	int i;
+
+	if (NULL == data || NULL == i2c_adap)
+		return -EINVAL;
+	if (len >= (sizeof(buf) - 1))
+		return -ENOMEM;
+
+	bank[0] = MPUREG_BANK_SEL;
+	bank[1] = mem_addr >> 8;
+
+	addr[0] = MPUREG_MEM_START_ADDR;
+	addr[1] = mem_addr & 0xFF;
+
+	buf[0] = MPUREG_MEM_R_W;
+	memcpy(buf + 1, data, len);
+
+	
+	msgs[0].addr = mpu_addr;
+	msgs[0].flags = 0;
+	msgs[0].buf = bank;
+	msgs[0].len = sizeof(bank);
+
+	msgs[1].addr = mpu_addr;
+	msgs[1].flags = 0;
+	msgs[1].buf = addr;
+	msgs[1].len = sizeof(addr);
+
+	msgs[2].addr = mpu_addr;
+	msgs[2].flags = 0;
+	msgs[2].buf = (unsigned char *) buf;
+	msgs[2].len = len + 1;
+
+#if MPU_I2C_RETRY_ENABLE
+		for (i = 0; i < MPU_I2C_RETRY_TIMES; i++) {
+			ret = i2c_transfer(i2c_adap, msgs, 3);
+			if (ret != 3) {
+				printk(KERN_ERR "I2c Slave address: %x,\
+				mpu_memory_write,\
+				retry:%d\n", mpu_addr, i);
+				mdelay(MPU_I2C_DELAY_TIMES_MS);
+			} else
+				return 0;
+
+		}
+		return ret;
+#else
+	ret = i2c_transfer(i2c_adap, msgs, 3);
+	if (ret != 3)
+		return ret;
+	else
+		return 0;
+#endif
+}
+
diff --git a/drivers/input/misc/mpu3050/mpu-i2c.h b/drivers/input/misc/mpu3050/mpu-i2c.h
new file mode 100644
index 0000000..c26aafb
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mpu-i2c.h
@@ -0,0 +1,48 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __MPU_I2C_H__
+#define __MPU_I2C_H__
+
+#include <linux/i2c.h>
+
+int sensor_i2c_write(struct i2c_adapter *i2c_adap,
+		     unsigned char address,
+		     unsigned int len, unsigned char const *data);
+
+int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
+			      unsigned char address,
+			      unsigned char reg, unsigned char value);
+
+int sensor_i2c_read(struct i2c_adapter *i2c_adap,
+		    unsigned char address,
+		    unsigned char reg,
+		    unsigned int len, unsigned char *data);
+
+int mpu_memory_read(struct i2c_adapter *i2c_adap,
+		    unsigned char mpu_addr,
+		    unsigned short mem_addr,
+		    unsigned int len, unsigned char *data);
+
+int mpu_memory_write(struct i2c_adapter *i2c_adap,
+		     unsigned char mpu_addr,
+		     unsigned short mem_addr,
+		     unsigned int len, unsigned char const *data);
+
+#endif	
diff --git a/drivers/input/misc/mpu3050/mpuirq.c b/drivers/input/misc/mpu3050/mpuirq.c
new file mode 100644
index 0000000..561d6cf
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mpuirq.c
@@ -0,0 +1,319 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include "mpu.h"
+#include "mpuirq.h"
+#include "mldl_cfg.h"
+#include "mpu-i2c.h"
+
+#define MPUIRQ_NAME "mpuirq"
+
+
+DECLARE_WAIT_QUEUE_HEAD(mpuirq_wait);
+
+struct mpuirq_dev_data {
+	struct work_struct work;
+	struct i2c_client *mpu_client;
+	struct miscdevice *dev;
+	int irq;
+	int pid;
+	int accel_divider;
+	int data_ready;
+	int timeout;
+};
+
+static struct mpuirq_dev_data mpuirq_dev_data;
+static struct mpuirq_data mpuirq_data;
+static char *interface = MPUIRQ_NAME;
+
+static void mpu_accel_data_work_fcn(struct work_struct *work);
+
+static int mpuirq_open(struct inode *inode, struct file *file)
+{
+	dev_dbg(mpuirq_dev_data.dev->this_device,
+		"%s current->pid %d\n", __func__, current->pid);
+	mpuirq_dev_data.pid = current->pid;
+	file->private_data = &mpuirq_dev_data;
+	
+	
+	
+	return 0;
+}
+
+static int mpuirq_release(struct inode *inode, struct file *file)
+{
+	dev_dbg(mpuirq_dev_data.dev->this_device, "mpuirq_release\n");
+	return 0;
+}
+
+static ssize_t mpuirq_read(struct file *file,
+			   char *buf, size_t count, loff_t *ppos)
+{
+	int len, err;
+	struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
+
+	if (!mpuirq_dev_data.data_ready) {
+		wait_event_interruptible_timeout(mpuirq_wait,
+						 mpuirq_dev_data.
+						 data_ready,
+						 mpuirq_dev_data.timeout);
+	}
+
+	if (mpuirq_dev_data.data_ready && NULL != buf
+	    && count >= sizeof(mpuirq_data)) {
+		err = copy_to_user(buf, &mpuirq_data, sizeof(mpuirq_data));
+		mpuirq_data.data_type = 0;
+	} else {
+		return 0;
+	}
+	if (err != 0) {
+		dev_err(p_mpuirq_dev_data->dev->this_device,
+			"Copy to user returned %d\n", err);
+		return -EFAULT;
+	}
+	mpuirq_dev_data.data_ready = 0;
+	len = sizeof(mpuirq_data);
+	return len;
+}
+
+unsigned int mpuirq_poll(struct file *file, struct poll_table_struct *poll)
+{
+	int mask = 0;
+
+	poll_wait(file, &mpuirq_wait, poll);
+	if (mpuirq_dev_data.data_ready)
+		mask |= POLLIN | POLLRDNORM;
+	return mask;
+}
+
+static long mpuirq_ioctl(struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+	int data;
+
+	switch (cmd) {
+	case MPUIRQ_SET_TIMEOUT:
+		mpuirq_dev_data.timeout = arg;
+		break;
+
+	case MPUIRQ_GET_INTERRUPT_CNT:
+		data = mpuirq_data.interruptcount - 1;
+		if (mpuirq_data.interruptcount > 1)
+			mpuirq_data.interruptcount = 1;
+
+		if (copy_to_user((int *) arg, &data, sizeof(int)))
+			return -EFAULT;
+		break;
+	case MPUIRQ_GET_IRQ_TIME:
+		if (copy_to_user((int *) arg, &mpuirq_data.irqtime,
+				 sizeof(mpuirq_data.irqtime)))
+			return -EFAULT;
+		mpuirq_data.irqtime = 0;
+		break;
+	case MPUIRQ_SET_FREQUENCY_DIVIDER:
+		mpuirq_dev_data.accel_divider = arg;
+		break;
+	case MPUIRQ_GET_DEBUG_FLAG:
+		if (copy_to_user((int *) arg, &mpu_debug_flag, sizeof(int)))
+			return -EFAULT;
+		break;
+	default:
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static void mpu_accel_data_work_fcn(struct work_struct *work)
+{
+	struct mpuirq_dev_data *mpuirq_dev_data =
+	    (struct mpuirq_dev_data *) work;
+	struct mldl_cfg *mldl_cfg =
+	    (struct mldl_cfg *)
+	    i2c_get_clientdata(mpuirq_dev_data->mpu_client);
+	struct i2c_adapter *accel_adapter;
+	unsigned char wbuff[16];
+	unsigned char rbuff[16];
+	int ii;
+
+	accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+	mldl_cfg->accel->read(accel_adapter,
+			      mldl_cfg->accel,
+			      &mldl_cfg->pdata->accel, rbuff);
+
+
+	
+	if (EXT_SLAVE_BIG_ENDIAN == mldl_cfg->accel->endian) {
+		for (ii = 0; ii < 3; ii++) {
+			wbuff[2 * ii + 1] = rbuff[2 * ii + 1];
+			wbuff[2 * ii + 2] = rbuff[2 * ii + 0];
+		}
+	} else {
+		memcpy(wbuff + 1, rbuff, mldl_cfg->accel->len);
+	}
+
+	wbuff[7] = 0;
+	wbuff[8] = 1;		
+
+	mpu_memory_write(mpuirq_dev_data->mpu_client->adapter,
+			 mldl_cfg->addr, 0x0108, 8, wbuff);
+}
+
+static irqreturn_t mpuirq_handler(int irq, void *dev_id)
+{
+	static int mycount;
+	struct timeval irqtime;
+	mycount++;
+
+	mpuirq_data.interruptcount++;
+
+	
+	
+	mpuirq_dev_data.data_ready = 1;
+
+	do_gettimeofday(&irqtime);
+	mpuirq_data.irqtime = (((long long) irqtime.tv_sec) << 32);
+	mpuirq_data.irqtime += irqtime.tv_usec;
+
+	if ((mpuirq_dev_data.accel_divider >= 0) &&
+		(0 == (mycount % (mpuirq_dev_data.accel_divider + 1)))) {
+		schedule_work((struct work_struct
+				*) (&mpuirq_dev_data));
+	}
+
+	wake_up_interruptible(&mpuirq_wait);
+
+	return IRQ_HANDLED;
+
+}
+
+const struct file_operations mpuirq_fops = {
+	.owner = THIS_MODULE,
+	.read = mpuirq_read,
+	.poll = mpuirq_poll,
+
+#if HAVE_COMPAT_IOCTL
+	.compat_ioctl = mpuirq_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+	.unlocked_ioctl = mpuirq_ioctl,
+#endif
+	.open = mpuirq_open,
+	.release = mpuirq_release,
+};
+
+static struct miscdevice mpuirq_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = MPUIRQ_NAME,
+	.fops = &mpuirq_fops,
+};
+
+int mpuirq_init(struct i2c_client *mpu_client)
+{
+
+	int res;
+	struct mldl_cfg *mldl_cfg =
+	    (struct mldl_cfg *) i2c_get_clientdata(mpu_client);
+
+	
+	INIT_WORK((struct work_struct *) &mpuirq_dev_data,
+		  mpu_accel_data_work_fcn);
+	mpuirq_dev_data.mpu_client = mpu_client;
+
+	dev_info(&mpu_client->adapter->dev,
+		 "Module Param interface = %s\n", interface);
+
+	mpuirq_dev_data.irq = mpu_client->irq;
+	mpuirq_dev_data.pid = 0;
+	mpuirq_dev_data.accel_divider = -1;
+	mpuirq_dev_data.data_ready = 0;
+	mpuirq_dev_data.timeout = 0;
+	mpuirq_dev_data.dev = &mpuirq_device;
+
+	if (mpuirq_dev_data.irq) {
+		unsigned long flags;
+		if (BIT_ACTL_LOW ==
+		    ((mldl_cfg->pdata->int_config) & BIT_ACTL))
+			flags = IRQF_TRIGGER_FALLING;
+		else
+			flags = IRQF_TRIGGER_RISING;
+
+		res =
+		    request_irq(mpuirq_dev_data.irq, mpuirq_handler, flags,
+				interface, &mpuirq_dev_data.irq);
+		if (res) {
+			dev_err(&mpu_client->adapter->dev,
+				"myirqtest: cannot register IRQ %d\n",
+				mpuirq_dev_data.irq);
+		} else {
+			res = misc_register(&mpuirq_device);
+			if (res < 0) {
+				dev_err(&mpu_client->adapter->dev,
+					"misc_register returned %d\n",
+					res);
+				free_irq(mpuirq_dev_data.irq,
+					 &mpuirq_dev_data.irq);
+			}
+		}
+
+	} else {
+		res = 0;
+	}
+
+	return res;
+}
+
+void mpuirq_exit(void)
+{
+	
+	if (mpuirq_dev_data.irq > 0)
+		free_irq(mpuirq_dev_data.irq, &mpuirq_dev_data.irq);
+
+	flush_scheduled_work();
+
+	dev_info(mpuirq_device.this_device, "Unregistering %s\n",
+		 MPUIRQ_NAME);
+	misc_deregister(&mpuirq_device);
+
+	return;
+}
+
+module_param(interface, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(interface, "The Interface name");
diff --git a/drivers/input/misc/mpu3050/mpuirq.h b/drivers/input/misc/mpu3050/mpuirq.h
new file mode 100644
index 0000000..54c2e88
--- /dev/null
+++ b/drivers/input/misc/mpu3050/mpuirq.h
@@ -0,0 +1,45 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __MPUIRQ__
+#define __MPUIRQ__
+
+#ifdef __KERNEL__
+#include <linux/i2c-dev.h>
+#endif
+
+#define MPUIRQ_ENABLE_DEBUG          (1)
+#define MPUIRQ_GET_INTERRUPT_CNT     (2)
+#define MPUIRQ_GET_IRQ_TIME          (3)
+#define MPUIRQ_GET_LED_VALUE         (4)
+#define MPUIRQ_SET_TIMEOUT           (5)
+#define MPUIRQ_SET_ACCEL_INFO        (6)
+#define MPUIRQ_SET_FREQUENCY_DIVIDER (7)
+#define MPUIRQ_GET_DEBUG_FLAG        (8)
+
+extern int mpu_debug_flag;
+
+#ifdef __KERNEL__
+
+void mpuirq_exit(void);
+int mpuirq_init(struct i2c_client *mpu_client);
+
+#endif
+
+#endif
diff --git a/drivers/input/misc/mpu3050/slaveirq.c b/drivers/input/misc/mpu3050/slaveirq.c
new file mode 100644
index 0000000..d985c26
--- /dev/null
+++ b/drivers/input/misc/mpu3050/slaveirq.c
@@ -0,0 +1,262 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+
+#include "mpu.h"
+#include "slaveirq.h"
+#include "mldl_cfg.h"
+#include "mpu-i2c.h"
+
+
+struct slaveirq_dev_data {
+	struct miscdevice dev;
+	struct i2c_client *slave_client;
+	struct mpuirq_data data;
+	wait_queue_head_t slaveirq_wait;
+	int irq;
+	int pid;
+	int data_ready;
+	int timeout;
+};
+
+static int slaveirq_open(struct inode *inode, struct file *file)
+{
+	struct slaveirq_dev_data *data =
+		container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+	dev_dbg(data->dev.this_device,
+		"%s current->pid %d\n", __func__, current->pid);
+	data->pid = current->pid;
+	return 0;
+}
+
+static int slaveirq_release(struct inode *inode, struct file *file)
+{
+	struct slaveirq_dev_data *data =
+		container_of(file->private_data, struct slaveirq_dev_data, dev);
+	dev_dbg(data->dev.this_device, "slaveirq_release\n");
+	return 0;
+}
+
+static ssize_t slaveirq_read(struct file *file,
+			   char *buf, size_t count, loff_t *ppos)
+{
+	int len, err;
+	struct slaveirq_dev_data *data =
+		container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+	if (!data->data_ready) {
+		wait_event_interruptible_timeout(data->slaveirq_wait,
+						 data->data_ready,
+						 data->timeout);
+	}
+
+	if (data->data_ready && NULL != buf
+	    && count >= sizeof(data->data)) {
+		err = copy_to_user(buf, &data->data, sizeof(data->data));
+		data->data.data_type = 0;
+	} else {
+		return 0;
+	}
+	if (err != 0) {
+		dev_err(data->dev.this_device,
+			"Copy to user returned %d\n", err);
+		return -EFAULT;
+	}
+	data->data_ready = 0;
+	len = sizeof(data->data);
+	return len;
+}
+
+unsigned int slaveirq_poll(struct file *file, struct poll_table_struct *poll)
+{
+	int mask = 0;
+	struct slaveirq_dev_data *data =
+		container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+	poll_wait(file, &data->slaveirq_wait, poll);
+	if (data->data_ready)
+		mask |= POLLIN | POLLRDNORM;
+	return mask;
+}
+
+static long slaveirq_ioctl(struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+	int tmp;
+	struct slaveirq_dev_data *data =
+		container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+	switch (cmd) {
+	case SLAVEIRQ_SET_TIMEOUT:
+		data->timeout = arg;
+		break;
+
+	case SLAVEIRQ_GET_INTERRUPT_CNT:
+		tmp = data->data.interruptcount - 1;
+		if (data->data.interruptcount > 1)
+			data->data.interruptcount = 1;
+
+		if (copy_to_user((int *) arg, &tmp, sizeof(int)))
+			return -EFAULT;
+		break;
+	case SLAVEIRQ_GET_IRQ_TIME:
+		if (copy_to_user((int *) arg, &data->data.irqtime,
+				 sizeof(data->data.irqtime)))
+			return -EFAULT;
+		data->data.irqtime = 0;
+		break;
+	default:
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static irqreturn_t slaveirq_handler(int irq, void *dev_id)
+{
+	struct slaveirq_dev_data *data = (struct slaveirq_dev_data *)dev_id;
+	static int mycount;
+	struct timeval irqtime;
+	mycount++;
+
+	data->data.interruptcount++;
+
+	
+	
+	data->data_ready = 1;
+
+	do_gettimeofday(&irqtime);
+	data->data.irqtime = (((long long) irqtime.tv_sec) << 32);
+	data->data.irqtime += irqtime.tv_usec;
+	data->data.data_type |= 1;
+
+	wake_up_interruptible(&data->slaveirq_wait);
+
+	return IRQ_HANDLED;
+
+}
+
+static const struct file_operations slaveirq_fops = {
+	.owner = THIS_MODULE,
+	.read = slaveirq_read,
+	.poll = slaveirq_poll,
+
+#if HAVE_COMPAT_IOCTL
+	.compat_ioctl = slaveirq_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+	.unlocked_ioctl = slaveirq_ioctl,
+#endif
+	.open = slaveirq_open,
+	.release = slaveirq_release,
+};
+
+int slaveirq_init(struct i2c_adapter *slave_adapter,
+		  struct ext_slave_platform_data *pdata,
+		  char *name)
+{
+
+	int res;
+	struct slaveirq_dev_data *data;
+
+	if (!pdata->irq)
+		return -EINVAL;
+
+	pdata->irq_data = kzalloc(sizeof(*data),
+				GFP_KERNEL);
+	data = (struct slaveirq_dev_data *) pdata->irq_data;
+	if (!data)
+		return -ENOMEM;
+
+	data->dev.minor = MISC_DYNAMIC_MINOR;
+	data->dev.name = name;
+	data->dev.fops = &slaveirq_fops;
+	data->irq = pdata->irq;
+	data->pid = 0;
+	data->data_ready = 0;
+	data->timeout = 0;
+
+	init_waitqueue_head(&data->slaveirq_wait);
+
+	res = request_irq(data->irq, slaveirq_handler, IRQF_TRIGGER_RISING,
+			  data->dev.name, data);
+
+	if (res) {
+		dev_err(&slave_adapter->dev,
+			"myirqtest: cannot register IRQ %d\n",
+			data->irq);
+		goto out_request_irq;
+	}
+
+	res = misc_register(&data->dev);
+	if (res < 0) {
+		dev_err(&slave_adapter->dev,
+			"misc_register returned %d\n",
+			res);
+		goto out_misc_register;
+	}
+
+	return res;
+
+out_misc_register:
+	free_irq(data->irq, data);
+out_request_irq:
+	kfree(pdata->irq_data);
+	pdata->irq_data = NULL;
+
+	return res;
+}
+
+void slaveirq_exit(struct ext_slave_platform_data *pdata)
+{
+	struct slaveirq_dev_data *data = pdata->irq_data;
+
+	if (!pdata->irq_data || data->irq <= 0)
+		return;
+
+	dev_info(data->dev.this_device, "Unregistering %s\n",
+		 data->dev.name);
+
+	free_irq(data->irq, data);
+	misc_deregister(&data->dev);
+	kfree(pdata->irq_data);
+	pdata->irq_data = NULL;
+}
diff --git a/drivers/input/misc/mpu3050/slaveirq.h b/drivers/input/misc/mpu3050/slaveirq.h
new file mode 100644
index 0000000..ca9c7e4
--- /dev/null
+++ b/drivers/input/misc/mpu3050/slaveirq.h
@@ -0,0 +1,46 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __SLAVEIRQ__
+#define __SLAVEIRQ__
+
+#ifdef __KERNEL__
+#include <linux/i2c-dev.h>
+#endif
+
+#include "mpu.h"
+#include "mpuirq.h"
+
+#define SLAVEIRQ_ENABLE_DEBUG          (1)
+#define SLAVEIRQ_GET_INTERRUPT_CNT     (2)
+#define SLAVEIRQ_GET_IRQ_TIME          (3)
+#define SLAVEIRQ_GET_LED_VALUE         (4)
+#define SLAVEIRQ_SET_TIMEOUT           (5)
+#define SLAVEIRQ_SET_SLAVE_INFO        (6)
+
+#ifdef __KERNEL__
+
+void slaveirq_exit(struct ext_slave_platform_data *pdata);
+int slaveirq_init(struct i2c_adapter *slave_adapter,
+		struct ext_slave_platform_data *pdata,
+		char *name);
+
+#endif
+
+#endif
diff --git a/drivers/input/misc/mpu3050/timerirq.c b/drivers/input/misc/mpu3050/timerirq.c
new file mode 100644
index 0000000..ce2b153
--- /dev/null
+++ b/drivers/input/misc/mpu3050/timerirq.c
@@ -0,0 +1,316 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+
+#include "mpu.h"
+#include "mltypes.h"
+#include "timerirq.h"
+
+struct timerirq_data {
+	int pid;
+	int data_ready;
+	int run;
+	int timeout;
+	unsigned long period;
+	struct mpuirq_data data;
+	struct completion timer_done;
+	wait_queue_head_t timerirq_wait;
+	struct timer_list timer;
+	struct miscdevice *dev;
+};
+
+static struct miscdevice *timerirq_dev_data;
+
+static void timerirq_handler(unsigned long arg)
+{
+	struct timerirq_data *data = (struct timerirq_data *)arg;
+	struct timeval irqtime;
+
+
+	data->data.interruptcount++;
+
+	data->data_ready = 1;
+
+	do_gettimeofday(&irqtime);
+	data->data.irqtime = (((long long) irqtime.tv_sec) << 32);
+	data->data.irqtime += irqtime.tv_usec;
+	data->data.data_type |= 1;
+
+	wake_up_interruptible(&data->timerirq_wait);
+
+	if (data->run)
+		mod_timer(&data->timer,
+			jiffies + msecs_to_jiffies(data->period));
+	else
+		complete(&data->timer_done);
+}
+
+static int start_timerirq(struct timerirq_data *data)
+{
+	dev_dbg(data->dev->this_device,
+		"%s current->pid %d\n", __func__, current->pid);
+
+	
+	if (data->run)
+		return 0;
+
+	
+	if (!data->period)
+		return -EINVAL;
+
+	if (data->period > 200)
+		data->period = 200;
+
+	printk(KERN_DEBUG "[GSNR][MPU3050][TIMERIRQ]%s: data->period = %lu\n",
+		__func__, data->period);
+
+	data->run = TRUE;
+	data->data_ready = FALSE;
+
+	return mod_timer(&data->timer,
+			jiffies + msecs_to_jiffies(data->period));
+}
+
+static int stop_timerirq(struct timerirq_data *data)
+{
+	int rc = -1;
+
+	dev_dbg(data->dev->this_device,
+		"%s current->pid %lx\n", __func__, (unsigned long)data);
+
+	printk(KERN_DEBUG "[GSNR][MPU3050][TIMERIRQ]%s: data->period = %lu, "
+			  "data->run = %d\n",
+			__func__, data->period, data->run);
+
+	if (data->run) {
+		data->run = FALSE;
+		mod_timer(&data->timer, jiffies + 1);
+		wait_for_completion(&data->timer_done);
+
+		rc = del_timer_sync(&(data->timer));
+	}
+	return 0;
+}
+
+static int timerirq_open(struct inode *inode, struct file *file)
+{
+	struct miscdevice *dev_data = file->private_data;
+	struct timerirq_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = dev_data;
+	file->private_data = data;
+	data->pid = current->pid;
+	init_waitqueue_head(&data->timerirq_wait);
+
+	dev_dbg(data->dev->this_device,
+		"%s current->pid %d\n", __func__, current->pid);
+
+	init_completion(&data->timer_done);
+	setup_timer(&data->timer, timerirq_handler, (unsigned long)data);
+
+	printk(KERN_DEBUG "[TIMERIRQ]%s: current->pid %d\n",
+		__func__, current->pid);
+
+	return 0;
+}
+
+static int timerirq_release(struct inode *inode, struct file *file)
+{
+	struct timerirq_data *data = file->private_data;
+	int rc = -1;
+
+	printk(KERN_DEBUG "[TIMERIRQ] %s: data->run = %d\n",
+				__func__, data->run);
+
+	
+
+	if (data->run)
+		stop_timerirq(data);
+
+	rc = del_timer_sync(&(data->timer));
+	printk(KERN_DEBUG "[TIMERIRQ]%s: del_timer_sync"
+		"() return = %d\n", __func__, rc);
+
+	kfree(data);
+	return 0;
+}
+
+static ssize_t timerirq_read(struct file *file,
+			   char *buf, size_t count, loff_t *ppos)
+{
+	int len, err;
+	struct timerirq_data *data = file->private_data;
+
+	if (!data->data_ready) {
+		wait_event_interruptible_timeout(data->timerirq_wait,
+						 data->data_ready,
+						 data->timeout);
+	}
+
+	if (data->data_ready && NULL != buf
+	    && count >= sizeof(data->data)) {
+		err = copy_to_user(buf, &data->data, sizeof(data->data));
+		data->data.data_type = 0;
+	} else {
+		return 0;
+	}
+	if (err != 0) {
+		dev_err(data->dev->this_device,
+			"Copy to user returned %d\n", err);
+		return -EFAULT;
+	}
+	data->data_ready = 0;
+	len = sizeof(data->data);
+	return len;
+}
+
+unsigned int timerirq_poll(struct file *file, struct poll_table_struct *poll)
+{
+	int mask = 0;
+	struct timerirq_data *data = file->private_data;
+
+	poll_wait(file, &data->timerirq_wait, poll);
+	if (data->data_ready)
+		mask |= POLLIN | POLLRDNORM;
+	return mask;
+}
+
+static long timerirq_ioctl(struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+	int tmp;
+	struct timerirq_data *data = file->private_data;
+
+	dev_dbg(data->dev->this_device,
+		"%s current->pid %d, %d, %ld\n",
+		__func__, current->pid, cmd, arg);
+
+	if (!data)
+		return -EFAULT;
+
+	switch (cmd) {
+	case TIMERIRQ_SET_TIMEOUT:
+		data->timeout = arg;
+		break;
+	case TIMERIRQ_GET_INTERRUPT_CNT:
+		tmp = data->data.interruptcount - 1;
+		if (data->data.interruptcount > 1)
+			data->data.interruptcount = 1;
+
+		if (copy_to_user((int *) arg, &tmp, sizeof(int)))
+			return -EFAULT;
+		break;
+	case TIMERIRQ_START:
+		data->period = arg;
+		retval = start_timerirq(data);
+		break;
+	case TIMERIRQ_STOP:
+		retval = stop_timerirq(data);
+		break;
+	default:
+		retval = -EINVAL;
+	}
+	return retval;
+}
+
+static const struct file_operations timerirq_fops = {
+	.owner = THIS_MODULE,
+	.read = timerirq_read,
+	.poll = timerirq_poll,
+
+#if HAVE_COMPAT_IOCTL
+	.compat_ioctl = timerirq_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+	.unlocked_ioctl = timerirq_ioctl,
+#endif
+	.open = timerirq_open,
+	.release = timerirq_release,
+};
+
+static int __init timerirq_init(void)
+{
+
+	int res;
+	static struct miscdevice *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	timerirq_dev_data = data;
+	data->minor = MISC_DYNAMIC_MINOR;
+	data->name = "timerirq";
+	data->fops = &timerirq_fops;
+
+	res = misc_register(data);
+	if (res < 0) {
+		dev_err(data->this_device,
+			"misc_register returned %d\n",
+			res);
+		return res;
+	}
+
+	return res;
+}
+module_init(timerirq_init);
+
+static void __exit timerirq_exit(void)
+{
+	struct miscdevice *data = timerirq_dev_data;
+
+	dev_info(data->this_device, "Unregistering %s\n",
+		 data->name);
+
+	printk(KERN_DEBUG "[TIMERIRQ]%s: Unregistering %s\n",
+		__func__, data->name);
+
+	misc_deregister(data);
+	kfree(data);
+
+	timerirq_dev_data = NULL;
+}
+module_exit(timerirq_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Timer IRQ device driver.");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("timerirq");
diff --git a/drivers/input/misc/mpu3050/timerirq.h b/drivers/input/misc/mpu3050/timerirq.h
new file mode 100644
index 0000000..a38b490
--- /dev/null
+++ b/drivers/input/misc/mpu3050/timerirq.h
@@ -0,0 +1,28 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __TIMERIRQ__
+#define __TIMERIRQ__
+
+#define TIMERIRQ_SET_TIMEOUT           (5)
+#define TIMERIRQ_GET_INTERRUPT_CNT     (7)
+#define TIMERIRQ_START                 (8)
+#define TIMERIRQ_STOP                  (9)
+
+#endif