summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorWen Yi <wyi@nvidia.com>2011-01-28 14:38:45 -0800
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:46:33 -0800
commitc2d4340aa561998b4afc87cd935c22f2c1b113f4 (patch)
treef30452f935159209ad025593eaf1db477942cd17 /drivers/misc
parentdf3ec81e193b55c04362ab2fbbf4611a4f41947c (diff)
Port Invensense MPU3050 drivers into tegra-2.6.36
Original-Change-Id: Iceb3ef8b11d4ce18fd3cb0947268744775b81758 Reviewed-on: http://git-master/r/17525 Reviewed-by: Daniel Willemsen <dwillemsen@nvidia.com> Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: R5aa1acdb6de5265529a9695f6cc996d4cf0dbfec
Diffstat (limited to 'drivers/misc')
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/Kconfig54
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/Makefile84
-rwxr-xr-xdrivers/misc/mpu3050/README138
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/accel/kxtf9.c69
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/compass/ak8975.c79
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/log.h71
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mldl_cfg.c1023
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mldl_cfg.h81
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mlos-kernel.c3
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mlos.h5
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mlsl-kernel.c258
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mlsl.h64
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mltypes.h68
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mpu-dev.c709
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mpu-i2c.c53
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mpu-i2c.h8
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mpuirq.c76
-rw-r--r--[-rwxr-xr-x]drivers/misc/mpu3050/mpuirq.h8
-rw-r--r--drivers/misc/mpu3050/slaveirq.c272
-rw-r--r--drivers/misc/mpu3050/slaveirq.h46
20 files changed, 2352 insertions, 817 deletions
diff --git a/drivers/misc/mpu3050/Kconfig b/drivers/misc/mpu3050/Kconfig
index 99ea1c6aa8e2..579ffd2665fb 100755..100644
--- a/drivers/misc/mpu3050/Kconfig
+++ b/drivers/misc/mpu3050/Kconfig
@@ -1,20 +1,34 @@
menu "Motion Sensors Support"
+choice
+ tristate "Motion Processing Unit"
+ depends on I2C
+ default MPU_NONE
+
+config MPU_NONE
+ bool "None"
+ help
+ This disables support for motion processing using the MPU family of
+ motion processing units.
+
config SENSORS_MPU3050
- tristate "MPU3050 Gyroscope Driver"
+ 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.
-config SENSORS_MPU3050_DEBUG
- bool "MPU3050 debug"
- depends on SENSORS_MPU3050
+config SENSORS_MPU6000
+ tristate "MPU6000"
+ depends on I2C
help
- If you say yes here you get extra debug messages from the MPU3050
- and other slave sensors.
+ If you say yes here you get support for the MPU6000 Gyroscope driver
+ This driver can also be built as a module. If so, the module
+ will be called mpu6000.
+
+endchoice
choice
prompt "Accelerometer Type"
@@ -23,11 +37,13 @@ choice
config SENSORS_ACCELEROMETER_NONE
bool "NONE"
+ depends on SENSORS_MPU3050 || SENSORS_MPU6000
help
This disables accelerometer support for the MPU3050
config SENSORS_KXTF9_MPU
bool "Kionix KXTF9"
+ depends on SENSORS_MPU3050
help
This enables support for the Kionix KXFT9 accelerometer
@@ -35,20 +51,42 @@ endchoice
choice
prompt "Compass Type"
- depends on SENSORS_MPU3050
+ depends on SENSORS_MPU6000 || SENSORS_MPU3050
default SENSORS_AK8975_MPU
config SENSORS_COMPASS_NONE
bool "NONE"
+ depends on SENSORS_MPU6000 || SENSORS_MPU3050
help
- This disables compass support for the MPU3050
+ This disables compass support for the MPU6000
config SENSORS_AK8975_MPU
bool "AKM ak8975"
+ depends on SENSORS_MPU6000 || SENSORS_MPU3050
help
This enables support for the AKM ak8975 compass
endchoice
+choice
+ prompt "Pressure Type"
+ depends on SENSORS_MPU6000 || SENSORS_MPU3050
+ default SENSORS_NONE
+
+config SENSORS_PRESSURE_NONE
+ bool "NONE"
+ depends on SENSORS_MPU6000 || SENSORS_MPU3050
+ help
+ This disables pressure sensor support for the MPU6000
+
+endchoice
+
+config SENSORS_MPU_DEBUG
+ bool "MPU debug"
+ depends on SENSORS_MPU3050 || SENSORS_MPU6000
+ help
+ If you say yes here you get extra debug messages from the MPU3050
+ and other slave sensors.
+
endmenu
diff --git a/drivers/misc/mpu3050/Makefile b/drivers/misc/mpu3050/Makefile
index 99955ad487fc..c03e473e375b 100755..100644
--- a/drivers/misc/mpu3050/Makefile
+++ b/drivers/misc/mpu3050/Makefile
@@ -6,6 +6,7 @@
# MPU
obj-$(CONFIG_SENSORS_MPU3050) += mpu3050.o
mpu3050-objs += mpuirq.o \
+ slaveirq.o \
mpu-dev.o \
mpu-i2c.o \
mlsl-kernel.o \
@@ -15,10 +16,42 @@ mpu3050-objs += mpuirq.o \
#
# Accel options
#
+ifdef CONFIG_SENSORS_ADXL346
+mpu3050-objs += $(MLLITE_DIR)accel/adxl346.o
+endif
+
+ifdef CONFIG_SENSORS_BMA150
+mpu3050-objs += $(MLLITE_DIR)accel/bma150.o
+endif
+
+ifdef CONFIG_SENSORS_BMA222
+mpu3050-objs += $(MLLITE_DIR)accel/bma222.o
+endif
+
+ifdef CONFIG_SENSORS_KXSD9
+mpu3050-objs += $(MLLITE_DIR)accel/kxsd9.o
+endif
+
ifdef CONFIG_SENSORS_KXTF9_MPU
mpu3050-objs += $(MLLITE_DIR)accel/kxtf9.o
endif
+ifdef CONFIG_SENSORS_LIS331DLH
+mpu3050-objs += $(MLLITE_DIR)accel/lis331.o
+endif
+
+ifdef CONFIG_SENSORS_LSM303DLHA
+mpu3050-objs += $(MLLITE_DIR)accel/lsm303a.o
+endif
+
+ifdef CONFIG_SENSORS_MMA8450
+mpu3050-objs += $(MLLITE_DIR)accel/mma8450.o
+endif
+
+ifdef CONFIG_SENSORS_MMA8451
+mpu3050-objs += $(MLLITE_DIR)accel/mma8451.o
+endif
+
#
# Compass options
#
@@ -26,12 +59,59 @@ ifdef CONFIG_SENSORS_AK8975_MPU
mpu3050-objs += $(MLLITE_DIR)compass/ak8975.o
endif
+ifdef CONFIG_SENSORS_AMI30X
+mpu3050-objs += $(MLLITE_DIR)compass/ami30x.o
+endif
+
+ifdef CONFIG_SENSORS_HMC5883
+mpu3050-objs += $(MLLITE_DIR)compass/hmc5883.o
+endif
+
+ifdef CONFIG_SENSORS_LSM303DLHM
+mpu3050-objs += $(MLLITE_DIR)compass/lsm303m.o
+endif
+
+ifdef CONFIG_SENSORS_MMC314X
+mpu3050-objs += $(MLLITE_DIR)compass/mmc314x.o
+endif
+
+ifdef CONFIG_SENSORS_YAS529
+mpu3050-objs += $(MLLITE_DIR)compass/yas529-kernel.o
+endif
+
+ifdef CONFIG_SENSORS_HSCDTD002B
+mpu3050-objs += $(MLLITE_DIR)compass/hscdtd002b.o
+endif
+
+#
+# Pressure options
+#
+ifdef CONFIG_SENSORS_BMA085
+mpu3050-objs += $(MLLITE_DIR)pressure/bma085.o
+endif
+
EXTRA_CFLAGS += -I$(M)/$(MLLITE_DIR) \
-I$(M)/../../include \
- -Idrivers/misc/mpu3050 \
+ -Idrivers/misc/mpu3050 \
-Iinclude/linux
-ifdef CONFIG_SENSORS_MPU3050_DEBUG
+ifdef CONFIG_SENSORS_MPU_DEBUG
EXTRA_CFLAGS += -DDEBUG
endif
+obj-$(CONFIG_SENSORS_MPU6000)= mpu6000.o
+mpu6000-objs += mpuirq.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_SENSORS_AK8975_MPU
+mpu6000-objs += $(MLLITE_DIR)compass/ak8975.o
+endif
+
+ifdef CONFIG_SENSORS_MPU6000
+EXTRA_CFLAGS += -DM_HW
+endif
diff --git a/drivers/misc/mpu3050/README b/drivers/misc/mpu3050/README
deleted file mode 100755
index 8ff0c3009eca..000000000000
--- a/drivers/misc/mpu3050/README
+++ /dev/null
@@ -1,138 +0,0 @@
-Kernel driver mpu3050
-=====================
-
-Supported chips:
- * Invensense IMU3050
- Prefix: 'mpu3050'
- Datasheet:
- PS-MPU-3000A-00.2.4b.pdf
-
-Author: Invensense <http://invensense.com>
-
-Description
------------
-The mpu3050 is a motion processor that controls the mpu3050 gyroscope, a slave
-accelerometer and compass. This document describes how to install the driver
-into a linux kernel and a small note about how to set up the file permissions
-in an android file system.
-
-Sysfs entries
--------------
-/dev/mpu
-/dev/mpuirq
-
-General Remarks
----------------
-
-Valid addresses for the MPU3050 is 0x68.
-Accelerometer must be on the secondary I2C bus.
-
-Programming the chip using /dev/mpu
-----------------------------------
-Programming of the MPU3050 is done by first opening the /dev/mpu file and
-then performing a series of IOCTLS on the handle returned. The IOCTL codes can
-be found in mpu3050.h. Typically this is done by the mllite library in user
-space.
-
-Adding to a Kernel
-==================
-
-The mpu3050 driver is designed to be inserted in the drivers/misc part of the
-kernel. Copy the mpu3050 directory and the mpu3050 include file to:
-
- <kernel root dir>/drivers/misc/mpu3050
- <kernel root dir>/include/linux/mpu3050.h
-
-respectively.
-
-After this is done the drivers/misc/Kconfig must be edited to add the line:
-
- source "drivers/misc/mpu3050/Kconfig"
-
-Similarly drivers/misc/Makefile must be edited to add the line:
-
- obj-y += mpu3050/
-
-Configuration can then be done as normal.
-
-Board and Platform Data
------------------------
-
-In order for the driver to work, board and platform data specific to the device
-needs to be added to the board file. A mpu3050_platform_data structure must
-be created and populatd and set in the i2c_board_info_structure. For details of
-each structure member see mpu3050.h. All values below are modified for the ventana
-platform. You should add these lines into the
-kernel/arch/arm/mach-tegra/board-generic.c file.
-
-#include <linux/mpu3050.h>
-
-static struct mpu3050_platform_data mpu3050_data = {
- .int_config = 0x10,
- .orientation = { 0, -1, 0,
- -1, 0, 0,
- 0, 0, -1 }, //Orientation matrix for MPU on ventana
- .level_shifter = 0,
- .accel = {
- .get_slave_descr = kxtf9_get_slave_descr,
- .adapt_num = 0,
- .bus = EXT_SLAVE_BUS_SECONDARY,
- .address = 0x0F,
- .orientation = { 0, -1, 0,
- -1, 0, 0,
- 0, 0, -1 }, //Orientation matrix for Kionix on ventana
- },
-
-
- .compass = {
- .get_slave_descr = ak8975_get_slave_descr,
- .adapt_num = 3, //bus number 3 on ventana
- .bus = EXT_SLAVE_BUS_PRIMARY,
- .address = 0x0C,
- .orientation = { 1, 0, 0,
- 0, -1, 0,
- 0, 0, -1 }, //Orientation matrix for AKM on ventana
- },
-
-};
-
-static struct i2c_board_info __initdata mpu3050_i2c0_boardinfo[] = {
- {
- I2C_BOARD_INFO("mpu3050", 0x68),
- /*.irq = 299,*/
- .platform_data = &mpu3050_data,
- },
-};
-
-Note: If you are unsure where to add this code, look for other instances of "i2c_board_info"
-and copy paste this code after one of them.
-
-After this is done, we must register the board upon initialization. This is done in the
-i2c_device_setup function in the board-generic.c file. Look for this function and add these
-lines of code:
-
-if (ARRAY_SIZE(mpu3050_i2c0_boardinfo))
- i2c_register_board_info(0, mpu3050_i2c0_boardinfo,
- ARRAY_SIZE(mpu3050_i2c0_boardinfo));
-
-Before you can build the kernel, you will need to remove the existing NVidia AK8975 driver for the compass.
-In the board-generic.c file, rename the instance of CONFIG_SENSORS_AK8975 to NVIDIA_CONFIG_SENSORS_AK8975.
-In kernel/drivers/hwmon/Makefile, rename that instance of CONFIG_SENSORS_AK8975 to NVIDIA_CONFIG_SENSORS_AK8975 as well.
-This will prevent NVidia's driver for the compass from building.
-
-Now you can build the new kernel. First, we must configure the kernel. Take the tegra_ventana_android_defconfig
-file from this package and replace the existing one in the kernel/arch/arm/configs directory. In the root kernel
-directory, you can then run:
-
-export CCOMPILER=/<path to android environment>/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-
-make ARCH=arm CROSS_COMPILE=$CCOMPILER mrproper
-make ARCH=arm CROSS_COMPILE=$CCOMPILER tegra_ventana_android_defconfig
-make ARCH=arm CROSS_COMPILE=$CCOMPILER
-
-This should build your zImage, which you will find in kernel/arch/arm/boot/zImage. You can use the mkbootimg utility to then
-make a boot.img:
-
- ./mkbootimg --kernel <path to android system>/kernel/arch/arm/boot/zImage --ramdisk <path to android system>/out/target/product/ventana/ramdisk.img --output boot.img
-
-You can then flash this boot.img using the nvflash utility.
-
diff --git a/drivers/misc/mpu3050/accel/kxtf9.c b/drivers/misc/mpu3050/accel/kxtf9.c
index ecf9e7dfd3d7..11a9491dd7f1 100755..100644
--- a/drivers/misc/mpu3050/accel/kxtf9.c
+++ b/drivers/misc/mpu3050/accel/kxtf9.c
@@ -16,11 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
- *
- * $Id: kxtf9.c 3867 2010-10-09 01:06:18Z prao $
- *
- *******************************************************************************/
/**
* @defgroup ACCELDL (Motion Library - Accelerometer Driver Layer)
@@ -30,7 +25,7 @@
* @{
* @file kxtf9.c
* @brief Accelerometer setup and handling methods.
-**/
+*/
/* ------------------ */
/* - Include Files. - */
@@ -40,7 +35,7 @@
#include <linux/module.h>
#endif
-#include "mpu3050.h"
+#include "mpu.h"
#include "mlsl.h"
#include "mlos.h"
@@ -56,13 +51,14 @@
Accelerometer Initialization Functions
*****************************************/
-static int kxtf9_suspend(mlsl_handle_t mlsl_handle,
+static int kxtf9_suspend(void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata)
{
int result;
- /* RAM reset */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1d, 0xcd);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, 0);
+ ERROR_CHECK(result);
return result;
}
@@ -70,7 +66,7 @@ static int kxtf9_suspend(mlsl_handle_t mlsl_handle,
#define ACCEL_KIONIX_CTRL_REG (0x1b)
#define ACCEL_KIONIX_CTRL_MASK (0x18)
-static int kxtf9_resume(mlsl_handle_t mlsl_handle,
+static int kxtf9_resume(void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata)
{
@@ -78,38 +74,55 @@ static int kxtf9_resume(mlsl_handle_t mlsl_handle,
unsigned char reg;
/* RAM reset */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1d, 0xcd);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1d, 0xcd);
+ ERROR_CHECK(result);
MLOSSleep(10);
/* Wake up */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, 0x42);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, 0x42);
+ ERROR_CHECK(result);
/* INT_CTRL_REG1: */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1e, 0x14);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1e, 0x14);
+ ERROR_CHECK(result);
/* WUF_THRESH: */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x5a, 0x00);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x5a, 0x00);
+ ERROR_CHECK(result);
/* DATA_CTRL_REG */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x21, 0x04);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x21, 0x04);
+ ERROR_CHECK(result);
/* WUF_TIMER */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x29, 0x02);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x29, 0x02);
+ ERROR_CHECK(result);
/* Full Scale */
reg = 0xc2;
reg &= ~ACCEL_KIONIX_CTRL_MASK;
- reg |= 0x00; /* TODO FIXME michelle */
- if (slave->range.mantissa == 2) {
- reg |= 0x00;
- } else if (slave->range.mantissa == 4) {
+ reg |= 0x00;
+ if (slave->range.mantissa == 4)
reg |= 0x08;
- } else if (slave->range.mantissa == 8) {
+ else if (slave->range.mantissa == 8)
reg |= 0x10;
+ else {
+ slave->range.mantissa = 2;
+ reg |= 0x00;
}
- /* Normal operation */
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, reg);
+ slave->range.fraction = 0;
+
+ /* Normal operation */
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, reg);
+ ERROR_CHECK(result);
MLOSSleep(50);
return ML_SUCCESS;
}
-static int kxtf9_read(mlsl_handle_t mlsl_handle,
+static int kxtf9_read(void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata,
unsigned char *data)
@@ -118,9 +131,12 @@ static int kxtf9_read(mlsl_handle_t mlsl_handle,
}
static struct ext_slave_descr kxtf9_descr = {
+ /*.init = */ NULL,
+ /*.exit = */ NULL,
/*.suspend = */ kxtf9_suspend,
/*.resume = */ kxtf9_resume,
/*.read = */ kxtf9_read,
+ /*.config = */ NULL,
/*.name = */ "kxtf9",
/*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER,
/*.id = */ ACCEL_ID_KXTF9,
@@ -134,10 +150,7 @@ struct ext_slave_descr *kxtf9_get_slave_descr(void)
{
return &kxtf9_descr;
}
-
-#ifdef __KERNEL__
EXPORT_SYMBOL(kxtf9_get_slave_descr);
-#endif
/**
* @}
diff --git a/drivers/misc/mpu3050/compass/ak8975.c b/drivers/misc/mpu3050/compass/ak8975.c
index fb4c033556b3..18606e240f1c 100755..100644
--- a/drivers/misc/mpu3050/compass/ak8975.c
+++ b/drivers/misc/mpu3050/compass/ak8975.c
@@ -16,11 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
- *
- * $Id: ak8975.c 3879 2010-10-12 03:12:37Z mcaramello $
- *
- *******************************************************************************/
/**
* @defgroup COMPASSDL (Motion Library - Accelerometer Driver Layer)
@@ -40,7 +35,7 @@
#include <linux/module.h>
#endif
-#include "mpu3050.h"
+#include "mpu.h"
#include "mlsl.h"
#include "mlos.h"
@@ -48,6 +43,7 @@
#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)
@@ -57,29 +53,34 @@
#define AK8975_CNTL_MODE_POWER_DOWN (0x00)
#define AK8975_CNTL_MODE_SINGLE_MEASUREMENT (0x01)
-int ak8975_suspend(mlsl_handle_t mlsl_handle,
+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);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+ AK8975_REG_CNTL,
+ AK8975_CNTL_MODE_POWER_DOWN);
+ MLOSSleep(1); /* wait at least 100us */
+ ERROR_CHECK(result);
return result;
}
-int ak8975_resume(mlsl_handle_t mlsl_handle,
+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);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+ AK8975_REG_CNTL,
+ AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+ ERROR_CHECK(result);
return result;
}
-int ak8975_read(mlsl_handle_t mlsl_handle,
+int ak8975_read(void *mlsl_handle,
struct ext_slave_descr *slave,
struct ext_slave_platform_data *pdata, unsigned char *data)
{
@@ -87,47 +88,54 @@ int ak8975_read(mlsl_handle_t mlsl_handle,
unsigned char stat2;
int result = ML_SUCCESS;
- result = MLSLSerialRead(mlsl_handle, pdata->address,
- AK8975_REG_ST1, 1, &stat);
+ result =
+ MLSLSerialRead(mlsl_handle, pdata->address, AK8975_REG_ST1, 1,
+ &stat);
ERROR_CHECK(result);
if (stat & 0x01) {
- result = MLSLSerialRead(mlsl_handle, pdata->address,
- AK8975_REG_HXL, 6,
- (unsigned char *)data);
+ result =
+ MLSLSerialRead(mlsl_handle, pdata->address,
+ AK8975_REG_HXL, 6,
+ (unsigned char *) data);
ERROR_CHECK(result);
- result = MLSLSerialRead(mlsl_handle, pdata->address,
- AK8975_REG_ST2, 1, &stat2);
+ result =
+ MLSLSerialRead(mlsl_handle, pdata->address,
+ AK8975_REG_ST2, 1, &stat2);
ERROR_CHECK(result);
- if (stat2 & 0x04) { /*data error */
+ if (stat2 & 0x04) /* data error */
return ML_ERROR_COMPASS_DATA_NOT_READY;
- }
- if (stat2 & 0x08) {
+ if (stat2 & 0x08)
return ML_ERROR_COMPASS_DATA_OVERFLOW;
- }
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
- AK8975_REG_CNTL,
- AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+ AK8975_REG_CNTL,
+ AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+ ERROR_CHECK(result);
return ML_SUCCESS;
} else if (stat & 0x02) {
- result = MLSLSerialRead(mlsl_handle, pdata->address,
- AK8975_REG_ST2, 1, &stat2);
+ result =
+ MLSLSerialRead(mlsl_handle, pdata->address,
+ AK8975_REG_ST2, 1, &stat2);
ERROR_CHECK(result);
return ML_ERROR_COMPASS_DATA_OVERFLOW;
} else {
return ML_ERROR_COMPASS_DATA_NOT_READY;
}
-
}
struct ext_slave_descr ak8975_descr = {
+ /*.init = */ NULL,
+ /*.exit = */ NULL,
/*.suspend = */ ak8975_suspend,
/*.resume = */ ak8975_resume,
/*.read = */ ak8975_read,
+ /*.config = */ NULL,
/*.name = */ "ak8975",
/*.type = */ EXT_SLAVE_TYPE_COMPASS,
/*.id = */ COMPASS_ID_AKM,
- /*.reg = */ 0x06,
- /*.len = */ 6,
+ /*.reg = */ 0x01,
+ /*.len = */ 9,
/*.endian = */ EXT_SLAVE_LITTLE_ENDIAN,
/*.range = */ {9830, 4000}
};
@@ -136,10 +144,7 @@ struct ext_slave_descr *ak8975_get_slave_descr(void)
{
return &ak8975_descr;
}
-
-#ifdef __KERNEL__
EXPORT_SYMBOL(ak8975_get_slave_descr);
-#endif
/**
* @}
diff --git a/drivers/misc/mpu3050/log.h b/drivers/misc/mpu3050/log.h
index 6cb7eae4afcf..ceee28526265 100755..100644
--- a/drivers/misc/mpu3050/log.h
+++ b/drivers/misc/mpu3050/log.h
@@ -15,16 +15,16 @@
*/
/*
-// C/C++ logging functions. See the logging documentation for API details.
-//
-// We'd like these to be available from C code (in case we import some from
-// somewhere), so this has a C interface.
-//
-// The output will be correct when the log file is shared between multiple
-// threads and/or multiple processes so long as the operating system
-// supports O_APPEND. These calls have mutex-protected data structures
-// and so are NOT reentrant. Do not use MPL_LOG in a signal handler.
-*/
+ * C/C++ logging functions. See the logging documentation for API details.
+ *
+ * We'd like these to be available from C code (in case we import some from
+ * somewhere), so this has a C interface.
+ *
+ * The output will be correct when the log file is shared between multiple
+ * threads and/or multiple processes so long as the operating system
+ * supports O_APPEND. These calls have mutex-protected data structures
+ * and so are NOT reentrant. Do not use MPL_LOG in a signal handler.
+ */
#ifndef _LIBS_CUTILS_MPL_LOG_H
#define _LIBS_CUTILS_MPL_LOG_H
@@ -49,7 +49,6 @@ extern "C" {
* You can modify this (for example with "#define MPL_LOG_NDEBUG 0"
* at the top of your source file) to change that behavior.
*/
-#define MPL_LOGV /* comment this out to enable VERBOSE level logging */
#ifndef MPL_LOG_NDEBUG
#ifdef NDEBUG
#define MPL_LOG_NDEBUG 1
@@ -81,6 +80,7 @@ extern "C" {
#define MPL_LOG_SILENT (8)
#endif
+
/*
* This is the local tag used for the following simplified
* logging macros. You can change this preprocessor definition
@@ -99,7 +99,6 @@ extern "C" {
/*
* Simplified macro to send a verbose log message using the current MPL_LOG_TAG.
*/
-#define MPL_LOGV
#ifndef MPL_LOGV
#if MPL_LOG_NDEBUG
#define MPL_LOGV(...) ((void)0)
@@ -117,9 +116,9 @@ extern "C" {
#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)
+ ((CONDITION(cond)) \
+ ? ((void)MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, __VA_ARGS__)) \
+ : (void)0)
#endif
#endif
@@ -132,9 +131,9 @@ extern "C" {
#ifndef MPL_LOGD_IF
#define MPL_LOGD_IF(cond, ...) \
- ((CONDITION(cond)) \
- ? ((void)MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, __VA_ARGS__)) \
- : (void)0)
+ ((CONDITION(cond)) \
+ ? ((void)MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, __VA_ARGS__)) \
+ : (void)0)
#endif
/*
@@ -146,9 +145,9 @@ extern "C" {
#ifndef MPL_LOGI_IF
#define MPL_LOGI_IF(cond, ...) \
- ((CONDITION(cond)) \
- ? ((void)MPL_LOG(LOG_INFO, MPL_LOG_TAG, __VA_ARGS__)) \
- : (void)0)
+ ((CONDITION(cond)) \
+ ? ((void)MPL_LOG(LOG_INFO, MPL_LOG_TAG, __VA_ARGS__)) \
+ : (void)0)
#endif
/*
@@ -160,9 +159,9 @@ extern "C" {
#ifndef MPL_LOGW_IF
#define MPL_LOGW_IF(cond, ...) \
- ((CONDITION(cond)) \
- ? ((void)MPL_LOG(LOG_WARN, MPL_LOG_TAG, __VA_ARGS__)) \
- : (void)0)
+ ((CONDITION(cond)) \
+ ? ((void)MPL_LOG(LOG_WARN, MPL_LOG_TAG, __VA_ARGS__)) \
+ : (void)0)
#endif
/*
@@ -174,9 +173,9 @@ extern "C" {
#ifndef MPL_LOGE_IF
#define MPL_LOGE_IF(cond, ...) \
- ((CONDITION(cond)) \
- ? ((void)MPL_LOG(LOG_ERROR, MPL_LOG_TAG, __VA_ARGS__)) \
- : (void)0)
+ ((CONDITION(cond)) \
+ ? ((void)MPL_LOG(LOG_ERROR, MPL_LOG_TAG, __VA_ARGS__)) \
+ : (void)0)
#endif
/* --------------------------------------------------------------------- */
@@ -188,12 +187,12 @@ extern "C" {
* is -inverted- from the normal assert() semantics.
*/
#define MPL_LOG_ALWAYS_FATAL_IF(cond, ...) \
- ((CONDITION(cond)) \
- ? ((void)android_printAssert(#cond, MPL_LOG_TAG, __VA_ARGS__)) \
- : (void)0)
+ ((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__)))
+ (((void)android_printAssert(NULL, MPL_LOG_TAG, __VA_ARGS__)))
/*
* Versions of MPL_LOG_ALWAYS_FATAL_IF and MPL_LOG_ALWAYS_FATAL that
@@ -216,7 +215,6 @@ extern "C" {
* Stripped out of release builds. Uses the current MPL_LOG_TAG.
*/
#define MPL_LOG_ASSERT(cond, ...) MPL_LOG_FATAL_IF(!(cond), __VA_ARGS__)
-/*#define MPL_LOG_ASSERT(cond) MPL_LOG_FATAL_IF(!(cond), "Assertion failed: " #cond) */
/* --------------------------------------------------------------------- */
@@ -239,13 +237,13 @@ extern "C" {
#ifndef MPL_LOG_PRI
#ifdef ANDROID
#define MPL_LOG_PRI(priority, tag, ...) \
- LOG(priority, tag, __VA_ARGS__)
+ LOG(priority, tag, __VA_ARGS__)
#elif defined __KERNEL__
#define MPL_LOG_PRI(priority, tag, ...) \
- printk(MPL_##priority tag __VA_ARGS__)
+ printk(MPL_##priority tag __VA_ARGS__)
#else
#define MPL_LOG_PRI(priority, tag, ...) \
- _MLPrintLog(MPL_##priority, tag, __VA_ARGS__)
+ _MLPrintLog(MPL_##priority, tag, __VA_ARGS__)
#endif
#endif
@@ -274,7 +272,8 @@ extern "C" {
*/
#ifndef ANDROID
- int _MLPrintLog(int priority, const char *tag, const char *fmt, ...);
+ int _MLPrintLog(int priority, const char *tag, const char *fmt,
+ ...);
int _MLPrintVaLog(int priority, const char *tag, const char *fmt,
va_list args);
/* Final implementation of actual writing to a character device */
diff --git a/drivers/misc/mpu3050/mldl_cfg.c b/drivers/misc/mpu3050/mldl_cfg.c
index d96b0a72a549..668a4cf03ccc 100755..100644
--- a/drivers/misc/mpu3050/mldl_cfg.c
+++ b/drivers/misc/mpu3050/mldl_cfg.c
@@ -16,11 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
- *
- * $Id: mldl_cfg.c 3881 2010-10-12 18:58:45Z prao $
- *
- ******************************************************************************/
/**
* @addtogroup MLDL
@@ -37,7 +32,7 @@
#include <stddef.h>
#include "mldl_cfg.h"
-#include "mpu3050.h"
+#include "mpu.h"
#include "mlsl.h"
#include "mlos.h"
@@ -49,6 +44,41 @@
/* --------------------- */
/* - Variables. - */
/* --------------------- */
+#ifdef M_HW
+#define SLEEP 0
+#define WAKE_UP 7
+#define RESET 1
+#define STANDBY 1
+#else
+/* licteral significance of all parameters used in MLDLPowerMgmtMPU */
+#define SLEEP 1
+#define WAKE_UP 0
+#define RESET 1
+#define STANDBY 1
+#endif
+
+/* --------------------- */
+/* - Prototypes. - */
+/* --------------------- */
+#ifdef M_HW
+static tMLError MLDLPowerMgmtMantis(struct mldl_cfg *pdata,
+ void *mlsl_handle,
+ unsigned char reset,
+ unsigned char powerselection);
+static tMLError MLDLStandByGyros(struct mldl_cfg *pdata,
+ void *mlsl_handle,
+ unsigned char disable_gx,
+ unsigned char disable_gy,
+ unsigned char disable_gz);
+#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);
+#endif
/* ---------------------- */
/* - Static Functions. - */
@@ -65,25 +95,24 @@
*
* @return Zero if the command is successful, an error code otherwise.
*/
-static int MLDLCtrlDmp(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle,
+static int MLDLCtrlDmp(struct mldl_cfg *pdata, void *mlsl_handle,
bool enableRun, bool enableFIFO)
{
unsigned char b;
MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_USER_CTRL, 1, &b);
- if (enableRun) {
+ if (enableRun)
b |= BIT_DMP_EN;
- } else {
+ else
b &= ~BIT_DMP_EN;
- }
- if (enableFIFO) {
+ if (enableFIFO)
b |= BIT_FIFO_EN;
- }
b |= BIT_DMP_RST;
- MLSLSerialWriteSingle(mlsl_handle, pdata->addr, MPUREG_USER_CTRL, b);
+ MLSLSerialWriteSingle(mlsl_handle, pdata->addr, MPUREG_USER_CTRL,
+ b);
return ML_SUCCESS;
}
@@ -93,7 +122,7 @@ static int MLDLCtrlDmp(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle,
*
* @return ML_SUCCESS or non-zero error code
*/
-static int MLDLDmpStart(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle)
+static int MLDLDmpStart(struct mldl_cfg *pdata, void *mlsl_handle)
{
unsigned char fifoBuf[2];
unsigned char tries = 0;
@@ -108,11 +137,11 @@ static int MLDLDmpStart(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle)
result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
MPUREG_USER_CTRL,
((userCtrlReg & (~BIT_FIFO_EN))
- | BIT_FIFO_RST));
+ | BIT_FIFO_RST));
MLSLSerialRead(mlsl_handle, pdata->addr,
MPUREG_FIFO_COUNTH, 2, fifoBuf);
- len = (((unsigned short)fifoBuf[0] << 8)
- | (unsigned short)fifoBuf[1]);
+ len = (((unsigned short) fifoBuf[0] << 8)
+ | (unsigned short) fifoBuf[1]);
tries++;
}
@@ -124,22 +153,27 @@ static int MLDLDmpStart(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle)
}
/**
- * @brief enables/disables the I2C pass through to the accelerometer device.
- * @param enable Non-zero to enable pass through.
- * @return ML_SUCCESS if the command is successful, an error code otherwise.
+ * @brief enables/disables the I2C bypass to an external device
+ * connected to MPU's secondary I2C bus.
+ * @param enable
+ * Non-zero to enable pass through.
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
*/
static int MLDLSetI2CBypass(struct mldl_cfg *mldl_cfg,
- mlsl_handle_t mlsl_handle, unsigned char enable)
+ void *mlsl_handle,
+ unsigned char enable)
{
unsigned char b;
int result;
#ifdef ML_USE_DMP_SIM
- if (!MLGetGyroPresent()) /* done this way so that pc demo */
- return ML_SUCCESS; /* w/arm board works with universal api */
+ /* done this way so that pc demo */
+ /* w/arm board works with universal api */
+ if (!MLGetGyroPresent())
+ return ML_SUCCESS;
#endif
- /*---- get current 'USER_CTRL' into b ----*/
+ /*---- get current 'USER_CTRL' into b ----*/
result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
MPUREG_USER_CTRL, 1, &b);
ERROR_CHECK(result);
@@ -156,39 +190,51 @@ static int MLDLSetI2CBypass(struct mldl_cfg *mldl_cfg,
(b | BIT_AUX_IF_EN));
ERROR_CHECK(result);
} else {
- /* Coming out of I2C is tricky due to severla erratta. Do not modify
- * this algorithm */
+ /* Coming out of I2C is tricky due to several erratta. Do not
+ * modify this algorithm
+ */
/*
- * 1) wait for the right time and send the command to change the ime
- * i2c slave address to an invalid address that will get naked
+ * 1) wait for the right time and send the command to change
+ * the aux i2c slave address to an invalid address that will
+ * get nack'ed
*
- * 0x00 is broadcast. 0x7F is ulikely to be used by any accels.
+ * 0x00 is broadcast. 0x7F is unlikely to be used by any aux.
*/
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
MPUREG_AUX_SLV_ADDR, 0x7F);
ERROR_CHECK(result);
/*
- * 2) wait enough time for a nack to occur, then go into bypass mode:
+ * 2) wait enough time for a nack to occur, then go into
+ * bypass mode:
*/
MLOSSleep(2);
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
MPUREG_USER_CTRL, (b));
ERROR_CHECK(result);
/*
- * 3) wait for up to one MPU cycle then restore the slave address
+ * 3) wait for up to one MPU cycle then restore the slave
+ * address
*/
MLOSSleep(5);
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
MPUREG_AUX_SLV_ADDR,
- mldl_cfg->pdata->accel.address);
+ mldl_cfg->pdata->
+ accel.address);
ERROR_CHECK(result);
/*
* 4) reset the ime interface
*/
+#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);
}
@@ -197,14 +243,27 @@ static int MLDLSetI2CBypass(struct mldl_cfg *mldl_cfg,
}
struct tsProdRevMap {
- /*unsigned char prodRev; */
unsigned char siliconRev;
unsigned short sensTrim;
};
#define NUM_OF_PROD_REVS (DIM(prodRevsMap))
+/* NOTE : 'npp' is a non production part */
+#ifdef M_HW
+#define OLDEST_PROD_REV_SUPPORTED 1
+static struct tsProdRevMap prodRevsMap[] = {
+ {0, 0},
+ {MPU_SILICON_REV_A1, 131}, /* 1 A1 */
+ {MPU_SILICON_REV_A1, 131}, /* 2 A1 */
+ {MPU_SILICON_REV_A1, 131}, /* 3 A1 */
+ {MPU_SILICON_REV_A1, 131}, /* 4 A1 */
+ {MPU_SILICON_REV_A1, 131}, /* 5 A1 */
+};
+
+#else /* !M_HW */
#define OLDEST_PROD_REV_SUPPORTED 11
+
static struct tsProdRevMap prodRevsMap[] = {
{0, 0},
{MPU_SILICON_REV_A4, 131}, /* 1 A? OBSOLETED */
@@ -221,14 +280,20 @@ static struct tsProdRevMap prodRevsMap[] = {
{MPU_SILICON_REV_B1, 131}, /* 12 | */
{MPU_SILICON_REV_B1, 131}, /* 13 V */
{MPU_SILICON_REV_B1, 131}, /* 14 B4 */
- {MPU_SILICON_REV_B4, 131}, /* 15 | {MPU_SILICON_REV_B4, 131}, // 16 V */
+ {MPU_SILICON_REV_B4, 131}, /* 15 | */
+ {MPU_SILICON_REV_B4, 131}, /* 16 V */
{MPU_SILICON_REV_B4, 131}, /* 17 */
{MPU_SILICON_REV_B4, 131}, /* 18 */
- {MPU_SILICON_REV_B4, 115}, /* 19 */
+ {MPU_SILICON_REV_B4, 115}, /* 19 */
{MPU_SILICON_REV_B4, 115}, /* 20 */
- {MPU_SILICON_REV_B6, 131}, /* 21 B6 */
- {MPU_SILICON_REV_B4, 115}, /* 22 B4 */
+ {MPU_SILICON_REV_B6, 131}, /* 21 B6 (B6/A9) */
+ {MPU_SILICON_REV_B4, 115}, /* 22 B4 (B7/A10) */
+ {MPU_SILICON_REV_B6, 0}, /* 23 B6 (npp) */
+ {MPU_SILICON_REV_B6, 0}, /* 24 | (npp) */
+ {MPU_SILICON_REV_B6, 0}, /* 25 V (npp) */
+ {MPU_SILICON_REV_B6, 131}, /* 26 (B6/A11) */
};
+#endif /* !M_HW */
/**
* @internal
@@ -238,7 +303,8 @@ static struct tsProdRevMap prodRevsMap[] = {
* in a map.
* @return The silicon revision ID (0 on error).
*/
-static int MLDLGetSiliconRev(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle)
+static int MLDLGetSiliconRev(struct mldl_cfg *pdata,
+ void *mlsl_handle)
{
int result;
unsigned char index = 0x00;
@@ -248,17 +314,35 @@ static int MLDLGetSiliconRev(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle)
result = MLSLSerialReadMem(mlsl_handle, pdata->addr,
memAddr, 1, &index);
+ ERROR_CHECK(result)
if (result)
return result;
index >>= 2;
- if (index < OLDEST_PROD_REV_SUPPORTED || NUM_OF_PROD_REVS < index) {
+ /* clean the prefetch and cfg user bank bits */
+ 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;
- } else {
- pdata->silicon_revision = prodRevsMap[index].siliconRev;
- pdata->trim = prodRevsMap[index].sensTrim;
}
+
+ 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;
}
@@ -278,28 +362,28 @@ static int MLDLGetSiliconRev(struct mldl_cfg *pdata, mlsl_handle_t mlsl_handle)
* @return ML_SUCCESS if successfull, a non-zero error code otherwise.
**/
static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
- mlsl_handle_t mlsl_handle,
+ void *mlsl_handle,
unsigned char enable)
{
+#ifndef M_HW
int result;
unsigned char reg;
unsigned char mask;
unsigned char regval;
- if (0 == pdata->silicon_revision) {
+ if (0 == pdata->silicon_revision)
return ML_ERROR_INVALID_PARAMETER;
- }
- /*-- on parts before B6 the VDDIO bit is bit 7 of ACCEL_BURST_ADDR --
- NOTE: this is incompatible with ST accelerometers where the VDDIO
- bit MUST be set to enable ST's internal logic to autoincrement
- the register address on burst reads --*/
+ /*-- on parts before B6 the VDDIO bit is bit 7 of ACCEL_BURST_ADDR --
+ NOTE: this is incompatible with ST accelerometers where the VDDIO
+ bit MUST be set to enable ST's internal logic to autoincrement
+ the register address on burst reads --*/
if ((pdata->silicon_revision & 0xf) < MPU_SILICON_REV_B6) {
reg = MPUREG_ACCEL_BURST_ADDR;
mask = 0x80;
} else {
- /*-- on B6 parts the VDDIO bit was moved to FIFO_EN2 =>
- the mask is always 0x04 --*/
+ /*-- on B6 parts the VDDIO bit was moved to FIFO_EN2 =>
+ the mask is always 0x04 --*/
reg = MPUREG_FIFO_EN2;
mask = 0x04;
}
@@ -313,11 +397,122 @@ static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
else
regval &= ~mask;
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr, reg, regval);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->addr, reg, regval);
return result;
+#else
+ return ML_SUCCESS;
+#endif
}
+
+#ifdef M_HW
+/**
+ * @internal
+ * @param reset 1 to reset hardware
+**/
+static tMLError MLDLPowerMgmtMantis(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) {
+ /* Current sillicon has an errata where the reset will get
+ * nacked. Ignore the error code for now. */
+ result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+ MPUREG_PWR_MGM, b | 0x80);
+#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->is_suspended = FALSE;
+ else
+ pdata->is_suspended = TRUE;
+
+ result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+ MPUREG_PWR_MGM, b);
+ ERROR_CHECK(result);
+
+ return ML_SUCCESS;
+}
+
+/**
+ * @internal
+ */
+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;
+}
+
+/**
+ * @internal
+ */
+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 /* ! M_HW */
+
/**
* @internal
* @brief This function controls the power management on the MPU device.
@@ -343,7 +538,7 @@ static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
* @param reset
* Non-zero to reset the device. Note that this setting
* is volatile and the corresponding register bit will
- * clear itself right after.
+ * clear itself right after being applied.
* @param sleep
* Non-zero to put device into full sleep.
* @param disable_gx
@@ -356,23 +551,24 @@ static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
* @return ML_SUCCESS if successfull; a non-zero error code otherwise.
*/
static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
- mlsl_handle_t mlsl_handle,
+ void *mlsl_handle,
unsigned char reset,
unsigned char sleep,
unsigned char disable_gx,
- unsigned char disable_gy, unsigned char disable_gz)
+ unsigned char disable_gy,
+ unsigned char disable_gz)
{
unsigned char b;
int result;
result =
- MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGM, 1, &b);
+ MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGM, 1,
+ &b);
ERROR_CHECK(result);
/* If we are awake, we need to put it in bypass before resetting */
- if ((!(b & BIT_SLEEP)) && reset) {
+ if ((!(b & BIT_SLEEP)) && reset)
result = MLDLSetI2CBypass(pdata, mlsl_handle, 1);
- }
/* Reset if requested */
if (reset) {
@@ -382,35 +578,37 @@ static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
MLOSSleep(5);
}
- /* Some chips are awake after reset and some are asleep, check the status */
+ /* Some chips are awake after reset and some are asleep, check the
+ * status */
result =
- MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGM, 1, &b);
+ MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGM, 1,
+ &b);
ERROR_CHECK(result);
/* Update the suspended state just in case we return early */
- if (b & BIT_SLEEP) {
+ if (b & BIT_SLEEP)
pdata->is_suspended = TRUE;
- } else {
+ else
pdata->is_suspended = FALSE;
- }
if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG))
- == ((sleep * BIT_SLEEP) |
- (disable_gz * BIT_STBY_XG) |
- (disable_gy * BIT_STBY_YG) | (disable_gz * 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;
}
/*
- * This specific transition between states needs to be reinterpreted:
- * (1,1,1,1) -> (0,1,1,1) has to become
- * (1,1,1,1) -> (1,0,0,0) -> (0,1,1,1)
- * where
- * (1,1,1,1) stands for (sleep=1,disable_gx=1,disable_gy=1,disable_gz=1)
+ * This specific transition between states needs to be reinterpreted:
+ * (1,1,1,1) -> (0,1,1,1) has to become
+ * (1,1,1,1) -> (1,0,0,0) -> (0,1,1,1)
+ * where
+ * (1,1,1,1) is (sleep=1,disable_gx=1,disable_gy=1,disable_gz=1)
*/
- if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) == (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG) /* (1,1,1,1) */
- && ((!sleep) && disable_gx && disable_gy && disable_gz)) { /* (0,1,1,1) */
-
+ 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;
@@ -418,20 +616,23 @@ static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
}
- if ((b & BIT_SLEEP) != (sleep * BIT_SLEEP)) {
+
+ 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);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+ MPUREG_PWR_MGM, b);
ERROR_CHECK(result);
pdata->is_suspended = TRUE;
} else {
b &= ~BIT_SLEEP;
- result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
- MPUREG_PWR_MGM, b);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
+ MPUREG_PWR_MGM, b);
ERROR_CHECK(result);
pdata->is_suspended = FALSE;
MLOSSleep(5);
@@ -441,19 +642,19 @@ static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
WORKAROUND FOR PUTTING GYRO AXIS in STAND-BY MODE
1) put one axis at a time in stand-by
---*/
- if ((b & BIT_STBY_XG) != (disable_gx * BIT_STBY_XG)) {
+ 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 * BIT_STBY_YG)) {
+ 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 * BIT_STBY_ZG)) {
+ 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);
@@ -462,39 +663,52 @@ static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
return ML_SUCCESS;
}
+#endif /* M_HW */
-void mpu3050_print_cfg(struct mldl_cfg *mldl_cfg)
+
+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 *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.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.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_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.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.product_id = %02x\n",
+ mldl_cfg->product_id);
MPL_LOGD("mldl_cfg.trim = %02x\n", mldl_cfg->trim);
if (mldl_cfg->accel) {
MPL_LOGD("slave_accel->suspend = %02x\n",
- (int)mldl_cfg->accel->suspend);
+ (int) mldl_cfg->accel->suspend);
MPL_LOGD("slave_accel->resume = %02x\n",
- (int)mldl_cfg->accel->resume);
+ (int) mldl_cfg->accel->resume);
MPL_LOGD("slave_accel->read = %02x\n",
- (int)mldl_cfg->accel->read);
+ (int) mldl_cfg->accel->read);
MPL_LOGD("slave_accel->type = %02x\n",
mldl_cfg->accel->type);
MPL_LOGD("slave_accel->reg = %02x\n",
@@ -513,11 +727,11 @@ void mpu3050_print_cfg(struct mldl_cfg *mldl_cfg)
if (mldl_cfg->compass) {
MPL_LOGD("slave_compass->suspend = %02x\n",
- (int)mldl_cfg->compass->suspend);
+ (int) mldl_cfg->compass->suspend);
MPL_LOGD("slave_compass->resume = %02x\n",
- (int)mldl_cfg->compass->resume);
+ (int) mldl_cfg->compass->resume);
MPL_LOGD("slave_compass->read = %02x\n",
- (int)mldl_cfg->compass->read);
+ (int) mldl_cfg->compass->read);
MPL_LOGD("slave_compass->type = %02x\n",
mldl_cfg->compass->type);
MPL_LOGD("slave_compass->reg = %02x\n",
@@ -534,12 +748,37 @@ void mpu3050_print_cfg(struct mldl_cfg *mldl_cfg)
} 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);
+ (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"
+ MPL_LOGD("accel->orientation =\n"
" %2d %2d %2d\n"
" %2d %2d %2d\n"
" %2d %2d %2d\n",
@@ -549,11 +788,12 @@ void mpu3050_print_cfg(struct mldl_cfg *mldl_cfg)
accel->orientation[6], accel->orientation[7],
accel->orientation[8]);
MPL_LOGD("compass->get_slave_descr = %x\n",
- (unsigned int)compass->get_slave_descr);
+ (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"
+ MPL_LOGD("compass->orientation =\n"
" %2d %2d %2d\n"
" %2d %2d %2d\n"
" %2d %2d %2d\n",
@@ -562,10 +802,26 @@ void mpu3050_print_cfg(struct mldl_cfg *mldl_cfg)
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"
+ 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",
@@ -576,7 +832,8 @@ void mpu3050_print_cfg(struct mldl_cfg *mldl_cfg)
pdata->orientation[8]);
MPL_LOGD("Struct sizes: mldl_cfg: %d, "
- "ext_slave_descr:%d, mpu3050_platform_data:%d: RamOffset: %d\n",
+ "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));
@@ -601,7 +858,11 @@ void mpu3050_print_cfg(struct mldl_cfg *mldl_cfg)
* @return ML_SUCCESS if silicon revision, product id and woami are supported
* by this software.
*/
-int mpu3050_open(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle)
+int mpu3050_open(struct mldl_cfg *mldl_cfg,
+ void *mlsl_handle,
+ void *accel_handle,
+ void *compass_handle,
+ void *pressure_handle)
{
int result;
/* Default is Logic HIGH, pushpull, latch disabled, anyread to clear */
@@ -615,6 +876,7 @@ int mpu3050_open(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle)
mldl_cfg->ext_sync = 0;
mldl_cfg->dmp_cfg1 = 0;
mldl_cfg->dmp_cfg2 = 0;
+ mldl_cfg->gyro_power = 0;
if (mldl_cfg->addr == 0) {
#ifdef __KERNEL__
return ML_ERROR_INVALID_PARAMETER;
@@ -628,93 +890,291 @@ int mpu3050_open(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle)
* Take the DMP out of sleep, and
* read the product_id, sillicon rev and whoami
*/
- result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 1, 0, 0, 0, 0);
+#ifdef M_HW
+ result =
+ MLDLPowerMgmtMantis(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);
result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
- MPUREG_PRODUCT_ID, 1, &mldl_cfg->product_id);
+ MPUREG_PRODUCT_ID, 1,
+ &mldl_cfg->product_id);
ERROR_CHECK(result);
/* Get the factory temperature compensation offsets */
result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
- MPUREG_XG_OFFS_TC, 1, &mldl_cfg->offset_tc[0]);
+ 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]);
+ 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]);
+ MPUREG_ZG_OFFS_TC, 1,
+ &mldl_cfg->offset_tc[2]);
ERROR_CHECK(result);
/* Configure the MPU */
- result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 0, 1, 0, 0, 0);
+#ifdef M_HW
+ result = MLDLPowerMgmtMantis(mldl_cfg, mlsl_handle, 0, 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;
+ }
+ }
+
+ 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;
+
+}
+
+/**
+ * Close the mpu3050 interface
+ *
+ * @param mldl_cfg pointer to the configuration structure
+ * @param mlsl_handle pointer to the serial layer handle
+ *
+ * @return ML_SUCCESS or non-zero error code
+ */
+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, mlsl_handle_t mlsl_handle,
- mlsl_handle_t accel_handle,
- mlsl_handle_t compass_handle,
- bool resume_accel, bool resume_compass)
+/**
+ * @brief resume the MPU3050 device and all the other sensor
+ * devices from their low power state.
+ * @param mlsl_handle
+ * the main file handle to the MPU3050 device.
+ * @param accel_handle
+ * an handle to the accelerometer device, if sitting
+ * onto a separate bus. Can match mlsl_handle if
+ * the accelerometer device operates on the same
+ * primary bus of MPU.
+ * @param compass_handle
+ * an handle to the compass device, if sitting
+ * onto a separate bus. Can match mlsl_handle if
+ * the compass device operates on the same
+ * primary bus of MPU.
+ * @param pressure_handle
+ * an handle to the pressure sensor device, if sitting
+ * onto a separate bus. Can match mlsl_handle if
+ * the pressure sensor device operates on the same
+ * primary bus of MPU.
+ * @param resume_accel
+ * whether resuming the accelerometer device is
+ * actually needed (if the device supports low power
+ * mode of some sort).
+ * @param resume_compass
+ * whether resuming the compass device is
+ * actually needed (if the device supports low power
+ * mode of some sort).
+ * @param resume_pressure
+ * whether resuming the pressure sensor device is
+ * actually needed (if the device supports low power
+ * mode of some sort).
+ * @return ML_SUCCESS or a non-zero error code.
+ */
+int mpu3050_resume(struct mldl_cfg *mldl_cfg,
+ void *mlsl_handle,
+ void *accel_handle,
+ void *compass_handle,
+ void *pressure_handle,
+ bool resume_accel, bool resume_compass, bool resume_pressure)
{
int result;
int ii;
int jj;
unsigned char reg;
+ unsigned char regs[7];
+
+
+#ifdef CONFIG_SENSORS_MPU_DEBUG
+ mpu_print_cfg(mldl_cfg);
+#endif
- /* mpu3050_print_cfg(mldl_cfg); */
/* Wake up the part */
- result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 1, 0, 0, 0, 0);
+#ifdef M_HW
+ result = MLDLPowerMgmtMantis(mldl_cfg, mlsl_handle, 0, WAKE_UP);
+#else
+ result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 1, 0,
+ mldl_cfg->gyro_power & BIT_STBY_XG,
+ mldl_cfg->gyro_power & BIT_STBY_YG,
+ mldl_cfg->gyro_power & BIT_STBY_ZG);
+#endif
ERROR_CHECK(result);
/* Configure the MPU */
+#ifdef M_HW
+ result = MLDLSetI2CBypass(mldl_cfg, mlsl_handle, 1);
+ ERROR_CHECK(result);
+ result = MLDLPowerMgmtMantis(mldl_cfg, mlsl_handle, RESET, SLEEP);
+ ERROR_CHECK(result);
+ result = MLDLPowerMgmtMantis(mldl_cfg, mlsl_handle, 0, WAKE_UP);
+ ERROR_CHECK(result);
+ /* setting int_config with the propert flag BIT_BYPASS_EN should be
+ done by the setup functions */
+ result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+ MPUREG_INT_PIN_CFG,
+ (mldl_cfg->pdata->int_config |
+ BIT_BYPASS_EN));
+ ERROR_CHECK(result);
+ /* temporary: masking out higher bits to avoid switching intelligence */
+ result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
+ MPUREG_INT_ENABLE,
+ (mldl_cfg->int_config & 0x0f));
+ ERROR_CHECK(result);
+#else
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
MPUREG_INT_CFG,
- (mldl_cfg->int_config | mldl_cfg->
- pdata->int_config));
+ (mldl_cfg->
+ int_config | mldl_cfg->pdata->
+ int_config));
ERROR_CHECK(result);
+#endif
result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
MPUREG_PWR_MGM, 1, &reg);
ERROR_CHECK(result);
reg &= ~BITS_CLKSEL;
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
- MPUREG_PWR_MGM, mldl_cfg->clk_src | reg);
+ MPUREG_PWR_MGM,
+ mldl_cfg->clk_src | reg);
ERROR_CHECK(result);
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
- MPUREG_SMPLRT_DIV, mldl_cfg->divider);
+ 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(mlsl_handle, mldl_cfg->addr,
+ MPUREG_GYRO_CONFIG, reg);
+ reg = DLPF_FS_SYNC_VALUE(0, 0, mldl_cfg->lpf);
+ result = MLSLSerialWriteSingle(mlsl_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(mlsl_handle, mldl_cfg->addr,
MPUREG_DLPF_FS_SYNC, reg);
+#endif
ERROR_CHECK(result);
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
- MPUREG_DMP_CFG_1, mldl_cfg->dmp_cfg1);
+ MPUREG_DMP_CFG_1,
+ mldl_cfg->dmp_cfg1);
ERROR_CHECK(result);
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
- MPUREG_DMP_CFG_2, mldl_cfg->dmp_cfg2);
+ MPUREG_DMP_CFG_2,
+ mldl_cfg->dmp_cfg2);
ERROR_CHECK(result);
/* Write and verify memory */
for (ii = 0; ii < MPU_MEM_NUM_RAM_BANKS; ii++) {
- unsigned char read[128];
+ unsigned char read[MPU_MEM_BANK_SIZE];
+
result = MLSLSerialWriteMem(mlsl_handle, mldl_cfg->addr,
- ((ii << 8)),
- MPU_MEM_BANK_SIZE / 2,
+ ((ii << 8) | 0x00),
+ MPU_MEM_BANK_SIZE,
mldl_cfg->ram[ii]);
ERROR_CHECK(result);
result = MLSLSerialReadMem(mlsl_handle, mldl_cfg->addr,
- ((ii << 8) | 0),
- MPU_MEM_BANK_SIZE / 2, read);
+ ((ii << 8) | 0x00),
+ MPU_MEM_BANK_SIZE, read);
ERROR_CHECK(result);
- for (jj = 0; jj < MPU_MEM_BANK_SIZE / 2; jj++) {
+#ifdef M_HW
+#define ML_SKIP_CHECK 38
+#else
+#define ML_SKIP_CHECK 20
+#endif
+ for (jj = 0; jj < MPU_MEM_BANK_SIZE; jj++) {
/* skip the register memory locations */
- if (ii == 0 && jj < 20)
+ if (ii == 0 && jj < ML_SKIP_CHECK)
continue;
if (mldl_cfg->ram[ii][jj] != read[jj]) {
result = ML_ERROR_SERIAL_WRITE;
@@ -722,25 +1182,6 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
}
}
ERROR_CHECK(result);
-
- result = MLSLSerialWriteMem(mlsl_handle, mldl_cfg->addr,
- ((ii << 8) | MPU_MEM_BANK_SIZE / 2),
- MPU_MEM_BANK_SIZE / 2,
- &mldl_cfg->ram[ii][MPU_MEM_BANK_SIZE
- / 2]);
- ERROR_CHECK(result);
- result = MLSLSerialReadMem(mlsl_handle, mldl_cfg->addr,
- ((ii << 8) | MPU_MEM_BANK_SIZE / 2),
- MPU_MEM_BANK_SIZE / 2, read);
- ERROR_CHECK(result);
- for (jj = 0; jj < MPU_MEM_BANK_SIZE / 2; jj++) {
- if (mldl_cfg->ram[ii][MPU_MEM_BANK_SIZE / 2 + jj] !=
- read[jj]) {
- result = ML_ERROR_SERIAL_WRITE;
- break;
- }
- }
- ERROR_CHECK(result);
}
result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
@@ -756,15 +1197,25 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
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(mlsl_handle, mldl_cfg->addr, 7, regs);
+ ERROR_CHECK(result);
+
/* Configure slaves */
result = MLDLSetLevelShifterBit(mldl_cfg, mlsl_handle,
mldl_cfg->pdata->level_shifter);
ERROR_CHECK(result);
if (resume_accel) {
- if ((!mldl_cfg->accel) || (!mldl_cfg->accel->resume)) {
+ if ((!mldl_cfg->accel) || (!mldl_cfg->accel->resume))
return ML_ERROR_INVALID_PARAMETER;
- }
+
result = mldl_cfg->accel->resume(accel_handle,
mldl_cfg->accel,
&mldl_cfg->pdata->accel);
@@ -772,15 +1223,17 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
if (EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
/* Address */
result =
- MLSLSerialWriteSingle(accel_handle, mldl_cfg->addr,
+ MLSLSerialWriteSingle(accel_handle,
+ mldl_cfg->addr,
MPUREG_AUX_SLV_ADDR,
mldl_cfg->pdata->
accel.address);
ERROR_CHECK(result);
/* Register */
- result = MLSLSerialRead(accel_handle, mldl_cfg->addr,
- MPUREG_ACCEL_BURST_ADDR, 1,
- &reg);
+ result =
+ MLSLSerialRead(accel_handle, mldl_cfg->addr,
+ MPUREG_ACCEL_BURST_ADDR, 1,
+ &reg);
ERROR_CHECK(result);
reg = ((reg & 0x80) | mldl_cfg->accel->reg);
/* Set VDDIO bit for ST accel */
@@ -789,19 +1242,24 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
reg |= 0x80;
}
result =
- MLSLSerialWriteSingle(accel_handle, mldl_cfg->addr,
- MPUREG_ACCEL_BURST_ADDR, reg);
+ MLSLSerialWriteSingle(accel_handle,
+ mldl_cfg->addr,
+ MPUREG_ACCEL_BURST_ADDR,
+ reg);
ERROR_CHECK(result);
/* Length */
- result = MLSLSerialRead(accel_handle, mldl_cfg->addr,
- MPUREG_USER_CTRL, 1, &reg);
+ result =
+ MLSLSerialRead(accel_handle, mldl_cfg->addr,
+ MPUREG_USER_CTRL, 1, &reg);
ERROR_CHECK(result);
reg = (reg & ~BIT_AUX_RD_LENG);
result =
- MLSLSerialWriteSingle(accel_handle, mldl_cfg->addr,
+ MLSLSerialWriteSingle(accel_handle,
+ mldl_cfg->addr,
MPUREG_USER_CTRL, reg);
ERROR_CHECK(result);
- result = MLDLSetI2CBypass(mldl_cfg, accel_handle, 0);
+ result =
+ MLDLSetI2CBypass(mldl_cfg, accel_handle, 0);
ERROR_CHECK(result);
}
}
@@ -810,10 +1268,83 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
if ((mldl_cfg->compass) && (mldl_cfg->compass->resume)) {
result = mldl_cfg->compass->resume(compass_handle,
mldl_cfg->compass,
- &mldl_cfg->
- pdata->compass);
+ &mldl_cfg->pdata->
+ compass);
ERROR_CHECK(result);
}
+ ERROR_CHECK(result);
+ if (EXT_SLAVE_BUS_SECONDARY ==
+ mldl_cfg->pdata->compass.bus) {
+ /* Address */
+ result =
+ MLSLSerialWriteSingle(mlsl_handle,
+ mldl_cfg->addr,
+ MPUREG_AUX_SLV_ADDR,
+ mldl_cfg->pdata->
+ compass.address);
+ ERROR_CHECK(result);
+ /* Register */
+ result =
+ MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
+ MPUREG_ACCEL_BURST_ADDR, 1,
+ &reg);
+ ERROR_CHECK(result);
+ reg = ((reg & 0x80) | mldl_cfg->compass->reg);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle,
+ mldl_cfg->addr,
+ MPUREG_ACCEL_BURST_ADDR,
+ reg);
+ ERROR_CHECK(result);
+
+#ifdef M_HW
+ /* Length, byte swapping, grouping & enable */
+ if (mldl_cfg->compass->len > BITS_SLV_LENG) {
+ MPL_LOGW("Limiting slave burst read length to "
+ "the allowed maximum (15B, req. %d)\n",
+ mldl_cfg->compass->len);
+ mldl_cfg->compass->len = BITS_SLV_LENG;
+ }
+ reg = mldl_cfg->compass->len;
+ if (mldl_cfg->compass->endian ==
+ EXT_SLAVE_LITTLE_ENDIAN)
+ reg |= BIT_SLV_BYTE_SW;
+ reg |= BIT_SLV_GRP;
+ reg |= BIT_SLV_ENABLE;
+
+ result =
+ MLSLSerialWriteSingle(mlsl_handle,
+ mldl_cfg->addr,
+ MPUREG_I2C_SLV0_CTRL,
+ reg);
+#else
+ /* Length */
+ result =
+ MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
+ MPUREG_USER_CTRL, 1, &reg);
+ ERROR_CHECK(result);
+ reg = (reg & ~BIT_AUX_RD_LENG);
+ result =
+ MLSLSerialWriteSingle(mlsl_handle,
+ mldl_cfg->addr,
+ MPUREG_USER_CTRL, reg);
+ ERROR_CHECK(result);
+#endif
+ result =
+ MLDLSetI2CBypass(mldl_cfg, mlsl_handle, 0);
+ ERROR_CHECK(result);
+ }
+ }
+
+ if (resume_pressure) {
+ if ((mldl_cfg->pressure) && (mldl_cfg->pressure->resume)) {
+ result = mldl_cfg->pressure->resume(pressure_handle,
+ mldl_cfg->pressure,
+ &mldl_cfg->pdata->
+ pressure);
+ ERROR_CHECK(result);
+ }
+ ERROR_CHECK(result);
}
/* Now start */
@@ -822,13 +1353,58 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
return result;
}
-int mpu3050_suspend(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
- mlsl_handle_t accel_handle,
- mlsl_handle_t compass_handle, bool accel, bool compass)
+
+/**
+ * @brief suspend the MPU3050 device and all the other sensor
+ * devices into their low power state.
+ * @param mlsl_handle
+ * the main file handle to the MPU3050 device.
+ * @param accel_handle
+ * an handle to the accelerometer device, if sitting
+ * onto a separate bus. Can match mlsl_handle if
+ * the accelerometer device operates on the same
+ * primary bus of MPU.
+ * @param compass_handle
+ * an handle to the compass device, if sitting
+ * onto a separate bus. Can match mlsl_handle if
+ * the compass device operates on the same
+ * primary bus of MPU.
+ * @param pressure_handle
+ * an handle to the pressure sensor device, if sitting
+ * onto a separate bus. Can match mlsl_handle if
+ * the pressure sensor device operates on the same
+ * primary bus of MPU.
+ * @param accel
+ * whether suspending the accelerometer device is
+ * actually needed (if the device supports low power
+ * mode of some sort).
+ * @param compass
+ * whether suspending the compass device is
+ * actually needed (if the device supports low power
+ * mode of some sort).
+ * @param pressure
+ * whether suspending the pressure sensor device is
+ * actually needed (if the device supports low power
+ * mode of some sort).
+ * @return ML_SUCCESS or a non-zero error code.
+ */
+int mpu3050_suspend(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+ void *accel_handle,
+ void *compass_handle,
+ void *pressure_handle,
+ bool accel, bool compass, bool pressure)
{
int result;
/* This puts the bus into bypass mode */
- result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 0, 1, 0, 0, 0);
+
+#ifdef M_HW
+ result = MLDLSetI2CBypass(mldl_cfg, mlsl_handle, 1);
+ ERROR_CHECK(result);
+ result = MLDLPowerMgmtMantis(mldl_cfg, mlsl_handle, 0, SLEEP);
+#else
+ result =
+ MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 0, SLEEP, 0, 0, 0);
+#endif
if (ML_SUCCESS == result &&
accel && mldl_cfg->accel && mldl_cfg->accel->suspend) {
result = mldl_cfg->accel->suspend(accel_handle,
@@ -840,33 +1416,120 @@ int mpu3050_suspend(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
mldl_cfg->compass && mldl_cfg->compass->suspend) {
result = mldl_cfg->compass->suspend(compass_handle,
mldl_cfg->compass,
- &mldl_cfg->pdata->compass);
+ &mldl_cfg->
+ pdata->compass);
+ }
+
+ if (ML_SUCCESS == result && pressure &&
+ mldl_cfg->pressure && mldl_cfg->pressure->suspend) {
+ result = mldl_cfg->pressure->suspend(pressure_handle,
+ mldl_cfg->pressure,
+ &mldl_cfg->
+ pdata->pressure);
}
return result;
}
-int mpu3050_read_accel(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
- unsigned char *data)
+
+/**
+ * @brief read raw sensor data from the accelerometer device
+ * in use.
+ * @param data
+ * a buffer to store the raw sensor data.
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
+ void *mlsl_handle, unsigned char *data)
{
if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->read)
return mldl_cfg->accel->read(mlsl_handle,
mldl_cfg->accel,
- &mldl_cfg->pdata->accel, data);
+ &mldl_cfg->pdata->accel,
+ data);
else
- return ML_ERROR_NOT_OPENED;
+ return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
}
-int mpu3050_read_compass(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
- unsigned char *data)
+/**
+ * @brief read raw sensor data from the compass device
+ * in use.
+ * @param data
+ * a buffer to store the raw sensor data.
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
+ void *mlsl_handle, unsigned char *data)
{
if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->read)
return mldl_cfg->compass->read(mlsl_handle,
mldl_cfg->compass,
- &mldl_cfg->pdata->compass, data);
+ &mldl_cfg->pdata->compass,
+ data);
+ else
+ return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+/**
+ * @brief read raw sensor data from the pressure device
+ * in use.
+ * @param data
+ * a buffer to store the raw sensor data.
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+int mpu3050_read_pressure(struct mldl_cfg *mldl_cfg,
+ void *mlsl_handle, unsigned char *data)
+{
+ if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->read)
+ return mldl_cfg->pressure->read(mlsl_handle,
+ mldl_cfg->pressure,
+ &mldl_cfg->pdata->pressure,
+ data);
else
- return ML_ERROR_NOT_OPENED;
+ return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
}
-/***************************/
- /**@}*//* end of defgroup */
-/***************************/
+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;
+}
+
+
+/**
+ *@}
+ */
diff --git a/drivers/misc/mpu3050/mldl_cfg.h b/drivers/misc/mpu3050/mldl_cfg.h
index 03f752b75966..d714a0ee3ed8 100755..100644
--- a/drivers/misc/mpu3050/mldl_cfg.h
+++ b/drivers/misc/mpu3050/mldl_cfg.h
@@ -16,11 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
- *
- * $Id: mldl_cfg.h 3876 2010-10-12 02:42:22Z prao $
- *
- *******************************************************************************/
/**
* @addtogroup MLDL
@@ -38,7 +33,17 @@
/* ------------------ */
#include "mlsl.h"
-#include "mpu3050.h"
+#include "mpu.h"
+
+/* --------------------- */
+/* - Defines. - */
+/* --------------------- */
+
+#define SAMPLING_PERIOD(mldl_cfg) \
+ (((((mldl_cfg->lpf) == 0) || ((mldl_cfg->lpf) == 7)) \
+ ? (8000) \
+ : (1000)) \
+ / (mldl_cfg->divider + 1))
/* --------------------- */
/* - Variables. - */
@@ -58,8 +63,9 @@ struct mldl_cfg {
unsigned char fifo_enable;
unsigned char dmp_cfg1;
unsigned char dmp_cfg2;
+ unsigned char gyro_power;
unsigned char offset_tc[MPU_NUM_AXES];
- unsigned char __packing;
+ unsigned short offset[MPU_NUM_AXES];
unsigned char ram[MPU_MEM_NUM_RAM_BANKS][MPU_MEM_BANK_SIZE];
/* MPU Related stored status and info */
@@ -73,26 +79,59 @@ struct mldl_cfg {
/* Slave related information */
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, mlsl_handle_t mlsl_handle);
-int mpu3050_resume(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
- mlsl_handle_t accel_handle,
- mlsl_handle_t compass_handle,
- bool resume_accel, bool resume_compass);
-int mpu3050_suspend(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
- mlsl_handle_t accel_handle,
- mlsl_handle_t compass_handle,
- bool suspend_accel, bool suspend_compass);
-int mpu3050_read_accel(struct mldl_cfg *mldl_cfg, mlsl_handle_t mlsl_handle,
+
+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 *mlsl_handle,
+ void *accel_handle,
+ void *compass_handle,
+ void *pressure_handle,
+ bool resume_accel,
+ bool resume_compass,
+ bool resume_pressure);
+int mpu3050_suspend(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+ void *accel_handle,
+ void *compass_handle,
+ void *pressure_handle,
+ bool resume_accel,
+ bool resume_compass,
+ bool resume_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, mlsl_handle_t mlsl_handle,
+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);
+
#endif /* __MLDL_CFG_H__ */
-/***************************/
- /**@}*//* end of defgroup */
-/***************************/
+/**
+ *@}
+ */
diff --git a/drivers/misc/mpu3050/mlos-kernel.c b/drivers/misc/mpu3050/mlos-kernel.c
index 9492ec11a0bf..ced9ba4f6f3c 100755..100644
--- a/drivers/misc/mpu3050/mlos-kernel.c
+++ b/drivers/misc/mpu3050/mlos-kernel.c
@@ -16,9 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/***************************************************************************** *
- * $Id: mlos-kernel.c 3863 2010-10-08 22:05:31Z nroyer $
- ******************************************************************************/
/**
* @defgroup
* @brief
diff --git a/drivers/misc/mpu3050/mlos.h b/drivers/misc/mpu3050/mlos.h
index 4a54ce236e95..4ebb86c9fa5c 100755..100644
--- a/drivers/misc/mpu3050/mlos.h
+++ b/drivers/misc/mpu3050/mlos.h
@@ -16,11 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
- *
- * $Id: mlos.h 3863 2010-10-08 22:05:31Z nroyer $
- *
- *******************************************************************************/
#ifndef _MLOS_H
#define _MLOS_H
diff --git a/drivers/misc/mpu3050/mlsl-kernel.c b/drivers/misc/mpu3050/mlsl-kernel.c
index 4b9494f1d919..908b16f16b24 100755..100644
--- a/drivers/misc/mpu3050/mlsl-kernel.c
+++ b/drivers/misc/mpu3050/mlsl-kernel.c
@@ -16,11 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
- *
- * $Id: mlsl-kernel.c 3863 2010-10-08 22:05:31Z nroyer $
- *
- ******************************************************************************/
#include "mlsl.h"
#include "mpu-i2c.h"
@@ -44,7 +39,7 @@
* The COM port number associated with the device in use.
* @return ML_SUCCESS if successful, a non-zero error code otherwise.
*/
-tMLError MLSLSerialOpen(char const *port, mlsl_handle_t * sl_handle)
+tMLError MLSLSerialOpen(char const *port, void **sl_handle)
{
return ML_SUCCESS;
}
@@ -53,7 +48,7 @@ tMLError MLSLSerialOpen(char const *port, mlsl_handle_t * sl_handle)
* @brief used to reset any buffering the driver may be doing
* @return ML_SUCCESS if successful, a non-zero error code otherwise.
*/
-tMLError MLSLSerialReset(mlsl_handle_t sl_handle)
+tMLError MLSLSerialReset(void *sl_handle)
{
return ML_SUCCESS;
}
@@ -63,7 +58,7 @@ tMLError MLSLSerialReset(mlsl_handle_t sl_handle)
* This port is used to send and receive data to the MPU device.
* @return ML_SUCCESS if successful, a non-zero error code otherwise.
*/
-tMLError MLSLSerialClose(mlsl_handle_t sl_handle)
+tMLError MLSLSerialClose(void *sl_handle)
{
return ML_SUCCESS;
}
@@ -78,94 +73,259 @@ tMLError MLSLSerialClose(mlsl_handle_t sl_handle)
*
* @return ML_SUCCESS if the command is successful, an error code otherwise.
*/
-tMLError MLSLSerialWriteSingle(mlsl_handle_t sl_handle,
+tMLError MLSLSerialWriteSingle(void *sl_handle,
unsigned char slaveAddr,
- unsigned char registerAddr, unsigned char data)
+ unsigned char registerAddr,
+ unsigned char data)
{
- return sensor_i2c_write_register((struct i2c_adapter *)sl_handle,
+ return sensor_i2c_write_register((struct i2c_adapter *) sl_handle,
slaveAddr, registerAddr, data);
+}
+
+
+/**
+ * @brief used to write multiple bytes of data from registers.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param registerAddr Register address to write.
+ * @param length Length of burst of data.
+ * @param data Pointer to block of data.
+ *
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+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 {
+ /* manually increment register addr between chunks */
+ 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;
}
+
/**
- * @brief used to read multiple bytes of data.
- * This should be sent by I2C or SPI.
+ * @brief used to read multiple bytes of data from registers.
+ * This should be sent by I2C.
*
* @param slaveAddr I2C slave address of device.
* @param registerAddr Register address to read.
- * @param length Length of burst data.
+ * @param length Length of burst of data.
* @param data Pointer to block of data.
*
- * @return Zero if the command is successful; an error code otherwise
+ * @return Zero if successful; an error code otherwise
*/
-tMLError MLSLSerialRead(mlsl_handle_t sl_handle,
+tMLError MLSLSerialRead(void *sl_handle,
unsigned char slaveAddr,
unsigned char registerAddr,
unsigned short length, unsigned char *data)
{
- return sensor_i2c_read((struct i2c_adapter *)sl_handle,
- slaveAddr, registerAddr, length, 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;
}
+
/**
- * @brief used to write multiple bytes of data.
- * This should be sent by I2C or SPI.
+ * @brief used to write multiple bytes of data to the memory.
+ * This should be sent by I2C.
*
* @param slaveAddr I2C slave address of device.
+ * @param memAddr The location in the memory to write to.
* @param length Length of burst data.
- * @param data Pointer to block of data. First byte is the
- * register address to write.
+ * @param data Pointer to block of data.
*
- * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ * @return Zero if successful; an error code otherwise
*/
-tMLError MLSLSerialWrite(mlsl_handle_t sl_handle,
- unsigned char slaveAddr,
- unsigned short length, unsigned char const *data)
+tMLError MLSLSerialWriteMem(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned short memAddr,
+ unsigned short length,
+ unsigned char const *data)
{
- return sensor_i2c_write((struct i2c_adapter *)sl_handle,
- slaveAddr, length, 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;
}
+
/**
- * @brief used to read multiple bytes of data.
- * This should be sent by I2C or SPI.
+ * @brief used to read multiple bytes of data from the memory.
+ * This should be sent by I2C.
*
* @param slaveAddr I2C slave address of device.
- * @param registerAddr Register address to read.
+ * @param memAddr The location in the memory to read from.
* @param length Length of burst data.
* @param data Pointer to block of data.
*
- * @return Zero if the command is successful; an error code otherwise
+ * @return Zero if successful; an error code otherwise
*/
-tMLError MLSLSerialReadMem(mlsl_handle_t sl_handle,
+tMLError MLSLSerialReadMem(void *sl_handle,
unsigned char slaveAddr,
unsigned short memAddr,
unsigned short length, unsigned char *data)
{
- return mpu_memory_read((struct i2c_adapter *)sl_handle,
- slaveAddr, memAddr, length, 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;
}
+
/**
- * @brief used to write multiple bytes of data.
- * This should be sent by I2C or SPI.
+ * @brief used to write multiple bytes of data to the fifo.
+ * This should be sent by I2C.
*
* @param slaveAddr I2C slave address of device.
- * @param length Length of burst data.
- * @param data Pointer to block of data. First byte is the
- * register address to write.
+ * @param length Length of burst of data.
+ * @param data Pointer to block of data.
*
- * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ * @return Zero if successful; an error code otherwise
+ */
+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;
+}
+
+
+/**
+ * @brief used to read multiple bytes of data from the fifo.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param length Length of burst of data.
+ * @param data Pointer to block of data.
+ *
+ * @return Zero if successful; an error code otherwise
*/
-tMLError MLSLSerialWriteMem(mlsl_handle_t sl_handle,
+tMLError MLSLSerialReadFifo(void *sl_handle,
unsigned char slaveAddr,
- unsigned short mem_addr,
- unsigned short length, unsigned char const *data)
+ unsigned short length, unsigned char *data)
{
- return mpu_memory_write((struct i2c_adapter *)sl_handle,
- slaveAddr, mem_addr, length, 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;
}
-/***********************/
- /** @} *//* defgroup */
-/*********************/
+/**
+ * @}
+ */
diff --git a/drivers/misc/mpu3050/mlsl.h b/drivers/misc/mpu3050/mlsl.h
index d41683eddb77..76f69c77ba98 100755..100644
--- a/drivers/misc/mpu3050/mlsl.h
+++ b/drivers/misc/mpu3050/mlsl.h
@@ -16,17 +16,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
- *
- * $Id: mlsl.h 3863 2010-10-08 22:05:31Z nroyer $
- *
- ******************************************************************************/
#ifndef __MSSL_H__
#define __MSSL_H__
#include "mltypes.h"
-#include "mpu3050.h"
+#include "mpu.h"
#ifdef __cplusplus
extern "C" {
@@ -36,46 +31,73 @@ extern "C" {
/* - Defines. - */
/* ------------ */
+/*
+ * NOTE : to properly support Yamaha compass reads,
+ * the max transfer size should be at least 9 B.
+ * Length in bytes, typically a power of 2 >= 2
+ */
+#define SERIAL_MAX_TRANSFER_SIZE 128
+
/* ---------------------- */
/* - Types definitions. - */
/* ---------------------- */
- typedef void *tMLSLHandle; /* For MPL coding standards */
-
/* --------------------- */
/* - Function p-types. - */
/* --------------------- */
- tMLError MLSLSerialOpen(char const *port, mlsl_handle_t * sl_handle);
- tMLError MLSLSerialReset(mlsl_handle_t sl_handle);
- tMLError MLSLSerialClose(mlsl_handle_t sl_handle);
- tMLError MLSLSerialWriteSingle(mlsl_handle_t sl_handle,
+ 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(mlsl_handle_t sl_handle,
+
+ tMLError MLSLSerialRead(void *sl_handle,
unsigned char slaveAddr,
unsigned char registerAddr,
- unsigned short length, unsigned char *data);
- tMLError MLSLSerialWrite(mlsl_handle_t sl_handle,
+ unsigned short length,
+ unsigned char *data);
+
+ tMLError MLSLSerialWrite(void *sl_handle,
unsigned char slaveAddr,
unsigned short length,
unsigned char const *data);
- tMLError MLSLSerialReadMem(mlsl_handle_t sl_handle,
+
+ tMLError MLSLSerialReadMem(void *sl_handle,
unsigned char slaveAddr,
unsigned short memAddr,
- unsigned short length, unsigned char *data);
- tMLError MLSLSerialWriteMem(mlsl_handle_t sl_handle,
+ 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 MLSLGetCalLength(unsigned int *len);
tMLError MLSLReadCal(unsigned char *cal, unsigned int len);
+ tMLError MLSLGetCalLength(unsigned int *len);
#ifdef __cplusplus
}
#endif
- /***********************//** @} *//* defgroup *//*********************/
-#endif // MLSL_H
+
+/**
+ * @}
+ */
+#endif /* MLSL_H */
diff --git a/drivers/misc/mpu3050/mltypes.h b/drivers/misc/mpu3050/mltypes.h
index 4ffc890ca7b8..447e208ee0a5 100755..100644
--- a/drivers/misc/mpu3050/mltypes.h
+++ b/drivers/misc/mpu3050/mltypes.h
@@ -16,15 +16,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/*******************************************************************************
+/******************************************************************************
*
- * $Id: mltypes.h 3866 2010-10-09 00:51:32Z nroyer $
- *
- *******************************************************************************/
+ * $Id: mltypes.h 4436 2011-01-13 05:07:53Z mcaramello $
+ *
+ *****************************************************************************/
/**
* @defgroup MLERROR
- * @brief Definition of the error codes used within the MPL and returned
+ * @brief Motion Library - Error definitions.
+ * Definition of the error codes used within the MPL and returned
* to the user.
* Every function tries to return a meaningful error code basing
* on the occuring error condition. The error code is numeric.
@@ -67,8 +68,15 @@
* - (70) ML_ERROR_COMPASS_DATA_OVERFLOW
* - (71) ML_ERROR_COMPASS_DATA_UNDERFLOW
* - (72) ML_ERROR_COMPASS_DATA_NOT_READY
+ * - (75) ML_ERROR_CALIBRATION_LOAD
+ * - (76) ML_ERROR_CALIBRATION_STORE
+ * - (77) ML_ERROR_CALIBRATION_LEN
+ * - (78) ML_ERROR_CALIBRATION_CHECKSUM
*
-**/
+ * @{
+ * @file mltypes.h
+ * @}
+ */
#ifndef MLTYPES_H
#define MLTYPES_H
@@ -84,19 +92,6 @@
ML Types
---------------------------*/
-typedef long long MLS64;
-typedef int MLS32;
-typedef unsigned int MLU32;
-typedef short MLS16;
-typedef unsigned short MLU16;
-typedef char MLS8;
-typedef unsigned char MLU8;
-typedef unsigned char MLBOOL;
-typedef double MLDBL;
-typedef float MLFLT;
-
-typedef unsigned char tReg;
-
/**
* @struct tMLError The MPL Error Code return type.
*
@@ -106,7 +101,7 @@ typedef unsigned char tReg;
*/
typedef unsigned char tMLError;
-#if defined(LINUX) || defined (__KERNEL__)
+#if defined(LINUX) || defined(__KERNEL__)
typedef unsigned int HANDLE;
#endif
@@ -144,18 +139,19 @@ typedef int_fast8_t bool;
/* - ML Errors. - */
#define ERROR_NAME(x) (#x)
#define ERROR_CHECK(x) \
-{ \
- if (ML_SUCCESS != x) { \
- MPL_LOGE("%s|%s|%d returning %d\n", \
- __FILE__, __func__, __LINE__, x); \
- return x; \
- } \
-}
+ { \
+ if (ML_SUCCESS != x) { \
+ MPL_LOGE("%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 ERROR_CHECK_FIRST(first, x) \
+ { if (ML_SUCCESS == first) first = x; }
#define ML_SUCCESS (0)
-/* Generic Error code. Propritary Error Codes only */
+/* Generic Error code. Proprietary Error Codes only */
#define ML_ERROR (1)
/* Compatibility and other generic error codes */
@@ -173,6 +169,7 @@ typedef int_fast8_t bool;
#define ML_ERROR_FILE_OPEN (14)
#define ML_ERROR_FILE_READ (15)
#define ML_ERROR_FILE_WRITE (16)
+#define ML_ERROR_INVALID_CONFIGURATION (17)
/* Serial Communication */
#define ML_ERROR_SERIAL_CLOSED (20)
@@ -197,7 +194,7 @@ typedef int_fast8_t bool;
#define ML_ERROR_LOG_MEMORY_ERROR (50)
#define ML_ERROR_LOG_OUTPUT_ERROR (51)
-/*OS interface errors */
+/* OS interface errors */
#define ML_ERROR_OS_BAD_PTR (60)
#define ML_ERROR_OS_BAD_HANDLE (61)
#define ML_ERROR_OS_CREATE_FAILED (62)
@@ -208,6 +205,17 @@ typedef int_fast8_t bool;
#define ML_ERROR_COMPASS_DATA_UNDERFLOW (71)
#define ML_ERROR_COMPASS_DATA_NOT_READY (72)
+/* Load/Store calibration */
+#define ML_ERROR_CALIBRATION_LOAD (75)
+#define ML_ERROR_CALIBRATION_STORE (76)
+#define ML_ERROR_CALIBRATION_LEN (77)
+#define ML_ERROR_CALIBRATION_CHECKSUM (78)
+
+/* For Linux coding compliance */
+#ifndef __KERNEL__
+#define EXPORT_SYMBOL(x)
+#endif
+
/*---------------------------
p-Types
---------------------------*/
diff --git a/drivers/misc/mpu3050/mpu-dev.c b/drivers/misc/mpu3050/mpu-dev.c
index dde346bc0e9b..6cde9eeccced 100755..100644
--- a/drivers/misc/mpu3050/mpu-dev.c
+++ b/drivers/misc/mpu3050/mpu-dev.c
@@ -46,23 +46,17 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/wait.h>
-#include <asm/uaccess.h>
-#include <asm/io.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 "mpu3050.h"
+#include "mpu.h"
#define MPU3050_EARLY_SUSPEND_IN_DRIVER 0
-#define MPU_NAME "mpu"
-#define MPU_SLAVE_ADDR (0x68)
-
-#define MPU_GET_INTERRUPT_CNT (2)
-#define MPU_GET_IRQ_TIME (3)
-#define MPU_GET_LED_VALUE (4)
-#define MPU_SET_TIMEOUT (5)
/* Platform data for the MPU */
struct mpu_private_data {
@@ -79,22 +73,24 @@ static struct i2c_client *this_client;
static int mpu_open(struct inode *inode, struct file *file)
{
- printk("mpu_open\n");
- printk("current->pid %d\n", current->pid);
+ 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;
- /* we could do some checking on the flags supplied by "open"
- // i.e. O_NONBLOCK
- // -> set some flag to disable interruptible_sleep_on in mpu_read */
+ /* we could do some checking on the flags supplied by "open" */
+ /* i.e. O_NONBLOCK */
+ /* -> set some flag to disable interruptible_sleep_on in mpu_read */
return 0;
}
-/* close function - called when the "file" /dev/mpu is closed in userspace */
+/* close function - called when the "file" /dev/mpu is closed in userspace */
static int mpu_release(struct inode *inode, struct file *file)
{
- struct i2c_client *client = (struct i2c_client *)file->private_data;
+ struct i2c_client *client =
+ (struct i2c_client *) file->private_data;
struct mpu_private_data *mpu =
- (struct mpu_private_data *)i2c_get_clientdata(client);
+ (struct mpu_private_data *) i2c_get_clientdata(client);
struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
int result = 0;
@@ -103,16 +99,21 @@ static int mpu_release(struct inode *inode, struct file *file)
if (!mldl_cfg->is_suspended) {
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);
result =
- mpu3050_suspend(mldl_cfg, client->adapter, accel_adapter,
- compass_adapter, TRUE, TRUE);
+ mpu3050_suspend(mldl_cfg, client->adapter,
+ accel_adapter, compass_adapter,
+ pressure_adapter,
+ TRUE, TRUE, TRUE);
}
- printk("mpu_release\n");
+ dev_dbg(&this_client->adapter->dev, "mpu_release\n");
return result;
}
@@ -125,7 +126,7 @@ static noinline int mpudev_ioctl_rdrw(struct i2c_client *client,
int i, res;
if (copy_from_user(&rdwr_arg,
- (struct i2c_rdwr_ioctl_data __user *)arg,
+ (struct i2c_rdwr_ioctl_data __user *) arg,
sizeof(rdwr_arg)))
return -EFAULT;
@@ -145,7 +146,8 @@ static noinline int mpudev_ioctl_rdrw(struct i2c_client *client,
return -EFAULT;
}
- data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+ data_ptrs =
+ kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
if (data_ptrs == NULL) {
kfree(rdwr_pa);
return -ENOMEM;
@@ -203,7 +205,8 @@ static ssize_t mpu_read(struct file *file,
char *tmp;
int ret;
- struct i2c_client *client = (struct i2c_client *)file->private_data;
+ struct i2c_client *client =
+ (struct i2c_client *) file->private_data;
if (count > 8192)
count = 8192;
@@ -223,25 +226,41 @@ static ssize_t mpu_read(struct file *file,
return ret;
}
-static int mpu_ioctl_get_mpu_pdata(struct i2c_client *client, unsigned long arg)
+static int
+mpu_ioctl_set_mpu_pdata(struct i2c_client *client, unsigned long arg)
{
+ int ii;
int result;
struct mpu_private_data *mpu =
- (struct mpu_private_data *)i2c_get_clientdata(client);
- struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
- int accel_adapt_num = mldl_cfg->pdata->accel.adapt_num;
- int compass_adapt_num = mldl_cfg->pdata->compass.adapt_num;
- int accel_bus = mldl_cfg->pdata->accel.bus;
- int compass_bus = mldl_cfg->pdata->compass.bus;
-
- result = copy_from_user(mldl_cfg->pdata,
- (unsigned char *)arg,
- sizeof(struct mpu3050_platform_data));
- /* Don't allow userspace to change the adapter number or bus */
- mldl_cfg->pdata->accel.adapt_num = accel_adapt_num;
- mldl_cfg->pdata->compass.adapt_num = compass_adapt_num;
- mldl_cfg->pdata->accel.bus = accel_bus;
- mldl_cfg->pdata->compass.bus = compass_bus;
+ (struct mpu_private_data *) i2c_get_clientdata(client);
+ struct mpu3050_platform_data *pdata = mpu->mldl_cfg.pdata;
+ struct mpu3050_platform_data local_pdata;
+
+ result = copy_from_user(&local_pdata,
+ (unsigned char *) arg,
+ sizeof(local_pdata));
+
+ 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 result;
}
@@ -250,18 +269,18 @@ static int
mpu_ioctl_set_mpu_config(struct i2c_client *client, unsigned long arg)
{
struct mpu_private_data *mpu =
- (struct mpu_private_data *)i2c_get_clientdata(client);
+ (struct mpu_private_data *) i2c_get_clientdata(client);
struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
- printk("%s\n", __func__);
+ dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
+
/*
- * User space is not allowed to modify accel compass or pdata structs,
- * as well as silicon_revision product_id or trim
+ * User space is not allowed to modify accel compass pressure or
+ * pdata structs, as well as silicon_revision product_id or trim
*/
- if (copy_from_user(mldl_cfg,
- (struct mldl_cfg *)arg,
+ if (copy_from_user(mldl_cfg, (struct mldl_cfg *) arg,
offsetof(struct mldl_cfg, silicon_revision)))
- return -EFAULT;
+ return -EFAULT;
return 0;
}
@@ -272,22 +291,22 @@ mpu_ioctl_get_mpu_config(struct i2c_client *client, unsigned long arg)
/* Have to be careful as there are 3 pointers in the mldl_cfg
* structure */
struct mpu_private_data *mpu =
- (struct mpu_private_data *)i2c_get_clientdata(client);
+ (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 = kmalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
+ local_mldl_cfg = kzalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
if (NULL == local_mldl_cfg)
return -ENOMEM;
retval =
- copy_from_user(local_mldl_cfg, (void *)arg,
+ copy_from_user(local_mldl_cfg, (void *) arg,
sizeof(struct mldl_cfg));
if (retval)
goto out;
- /* Fill in the accel, compass and pdata pointers */
+ /* Fill in the accel, compass, pressure and pdata pointers */
if (mldl_cfg->accel) {
retval = copy_to_user(local_mldl_cfg->accel,
mldl_cfg->accel,
@@ -304,6 +323,14 @@ mpu_ioctl_get_mpu_config(struct i2c_client *client, unsigned long arg)
goto out;
}
+ if (mldl_cfg->pressure) {
+ retval = copy_to_user(local_mldl_cfg->pressure,
+ mldl_cfg->pressure,
+ sizeof(*mldl_cfg->pressure));
+ if (retval)
+ goto out;
+ }
+
if (mldl_cfg->pdata) {
retval = copy_to_user(local_mldl_cfg->pdata,
mldl_cfg->pdata,
@@ -312,28 +339,34 @@ mpu_ioctl_get_mpu_config(struct i2c_client *client, unsigned long arg)
goto out;
}
- /* Do not modify the accel, compass and pdata pointers */
- retval = copy_to_user((struct mldl_cfg *)arg,
+ /* Do not modify the accel, compass, pressure and pdata pointers */
+ retval = copy_to_user((struct mldl_cfg *) arg,
mldl_cfg, offsetof(struct mldl_cfg, accel));
- out:
+out:
kfree(local_mldl_cfg);
return retval;
}
/* ioctl - I/O control */
-static long mpu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long mpu_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- struct i2c_client *client = (struct i2c_client *)file->private_data;
+ struct i2c_client *client =
+ (struct i2c_client *) file->private_data;
struct mpu_private_data *mpu =
- (struct mpu_private_data *)i2c_get_clientdata(client);
+ (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);
+ 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:
@@ -341,104 +374,214 @@ static long mpu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case I2C_SLAVE:
if ((arg & 0x7E) != (client->addr & 0x7E)) {
- printk("%s: Invalid I2C_SLAVE arg %lu \n",
- __func__, arg);
+ dev_err(&this_client->adapter->dev,
+ "%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;
+ mldl_cfg->int_config = (unsigned char) arg;
break;
case MPU_SET_EXT_SYNC:
- mldl_cfg->ext_sync = (enum mpu_ext_sync)arg;
+ mldl_cfg->ext_sync = (enum mpu_ext_sync) arg;
break;
case MPU_SET_FULL_SCALE:
- mldl_cfg->full_scale = (enum mpu_fullscale)arg;
+ mldl_cfg->full_scale = (enum mpu_fullscale) arg;
break;
case MPU_SET_LPF:
- mldl_cfg->lpf = (enum mpu_filter)arg;
+ mldl_cfg->lpf = (enum mpu_filter) arg;
break;
case MPU_SET_CLK_SRC:
- mldl_cfg->clk_src = (enum mpu_clock_sel)arg;
+ mldl_cfg->clk_src = (enum mpu_clock_sel) arg;
break;
case MPU_SET_DIVIDER:
- mldl_cfg->divider = (unsigned char)arg;
+ mldl_cfg->divider = (unsigned char) arg;
break;
case MPU_SET_LEVEL_SHIFTER:
- mldl_cfg->pdata->level_shifter = (unsigned char)arg;
+ mldl_cfg->pdata->level_shifter = (unsigned char) arg;
break;
case MPU_SET_DMP_ENABLE:
- mldl_cfg->dmp_enable = (unsigned char)arg;
+ mldl_cfg->dmp_enable = (unsigned char) arg;
break;
case MPU_SET_FIFO_ENABLE:
- mldl_cfg->fifo_enable = (unsigned char)arg;
+ mldl_cfg->fifo_enable = (unsigned char) arg;
break;
case MPU_SET_DMP_CFG1:
- mldl_cfg->dmp_cfg1 = (unsigned char)arg;
+ mldl_cfg->dmp_cfg1 = (unsigned char) arg;
break;
case MPU_SET_DMP_CFG2:
- mldl_cfg->dmp_cfg2 = (unsigned char)arg;
+ mldl_cfg->dmp_cfg2 = (unsigned char) arg;
break;
case MPU_SET_OFFSET_TC:
retval = copy_from_user(mldl_cfg->offset_tc,
- (unsigned char *)arg,
+ (unsigned char *) arg,
sizeof(mldl_cfg->offset_tc));
break;
case MPU_SET_RAM:
retval = copy_from_user(mldl_cfg->ram,
- (unsigned char *)arg,
+ (unsigned char *) arg,
sizeof(mldl_cfg->ram));
break;
case MPU_SET_PLATFORM_DATA:
- retval = mpu_ioctl_get_mpu_pdata(client, arg);
+ 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:
- mldl_cfg->int_config = (unsigned char)arg;
+ mldl_cfg->int_config = (unsigned char) arg;
break;
case MPU_GET_EXT_SYNC:
- mldl_cfg->ext_sync = (enum mpu_ext_sync)arg;
+ mldl_cfg->ext_sync = (enum mpu_ext_sync) arg;
break;
case MPU_GET_FULL_SCALE:
- mldl_cfg->full_scale = (enum mpu_fullscale)arg;
+ mldl_cfg->full_scale = (enum mpu_fullscale) arg;
break;
case MPU_GET_LPF:
- mldl_cfg->lpf = (enum mpu_filter)arg;
+ mldl_cfg->lpf = (enum mpu_filter) arg;
break;
case MPU_GET_CLK_SRC:
- mldl_cfg->clk_src = (enum mpu_clock_sel)arg;
+ mldl_cfg->clk_src = (enum mpu_clock_sel) arg;
break;
case MPU_GET_DIVIDER:
- mldl_cfg->divider = (unsigned char)arg;
+ mldl_cfg->divider = (unsigned char) arg;
break;
case MPU_GET_LEVEL_SHIFTER:
- mldl_cfg->pdata->level_shifter = (unsigned char)arg;
+ mldl_cfg->pdata->level_shifter = (unsigned char) arg;
break;
case MPU_GET_DMP_ENABLE:
- mldl_cfg->dmp_enable = (unsigned char)arg;
+ mldl_cfg->dmp_enable = (unsigned char) arg;
break;
case MPU_GET_FIFO_ENABLE:
- mldl_cfg->fifo_enable = (unsigned char)arg;
+ mldl_cfg->fifo_enable = (unsigned char) arg;
break;
case MPU_GET_DMP_CFG1:
- mldl_cfg->dmp_cfg1 = (unsigned char)arg;
+ mldl_cfg->dmp_cfg1 = (unsigned char) arg;
break;
case MPU_GET_DMP_CFG2:
- mldl_cfg->dmp_cfg2 = (unsigned char)arg;
+ mldl_cfg->dmp_cfg2 = (unsigned char) arg;
break;
case MPU_GET_OFFSET_TC:
- retval = copy_to_user((unsigned char *)arg,
+ retval = copy_to_user((unsigned char *) arg,
mldl_cfg->offset_tc,
sizeof(mldl_cfg->offset_tc));
break;
case MPU_GET_RAM:
- retval = copy_to_user((unsigned char *)arg,
- mldl_cfg->ram, sizeof(mldl_cfg->ram));
+ retval = copy_to_user((unsigned char *) arg,
+ mldl_cfg->ram,
+ sizeof(mldl_cfg->ram));
break;
+ case MPU_CONFIG_ACCEL:
+ {
+ if ((mldl_cfg->accel) && (mldl_cfg->accel->config)) {
+ struct ext_slave_config config;
+ retval = copy_from_user(
+ &config,
+ (struct ext_slave_config *)arg,
+ sizeof(config));
+ if (retval)
+ break;
+
+ if (config.len && config.data) {
+ int *data;
+ data = kzalloc(config.len, GFP_KERNEL);
+ if (!data) {
+ retval = ML_ERROR_MEMORY_EXAUSTED;
+ break;
+ }
+ retval = copy_from_user(data,
+ (void *)config.data,
+ config.len);
+ if (retval) {
+ kfree(data);
+ break;
+ }
+ config.data = data;
+ }
+ retval = mldl_cfg->accel->config(
+ accel_adapter,
+ mldl_cfg->accel,
+ &mldl_cfg->pdata->accel,
+ &config);
+ kfree(config.data);
+ }
+ break;
+ }
+ case MPU_CONFIG_COMPASS:
+ {
+ if ((mldl_cfg->compass) && (mldl_cfg->compass->config)) {
+ struct ext_slave_config config;
+ retval = copy_from_user(
+ &config,
+ (struct ext_slave_config *)arg,
+ sizeof(config));
+ if (retval)
+ break;
+
+ if (config.len && config.data) {
+ int *data;
+ data = kzalloc(config.len, GFP_KERNEL);
+ if (!data) {
+ retval = ML_ERROR_MEMORY_EXAUSTED;
+ break;
+ }
+ retval = copy_from_user(data,
+ (void *)config.data,
+ config.len);
+ if (retval) {
+ kfree(data);
+ break;
+ }
+ config.data = data;
+ }
+ retval = mldl_cfg->compass->config(
+ compass_adapter,
+ mldl_cfg->compass,
+ &mldl_cfg->pdata->compass,
+ &config);
+ kfree(config.data);
+ }
+ break;
+ }
+ case MPU_CONFIG_PRESSURE:
+ {
+ if ((mldl_cfg->pressure) && (mldl_cfg->pressure->config)) {
+ struct ext_slave_config config;
+ retval = copy_from_user(
+ &config,
+ (struct ext_slave_config *)arg,
+ sizeof(config));
+ if (retval)
+ break;
+
+ if (config.len && config.data) {
+ int *data;
+ data = kzalloc(config.len, GFP_KERNEL);
+ if (!data) {
+ retval = ML_ERROR_MEMORY_EXAUSTED;
+ break;
+ }
+ retval = copy_from_user(data,
+ (void *)config.data,
+ config.len);
+ if (retval) {
+ kfree(data);
+ break;
+ }
+ config.data = data;
+ }
+ retval = mldl_cfg->pressure->config(
+ pressure_adapter,
+ mldl_cfg->pressure,
+ &mldl_cfg->pdata->pressure,
+ &config);
+ kfree(config.data);
+ }
+ break;
+ }
case MPU_READ_MEMORY:
case MPU_WRITE_MEMORY:
case MPU_SUSPEND:
@@ -456,11 +599,13 @@ static long mpu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
client->adapter,
accel_adapter,
compass_adapter,
+ pressure_adapter,
suspend.accel,
- suspend.compass);
+ suspend.compass,
+ suspend.pressure);
} else {
- /* Cannot suspend the compass or accel while
- * the MPU is running */
+ /* Cannot suspend the pressure compass or
+ * accel while the MPU is running */
retval = ML_ERROR_FEATURE_NOT_IMPLEMENTED;
}
}
@@ -480,28 +625,43 @@ static long mpu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
client->adapter,
accel_adapter,
compass_adapter,
+ pressure_adapter,
resume.accel,
- resume.compass);
+ resume.compass,
+ resume.pressure);
} else if (mldl_cfg->is_suspended) {
if (resume.accel) {
retval =
- mldl_cfg->accel->
- resume(accel_adapter,
- mldl_cfg->accel,
- &mldl_cfg->pdata->accel);
+ mldl_cfg->
+ accel->resume(accel_adapter,
+ mldl_cfg->accel,
+ &mldl_cfg->
+ pdata->accel);
+ if (retval)
+ break;
+ }
+
+ if (resume.compass) {
+ retval =
+ mldl_cfg->
+ compass->resume
+ (compass_adapter,
+ mldl_cfg->compass,
+ &mldl_cfg->pdata->compass);
if (retval)
break;
}
- if (resume.compass)
+ if (resume.pressure)
retval =
- mldl_cfg->compass->
- resume(compass_adapter,
- mldl_cfg->compass,
- &mldl_cfg->pdata->compass);
+ mldl_cfg->
+ pressure->resume
+ (pressure_adapter,
+ mldl_cfg->pressure,
+ &mldl_cfg->pdata->pressure);
} else {
- /* Cannot resume the compass or accel while
- * the MPU is running */
+ /* Cannot resume the pressure compass or
+ * accel while the MPU is running */
retval = ML_ERROR_FEATURE_NOT_IMPLEMENTED;
}
}
@@ -510,10 +670,11 @@ static long mpu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned char data[6];
retval =
- mpu3050_read_accel(mldl_cfg, client->adapter, data);
+ mpu3050_read_accel(mldl_cfg, client->adapter,
+ data);
if (ML_SUCCESS == retval)
retval =
- copy_to_user((unsigned char *)arg,
+ copy_to_user((unsigned char *) arg,
data, sizeof(data));
}
break;
@@ -521,17 +682,36 @@ static long mpu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned char data[6];
struct i2c_adapter *compass_adapt =
- i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+ i2c_get_adapter(mldl_cfg->pdata->compass.
+ adapt_num);
retval =
- mpu3050_read_compass(mldl_cfg, compass_adapt, data);
+ mpu3050_read_compass(mldl_cfg, compass_adapt,
+ data);
if (ML_SUCCESS == retval)
retval =
- copy_to_user((unsigned char *)arg,
+ copy_to_user((unsigned char *) arg,
+ data, sizeof(data));
+ }
+ 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)
+ retval =
+ copy_to_user((unsigned char *) arg,
data, sizeof(data));
}
break;
default:
- printk("%s: Unknown cmd %d, arg %lu \n", __func__, cmd, arg);
+ dev_err(&this_client->adapter->dev,
+ "%s: Unknown cmd %d, arg %lu\n", __func__, cmd,
+ arg);
retval = -EINVAL;
}
@@ -548,15 +728,20 @@ void mpu3050_early_suspend(struct early_suspend *h)
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);
+ compass_adapter =
+ i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+ pressure_adapter =
+ i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
- printk("%s: %d, %d\n", __func__, h->level, mpu->mldl_cfg.is_suspended);
+ dev_dbg(&this_client->adapter->dev, "%s: %d, %d\n", __func__,
+ h->level, mpu->mldl_cfg.is_suspended);
if (MPU3050_EARLY_SUSPEND_IN_DRIVER)
- (void)mpu3050_suspend(mldl_cfg,
- accel_adapter, compass_adapter,
- this_client->adapter, TRUE, TRUE);
+ (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
+ accel_adapter, compass_adapter,
+ pressure_adapter, TRUE, TRUE, TRUE);
}
void mpu3050_early_resume(struct early_suspend *h)
@@ -568,56 +753,78 @@ void mpu3050_early_resume(struct early_suspend *h)
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);
+ 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) {
- (void)mpu3050_resume(mldl_cfg,
- accel_adapter, compass_adapter,
- this_client->adapter, TRUE, TRUE);
- printk("%s for pid %d\n", __func__, pid);
+ (void) mpu3050_resume(mldl_cfg,
+ this_client->adapter,
+ accel_adapter,
+ compass_adapter,
+ pressure_adapter,
+ TRUE, TRUE, TRUE);
+ dev_dbg(&this_client->adapter->dev,
+ "%s for pid %d\n", __func__, pid);
}
}
- printk("%s: %d\n", __func__, h->level);
+ 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 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);
-
- (void)mpu3050_suspend(mldl_cfg, this_client->adapter,
- accel_adapter, compass_adapter, TRUE, TRUE);
- printk("%s\n", __func__);
+ 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);
+ 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 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);
+ 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.is_suspended) {
- printk("%s: suspending on event %d\n", __func__, mesg.event);
- (void)mpu3050_suspend(mldl_cfg, this_client->adapter,
- accel_adapter, compass_adapter,
- TRUE, TRUE);
+ 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);
} else {
- printk("%s: Already suspended %d\n", __func__, mesg.event);
+ dev_dbg(&this_client->adapter->dev,
+ "%s: Already suspended %d\n", __func__,
+ mesg.event);
}
return 0;
}
@@ -625,25 +832,32 @@ int mpu_suspend(struct i2c_client *client, pm_message_t mesg)
int mpu_resume(struct i2c_client *client)
{
struct mpu_private_data *mpu =
- (struct mpu_private_data *)i2c_get_clientdata(client);
+ (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);
+ compass_adapter =
+ i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+ pressure_adapter =
+ i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
if (pid) {
- (void)mpu3050_resume(mldl_cfg, this_client->adapter,
- accel_adapter, compass_adapter,
- TRUE, TRUE);
- printk("%s for pid %d\n", __func__, pid);
+ (void) mpu3050_resume(mldl_cfg, this_client->adapter,
+ accel_adapter,
+ compass_adapter,
+ pressure_adapter,
+ TRUE, TRUE, TRUE);
+ dev_dbg(&this_client->adapter->dev,
+ "%s for pid %d\n", __func__, pid);
}
return 0;
}
/* define which file operations are supported */
-struct file_operations mpu_fops = {
+static const struct file_operations mpu_fops = {
.owner = THIS_MODULE,
.read = mpu_read,
#if HAVE_COMPAT_IOCTL
@@ -664,16 +878,22 @@ I2C_CLIENT_INSMOD;
static struct miscdevice i2c_mpu_device = {
.minor = MISC_DYNAMIC_MINOR,
- .name = MPU_NAME,
+ .name = "mpu", /* Same for both 3050 and 6000 */
.fops = &mpu_fops,
};
-int mpu3050_probe(struct i2c_client *client, const struct i2c_device_id *devid)
+
+int mpu3050_probe(struct i2c_client *client,
+ const struct i2c_device_id *devid)
{
struct mpu3050_platform_data *pdata;
struct mpu_private_data *mpu;
int res = 0;
- printk("%s\n", __func__);
+ 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;
@@ -689,77 +909,164 @@ int mpu3050_probe(struct i2c_client *client, const struct i2c_device_id *devid)
i2c_set_clientdata(client, mpu);
this_client = client;
- pdata = (struct mpu3050_platform_data *)client->dev.platform_data;
+ pdata = (struct mpu3050_platform_data *) client->dev.platform_data;
if (!pdata) {
- printk("Warning no platform data for mpu3050\n");
+ dev_warn(&this_client->adapter->dev,
+ "Warning no platform data for mpu3050\n");
} else {
mpu->mldl_cfg.pdata = pdata;
-#ifdef CONFIG_SENSORS_MPU3050_MODULE
+#if defined(CONFIG_SENSORS_MPU3050_MODULE) || \
+ defined(CONFIG_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) {
- mpu->mldl_cfg.accel = pdata->accel.get_slave_descr();
- printk("MPU3050: +%s\n", mpu->mldl_cfg.accel->name);
+ mpu->mldl_cfg.accel =
+ pdata->accel.get_slave_descr();
+ dev_info(&this_client->adapter->dev,
+ "%s: +%s\n", MPU_NAME,
+ mpu->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_warn(&this_client->adapter->dev,
+ "WARNING: Accel irq not assigned\n");
+ }
} else {
- printk("MPU3050: No Accel Present\n");
+ dev_warn(&this_client->adapter->dev,
+ "%s: No Accel Present\n", MPU_NAME);
}
if (pdata->compass.get_slave_descr) {
mpu->mldl_cfg.compass =
pdata->compass.get_slave_descr();
- printk("MPU3050: +%s\n", mpu->mldl_cfg.compass->name);
+ dev_info(&this_client->adapter->dev,
+ "%s: +%s\n", MPU_NAME,
+ mpu->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_warn(&this_client->adapter->dev,
+ "WARNING: Compass irq not assigned\n");
+ }
} else {
- printk("MPU3050: No Compass Present\n");
+ dev_warn(&this_client->adapter->dev,
+ "%s: No Compass Present\n", MPU_NAME);
+ }
+
+ if (pdata->pressure.get_slave_descr) {
+ mpu->mldl_cfg.pressure =
+ pdata->pressure.get_slave_descr();
+ dev_info(&this_client->adapter->dev,
+ "%s: +%s\n", MPU_NAME,
+ mpu->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_warn(&this_client->adapter->dev,
+ "%s: No Pressure Present\n", MPU_NAME);
}
}
mpu->mldl_cfg.addr = client->addr;
- res = mpu3050_open(&mpu->mldl_cfg, (tMLSLHandle) client->adapter);
+ res = mpu3050_open(&mpu->mldl_cfg, client->adapter,
+ accel_adapter, compass_adapter, pressure_adapter);
if (res) {
- printk("Unable to open MPU3050 %d\n", res);
+ dev_err(&this_client->adapter->dev,
+ "Unable to open %s %d\n", MPU_NAME, res);
res = -ENODEV;
goto out_whoami_failed;
}
-#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
res = misc_register(&i2c_mpu_device);
if (res < 0) {
- printk("ERROR: misc_register returned %d\n", res);
+ dev_err(&this_client->adapter->dev,
+ "ERROR: misc_register returned %d\n", res);
goto out_misc_register_failed;
}
if (this_client->irq > 0) {
- printk("Installing irq using %d\n", this_client->irq);
+ dev_info(&this_client->adapter->dev,
+ "Installing irq using %d\n", this_client->irq);
res = mpuirq_init(this_client);
- if (res) {
+ if (res)
goto out_mpuirq_failed;
- }
} else {
- printk("WARNING: mpu3050 irq not assigned\n");
+ dev_warn(&this_client->adapter->dev,
+ "WARNING: %s irq not assigned\n", MPU_NAME);
}
- return res;
- out_mpuirq_failed:
- misc_deregister(&i2c_mpu_device);
- out_misc_register_failed:
#ifdef CONFIG_HAS_EARLYSUSPEND
- unregister_early_suspend(&mpu->early_suspend);
+ 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
- out_whoami_failed:
+ return res;
+
+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:
- printk(KERN_ERR "%s failed %d\n", __func__, res);
+out_alloc_data_failed:
+out_check_functionality_failed:
+ dev_err(&this_client->adapter->dev, "%s failed %d\n", __func__,
+ res);
return res;
}
@@ -767,23 +1074,52 @@ int mpu3050_probe(struct i2c_client *client, const struct i2c_device_id *devid)
static int mpu3050_remove(struct i2c_client *client)
{
struct mpu_private_data *mpu = i2c_get_clientdata(client);
- printk("%s\n", __func__);
+ 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;
- if (client->irq) {
- mpuirq_exit();
- }
+ 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__);
- misc_deregister(&i2c_mpu_device);
#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[] = {
- {"mpu3050", 0},
+ {MPU_NAME, 0},
{}
};
@@ -796,7 +1132,7 @@ static struct i2c_driver mpu3050_driver = {
.id_table = mpu3050_id,
.driver = {
.owner = THIS_MODULE,
- .name = "mpu3050",
+ .name = MPU_NAME,
},
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
.address_data = &addr_data,
@@ -813,16 +1149,17 @@ static struct i2c_driver mpu3050_driver = {
static int __init mpu_init(void)
{
int res = i2c_add_driver(&mpu3050_driver);
- printk("%s\n", __func__);
- if (res) {
- printk("%s failed\n", __func__);
- }
+ pid = 0;
+ printk(KERN_DEBUG "%s\n", __func__);
+ if (res)
+ dev_err(&this_client->adapter->dev, "%s failed\n",
+ __func__);
return res;
}
static void __exit mpu_exit(void)
{
- printk("%s\n", __func__);
+ printk(KERN_DEBUG "%s\n", __func__);
i2c_del_driver(&mpu3050_driver);
}
@@ -832,4 +1169,4 @@ module_exit(mpu_exit);
MODULE_AUTHOR("Invensense Corporation");
MODULE_DESCRIPTION("User space character device interface for MPU3050");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("mpu3050");
+MODULE_ALIAS(MPU_NAME);
diff --git a/drivers/misc/mpu3050/mpu-i2c.c b/drivers/misc/mpu3050/mpu-i2c.c
index ca21b42a9e95..b1298d313abf 100755..100644
--- a/drivers/misc/mpu3050/mpu-i2c.c
+++ b/drivers/misc/mpu3050/mpu-i2c.c
@@ -16,25 +16,23 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/***************************************************************************** *
- * $Id: mpu-i2c.c 3863 2010-10-08 22:05:31Z nroyer $
- ******************************************************************************/
+
/**
- * @defgroup
- * @brief
- *
- * @{
- * @file mpu-i2c.c
- * @brief
+ * @defgroup
+ * @brief
*
+ * @{
+ * @file mpu-i2c.c
+ * @brief
*
*/
#include <linux/i2c.h>
+#include "mpu.h"
int sensor_i2c_write(struct i2c_adapter *i2c_adap,
unsigned char address,
- unsigned int len, unsigned char *data)
+ unsigned int len, unsigned char const *data)
{
struct i2c_msg msgs[1];
int res;
@@ -44,15 +42,14 @@ int sensor_i2c_write(struct i2c_adapter *i2c_adap,
msgs[0].addr = address;
msgs[0].flags = 0; /* write */
- msgs[0].buf = (unsigned char *)data;
+ msgs[0].buf = (unsigned char *) data;
msgs[0].len = len;
res = i2c_transfer(i2c_adap, msgs, 1);
- if (res < 1) {
+ if (res < 1)
return res;
- } else {
+ else
return 0;
- }
}
int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
@@ -68,7 +65,8 @@ int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
int sensor_i2c_read(struct i2c_adapter *i2c_adap,
unsigned char address,
- unsigned char reg, unsigned int len, unsigned char *data)
+ unsigned char reg,
+ unsigned int len, unsigned char *data)
{
struct i2c_msg msgs[2];
int res;
@@ -87,11 +85,10 @@ int sensor_i2c_read(struct i2c_adapter *i2c_adap,
msgs[1].len = len;
res = i2c_transfer(i2c_adap, msgs, 2);
- if (res < 2) {
+ if (res < 2)
return res;
- } else {
+ else
return 0;
- }
}
int mpu_memory_read(struct i2c_adapter *i2c_adap,
@@ -109,13 +106,13 @@ int mpu_memory_read(struct i2c_adapter *i2c_adap,
if (NULL == data || NULL == i2c_adap)
return -EINVAL;
- bank[0] = 0x37; /*MPUREG_BANK_SEL; */
+ bank[0] = MPUREG_BANK_SEL;
bank[1] = mem_addr >> 8;
- addr[0] = 0x38; /*MPUREG_MEM_START_ADDR; */
+ addr[0] = MPUREG_MEM_START_ADDR;
addr[1] = mem_addr & 0xFF;
- buf = 0x39; /* MPUREG_MEM_R_W; */
+ buf = MPUREG_MEM_R_W;
/* Write Message */
msgs[0].addr = mpu_addr;
@@ -148,7 +145,7 @@ int mpu_memory_read(struct i2c_adapter *i2c_adap,
int mpu_memory_write(struct i2c_adapter *i2c_adap,
unsigned char mpu_addr,
unsigned short mem_addr,
- unsigned int len, unsigned char *data)
+ unsigned int len, unsigned char const *data)
{
unsigned char bank[2];
unsigned char addr[2];
@@ -162,13 +159,13 @@ int mpu_memory_write(struct i2c_adapter *i2c_adap,
if (len >= (sizeof(buf) - 1))
return -ENOMEM;
- bank[0] = 0x37; /*MPUREG_BANK_SEL; */
+ bank[0] = MPUREG_BANK_SEL;
bank[1] = mem_addr >> 8;
- addr[0] = 0x38; /*MPUREG_MEM_START_ADDR; */
+ addr[0] = MPUREG_MEM_START_ADDR;
addr[1] = mem_addr & 0xFF;
- buf[0] = 0x39; /* MPUREG_MEM_R_W; */
+ buf[0] = MPUREG_MEM_R_W;
memcpy(buf + 1, data, len);
/* Write Message */
@@ -184,7 +181,7 @@ int mpu_memory_write(struct i2c_adapter *i2c_adap,
msgs[2].addr = mpu_addr;
msgs[2].flags = 0;
- msgs[2].buf = (unsigned char *)buf;
+ msgs[2].buf = (unsigned char *) buf;
msgs[2].len = len + 1;
ret = i2c_transfer(i2c_adap, msgs, 3);
@@ -193,3 +190,7 @@ int mpu_memory_write(struct i2c_adapter *i2c_adap,
else
return 0;
}
+
+/**
+ * @}
+ */
diff --git a/drivers/misc/mpu3050/mpu-i2c.h b/drivers/misc/mpu3050/mpu-i2c.h
index ac3f7e93b695..0bbc8c64594e 100755..100644
--- a/drivers/misc/mpu3050/mpu-i2c.h
+++ b/drivers/misc/mpu3050/mpu-i2c.h
@@ -16,9 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
$
*/
-/***************************************************************************** *
- * $Id: mpu-i2c.h 3863 2010-10-08 22:05:31Z nroyer $
- ******************************************************************************/
/**
* @defgroup
* @brief
@@ -45,7 +42,8 @@ int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
int sensor_i2c_read(struct i2c_adapter *i2c_adap,
unsigned char address,
- unsigned char reg, unsigned int len, unsigned char *data);
+ unsigned char reg,
+ unsigned int len, unsigned char *data);
int mpu_memory_read(struct i2c_adapter *i2c_adap,
unsigned char mpu_addr,
@@ -57,4 +55,4 @@ int mpu_memory_write(struct i2c_adapter *i2c_adap,
unsigned short mem_addr,
unsigned int len, unsigned char const *data);
-#endif /* __MPU_I2C_H__ */
+#endif /* __MPU_I2C_H__ */
diff --git a/drivers/misc/mpu3050/mpuirq.c b/drivers/misc/mpu3050/mpuirq.c
index bf3c10f176fe..b6f21856cf32 100755..100644
--- a/drivers/misc/mpu3050/mpuirq.c
+++ b/drivers/misc/mpu3050/mpuirq.c
@@ -35,10 +35,10 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/wait.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
-#include "mpu3050.h"
+#include "mpu.h"
#include "mpuirq.h"
#include "mldl_cfg.h"
#include "mpu-i2c.h"
@@ -61,7 +61,7 @@ struct mpuirq_dev_data {
};
static struct mpuirq_dev_data mpuirq_dev_data;
-static struct mpuirq_data mpuirq_data;
+static struct irq_data mpuirq_data;
static char *interface = MPUIRQ_NAME;
static void mpu_accel_data_work_fcn(struct work_struct *work);
@@ -72,9 +72,9 @@ static int mpuirq_open(struct inode *inode, struct file *file)
"%s current->pid %d\n", __func__, current->pid);
mpuirq_dev_data.pid = current->pid;
file->private_data = &mpuirq_dev_data;
- /* we could do some checking on the flags supplied by "open"
- // i.e. O_NONBLOCK
- // -> set some flag to disable interruptible_sleep_on in mpuirq_read */
+ /* we could do some checking on the flags supplied by "open" */
+ /* i.e. O_NONBLOCK */
+ /* -> set some flag to disable interruptible_sleep_on in mpuirq_read */
return 0;
}
@@ -87,20 +87,22 @@ static int mpuirq_release(struct inode *inode, struct file *file)
/* read function called when from /dev/mpuirq is read */
static ssize_t mpuirq_read(struct file *file,
- char *buf, size_t count, loff_t * ppos)
+ 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.
+ 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;
}
@@ -117,18 +119,16 @@ static ssize_t mpuirq_read(struct file *file,
unsigned int mpuirq_poll(struct file *file, struct poll_table_struct *poll)
{
int mask = 0;
- struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
poll_wait(file, &mpuirq_wait, poll);
if (mpuirq_dev_data.data_ready)
mask |= POLLIN | POLLRDNORM;
- dev_dbg(p_mpuirq_dev_data->dev->this_device,
- "%s: returning %d\n", __func__, mask);
return mask;
}
/* ioctl - I/O control */
-static long mpuirq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long mpuirq_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
{
int retval = 0;
int data;
@@ -140,14 +140,14 @@ static long mpuirq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case MPUIRQ_GET_INTERRUPT_CNT:
data = mpuirq_data.interruptcount - 1;
- if (mpuirq_data.interruptcount > 1) {
+ if (mpuirq_data.interruptcount > 1)
mpuirq_data.interruptcount = 1;
- }
- if (copy_to_user((int *)arg, &data, sizeof(int)))
+
+ 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,
+ if (copy_to_user((int *) arg, &mpuirq_data.irqtime,
sizeof(mpuirq_data.irqtime)))
return -EFAULT;
mpuirq_data.irqtime = 0;
@@ -164,17 +164,20 @@ static long mpuirq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static void mpu_accel_data_work_fcn(struct work_struct *work)
{
struct mpuirq_dev_data *mpuirq_dev_data =
- (struct mpuirq_dev_data *)work;
+ (struct mpuirq_dev_data *) work;
struct mldl_cfg *mldl_cfg =
- (struct mldl_cfg *)i2c_get_clientdata(mpuirq_dev_data->mpu_client);
+ (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((mlsl_handle_t) accel_adapter,
- mldl_cfg->accel, &mldl_cfg->pdata->accel, rbuff);
+ mldl_cfg->accel->read(accel_adapter,
+ mldl_cfg->accel,
+ &mldl_cfg->pdata->accel, rbuff);
+
/* @todo add other data formats here as well */
if (EXT_SLAVE_BIG_ENDIAN == mldl_cfg->accel->endian) {
@@ -201,18 +204,20 @@ static irqreturn_t mpuirq_handler(int irq, void *dev_id)
mpuirq_data.interruptcount++;
- /* wake up (unblock) for reading data from userspace
- // and ignore first interrupt generated in module init */
+ /* wake up (unblock) for reading data from userspace */
+ /* and ignore first interrupt generated in module init */
if (mpuirq_data.interruptcount > 1) {
mpuirq_dev_data.data_ready = 1;
do_gettimeofday(&irqtime);
- mpuirq_data.irqtime = (((long long)irqtime.tv_sec) << 32);
+ 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));
+ (0 ==
+ (mycount % (mpuirq_dev_data.accel_divider + 1)))) {
+ schedule_work((struct work_struct
+ *) (&mpuirq_dev_data));
}
wake_up_interruptible(&mpuirq_wait);
@@ -223,7 +228,7 @@ static irqreturn_t mpuirq_handler(int irq, void *dev_id)
}
/* define which file operations are supported */
-struct file_operations mpuirq_fops = {
+const struct file_operations mpuirq_fops = {
.owner = THIS_MODULE,
.read = mpuirq_read,
.poll = mpuirq_poll,
@@ -249,10 +254,10 @@ int mpuirq_init(struct i2c_client *mpu_client)
int res;
struct mldl_cfg *mldl_cfg =
- (struct mldl_cfg *)i2c_get_clientdata(mpu_client);
+ (struct mldl_cfg *) i2c_get_clientdata(mpu_client);
/* work_struct initialization */
- INIT_WORK((struct work_struct *)&mpuirq_dev_data,
+ INIT_WORK((struct work_struct *) &mpuirq_dev_data,
mpu_accel_data_work_fcn);
mpuirq_dev_data.mpu_client = mpu_client;
@@ -268,7 +273,8 @@ int mpuirq_init(struct i2c_client *mpu_client)
if (mpuirq_dev_data.irq) {
unsigned long flags;
- if (BIT_ACTL_LOW == ((mldl_cfg->pdata->int_config) & BIT_ACTL))
+ if (BIT_ACTL_LOW ==
+ ((mldl_cfg->pdata->int_config) & BIT_ACTL))
flags = IRQF_TRIGGER_FALLING;
else
flags = IRQF_TRIGGER_RISING;
@@ -284,7 +290,8 @@ int mpuirq_init(struct i2c_client *mpu_client)
res = misc_register(&mpuirq_device);
if (res < 0) {
dev_err(&mpu_client->adapter->dev,
- "misc_register returned %d\n", res);
+ "misc_register returned %d\n",
+ res);
free_irq(mpuirq_dev_data.irq,
&mpuirq_dev_data.irq);
}
@@ -300,12 +307,13 @@ int mpuirq_init(struct i2c_client *mpu_client)
void mpuirq_exit(void)
{
/* Free the IRQ first before flushing the work */
- if (mpuirq_dev_data.irq > 0) {
+ 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);
+ dev_info(mpuirq_device.this_device, "Unregistering %s\n",
+ MPUIRQ_NAME);
misc_deregister(&mpuirq_device);
return;
diff --git a/drivers/misc/mpu3050/mpuirq.h b/drivers/misc/mpu3050/mpuirq.h
index 69b7eaad5717..70a2d35679f0 100755..100644
--- a/drivers/misc/mpu3050/mpuirq.h
+++ b/drivers/misc/mpu3050/mpuirq.h
@@ -32,14 +32,6 @@
#define MPUIRQ_SET_ACCEL_INFO (6)
#define MPUIRQ_SET_FREQUENCY_DIVIDER (7)
-struct mpuirq_data {
- int interruptcount;
- unsigned long long irqtime;
- int data_type;
- int data_size;
- void *data;
-};
-
#ifdef __KERNEL__
void mpuirq_exit(void);
diff --git a/drivers/misc/mpu3050/slaveirq.c b/drivers/misc/mpu3050/slaveirq.c
new file mode 100644
index 000000000000..3791868505ee
--- /dev/null
+++ b/drivers/misc/mpu3050/slaveirq.c
@@ -0,0 +1,272 @@
+/*
+ $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 <asm/uaccess.h>
+#include <asm/io.h>
+
+#include "mpu.h"
+#include "slaveirq.h"
+#include "mldl_cfg.h"
+#include "mpu-i2c.h"
+#include <linux/wait.h>
+#include <linux/slab.h>
+
+/* function which gets slave data and sends it to SLAVE */
+
+struct slaveirq_dev_data {
+ struct miscdevice dev;
+ struct i2c_client *slave_client;
+ struct irq_data data;
+ wait_queue_head_t slaveirq_wait;
+ int irq;
+ int pid;
+ int data_ready;
+ int timeout;
+};
+
+/* The following depends on patch fa1f68db6ca7ebb6fc4487ac215bffba06c01c28
+ * drivers: misc: pass miscdevice pointer via file private data
+ */
+static int slaveirq_open(struct inode *inode, struct file *file)
+{
+ /* Device node is availabe in the file->private_data, this is
+ * exactly what we want so we leave it there */
+ 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;
+}
+
+/* read function called when from /dev/slaveirq is read */
+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;
+}
+
+/* ioctl - I/O control */
+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++;
+
+ /* wake up (unblock) for reading data from userspace */
+ /* and ignore first interrupt generated in module init */
+ if (data->data.interruptcount > 1) {
+ 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;
+
+}
+
+/* define which file operations are supported */
+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;
+
+ 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;
+ }
+
+ init_waitqueue_head(&data->slaveirq_wait);
+ 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/misc/mpu3050/slaveirq.h b/drivers/misc/mpu3050/slaveirq.h
new file mode 100644
index 000000000000..ca9c7e496dab
--- /dev/null
+++ b/drivers/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