diff options
author | Wen Yi <wyi@nvidia.com> | 2011-01-28 14:38:45 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:46:33 -0800 |
commit | c2d4340aa561998b4afc87cd935c22f2c1b113f4 (patch) | |
tree | f30452f935159209ad025593eaf1db477942cd17 /drivers/misc | |
parent | df3ec81e193b55c04362ab2fbbf4611a4f41947c (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')
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, ®); 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, - ®); + result = + MLSLSerialRead(accel_handle, mldl_cfg->addr, + MPUREG_ACCEL_BURST_ADDR, 1, + ®); 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, ®); + result = + MLSLSerialRead(accel_handle, mldl_cfg->addr, + MPUREG_USER_CTRL, 1, ®); 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, + ®); + 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, ®); + 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 |