mod/add: add mpu support
authorliuji <liuji@rock-chips.com>
Mon, 8 Aug 2011 16:53:25 +0000 (00:53 +0800)
committerliuji <liuji@rock-chips.com>
Mon, 8 Aug 2011 16:53:25 +0000 (00:53 +0800)
48 files changed:
arch/arm/mach-rk29/board-rk29-ddr3sdk.c
arch/arm/mach-rk29/board-rk29sdk.c
drivers/misc/mpu3050/Kconfig [changed mode: 0644->0755]
drivers/misc/mpu3050/Makefile [changed mode: 0644->0755]
drivers/misc/mpu3050/README [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/adxl346.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/bma150.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/bma222.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/cma3000.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/kxsd9.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/kxtf9.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/lis331.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/lis3dh.c [new file with mode: 0755]
drivers/misc/mpu3050/accel/lsm303a.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/mantis.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/mma8450.c [changed mode: 0644->0755]
drivers/misc/mpu3050/accel/mma845x.c [new file with mode: 0755]
drivers/misc/mpu3050/compass/ak8975.c [changed mode: 0644->0755]
drivers/misc/mpu3050/compass/ami306.c [new file with mode: 0755]
drivers/misc/mpu3050/compass/ami30x.c [changed mode: 0644->0755]
drivers/misc/mpu3050/compass/hmc5883.c [changed mode: 0644->0755]
drivers/misc/mpu3050/compass/hscdtd002b.c [new file with mode: 0755]
drivers/misc/mpu3050/compass/hscdtd004a.c [new file with mode: 0755]
drivers/misc/mpu3050/compass/lsm303m.c [changed mode: 0644->0755]
drivers/misc/mpu3050/compass/mmc314x.c [changed mode: 0644->0755]
drivers/misc/mpu3050/compass/yas529-kernel.c [changed mode: 0644->0755]
drivers/misc/mpu3050/compass/yas530-kernel.c [new file with mode: 0755]
drivers/misc/mpu3050/compass/yas530.c [new file with mode: 0755]
drivers/misc/mpu3050/log.h [changed mode: 0644->0755]
drivers/misc/mpu3050/mldl_cfg.c [changed mode: 0644->0755]
drivers/misc/mpu3050/mldl_cfg.h [changed mode: 0644->0755]
drivers/misc/mpu3050/mlos-kernel.c [changed mode: 0644->0755]
drivers/misc/mpu3050/mlos.h [changed mode: 0644->0755]
drivers/misc/mpu3050/mlsl-kernel.c [changed mode: 0644->0755]
drivers/misc/mpu3050/mlsl.h [changed mode: 0644->0755]
drivers/misc/mpu3050/mltypes.h [changed mode: 0644->0755]
drivers/misc/mpu3050/mpu-dev.c [changed mode: 0644->0755]
drivers/misc/mpu3050/mpu-i2c.c [changed mode: 0644->0755]
drivers/misc/mpu3050/mpu-i2c.h [changed mode: 0644->0755]
drivers/misc/mpu3050/mpuirq.c [changed mode: 0644->0755]
drivers/misc/mpu3050/mpuirq.h [changed mode: 0644->0755]
drivers/misc/mpu3050/slaveirq.c [changed mode: 0644->0755]
drivers/misc/mpu3050/slaveirq.h [changed mode: 0644->0755]
drivers/misc/mpu3050/timerirq.c [new file with mode: 0755]
drivers/misc/mpu3050/timerirq.h [new file with mode: 0755]
include/linux/mpu.h [changed mode: 0644->0755]
include/linux/mpu3050.h [changed mode: 0644->0755]
include/linux/mpu6000.h [changed mode: 0644->0755]

index 6ffc986a3cdba38fe15c338a3fbefaac781df267..f4e883fa9feefb8e375a5d015052db2b834ae5d3 100755 (executable)
@@ -497,7 +497,55 @@ static struct mma8452_platform_data mma8452_info = {
 
 };
 #endif
-
+#if defined (CONFIG_MPU_SENSORS_MPU3050)
+/*mpu3050*/
+static struct mpu3050_platform_data mpu3050_data = {
+               .int_config = 0x10,
+               //.orientation = { 1, 0, 0,0, -1, 0,0, 0, 1 },
+               //.orientation = { 0, 1, 0,-1, 0, 0,0, 0, -1 },
+               //.orientation = { -1, 0, 0,0, -1, 0,0, 0, -1 },
+               .orientation = { 0, 1, 0, -1, 0, 0, 0, 0, 1 },
+               .level_shifter = 0,
+#if defined (CONFIG_MPU_SENSORS_KXTF9)
+               .accel = {
+#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE
+                               .get_slave_descr = NULL ,
+#else
+                               .get_slave_descr = get_accel_slave_descr ,                      
+#endif
+                               .adapt_num = 0, // The i2c bus to which the mpu device is
+                               // connected
+                               //.irq = RK29_PIN0_PA3,
+                               .bus = EXT_SLAVE_BUS_SECONDARY,  //The secondary I2C of MPU
+                               .address = 0x0f,
+                               //.orientation = { 1, 0, 0,0, 1, 0,0, 0, 1 },
+                               //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 },
+                               //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 },
+                               .orientation = { 0, 1 ,0, -1 ,0, 0, 0, 0, 1 },
+               },
+#endif
+#if defined (CONFIG_MPU_SENSORS_AK8975)
+               .compass = {
+#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE
+                               .get_slave_descr = NULL,/*ak5883_get_slave_descr,*/
+#else
+                               .get_slave_descr = get_compass_slave_descr,
+#endif                                         
+                               .adapt_num = 0, // The i2c bus to which the compass device is. 
+                               // It can be difference with mpu
+                               // connected
+                               //.irq = RK29_PIN0_PA4,
+                               .bus = EXT_SLAVE_BUS_PRIMARY,
+                               .address = 0x0d,
+                               //.orientation = { -1, 0, 0,0, -1, 0,0, 0, 1 },
+                               //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 },
+                               //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 },
+                               //.orientation = { 0, -1, 0, 1, 0, 0, 0, 0, 1 },
+                               .orientation = { 0, 1, 0, -1, 0, 0, 0, 0, 1 },
+               },
+};
+#endif
+#endif
 #if defined (CONFIG_BATTERY_BQ27510)
 #define        DC_CHECK_PIN    RK29_PIN4_PA1
 #define        LI_LION_BAT_NUM 2
@@ -730,6 +778,15 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = {
                .irq                    = RK29_PIN0_PA4,
        },
 #endif
+#if defined (CONFIG_MPU_SENSORS_MPU3050) 
+       {
+               .type                   = "mpu3050",
+               .addr                   = 0x68,
+               .flags                  = 0,
+               .irq                    = RK29_PIN5_PA3,
+               .platform_data  = &mpu3050_data,
+       },
+#endif
 };
 #endif
 
index 9c354ef55c2bd1180e958902ee663556d07ef0c4..064441f203b5d02617f223d077fe1c06143bb7da 100755 (executable)
@@ -502,7 +502,55 @@ static struct mma8452_platform_data mma8452_info = {
 
 };
 #endif
-
+#if defined (CONFIG_MPU_SENSORS_MPU3050)
+/*mpu3050*/
+static struct mpu3050_platform_data mpu3050_data = {
+               .int_config = 0x10,
+               //.orientation = { 1, 0, 0,0, -1, 0,0, 0, 1 },
+               //.orientation = { 0, 1, 0,-1, 0, 0,0, 0, -1 },
+               //.orientation = { -1, 0, 0,0, -1, 0,0, 0, -1 },
+               .orientation = { 0, 1, 0, -1, 0, 0, 0, 0, 1 },
+               .level_shifter = 0,
+#if defined (CONFIG_MPU_SENSORS_KXTF9)
+               .accel = {
+#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE
+                               .get_slave_descr = NULL ,
+#else
+                               .get_slave_descr = get_accel_slave_descr ,                      
+#endif
+                               .adapt_num = 0, // The i2c bus to which the mpu device is
+                               // connected
+                               //.irq = RK29_PIN0_PA3,
+                               .bus = EXT_SLAVE_BUS_SECONDARY,  //The secondary I2C of MPU
+                               .address = 0x0f,
+                               //.orientation = { 1, 0, 0,0, 1, 0,0, 0, 1 },
+                               //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 },
+                               //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 },
+                               .orientation = { 0, 1 ,0, -1 ,0, 0, 0, 0, 1 },
+               },
+#endif
+#if defined (CONFIG_MPU_SENSORS_AK8975)
+               .compass = {
+#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE
+                               .get_slave_descr = NULL,/*ak5883_get_slave_descr,*/
+#else
+                               .get_slave_descr = get_compass_slave_descr,
+#endif                                         
+                               .adapt_num = 0, // The i2c bus to which the compass device is. 
+                               // It can be difference with mpu
+                               // connected
+                               //.irq = RK29_PIN0_PA4,
+                               .bus = EXT_SLAVE_BUS_PRIMARY,
+                               .address = 0x0d,
+                               //.orientation = { -1, 0, 0,0, -1, 0,0, 0, 1 },
+                               //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 },
+                               //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 },
+                               //.orientation = { 0, -1, 0, 1, 0, 0, 0, 0, 1 },
+                               .orientation = { 0, 1, 0, -1, 0, 0, 0, 0, 1 },
+               },
+};
+#endif
+#endif
 #if defined (CONFIG_BATTERY_BQ27510)
 #define        DC_CHECK_PIN    RK29_PIN4_PA1
 #define        LI_LION_BAT_NUM 2
@@ -735,6 +783,16 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = {
                .irq                    = RK29_PIN0_PA4,
        },
 #endif
+/*mpu3050*/
+#if defined (CONFIG_MPU_SENSORS_MPU3050) 
+       {
+               .type                   = "mpu3050",
+               .addr                   = 0x68,
+               .flags                  = 0,
+               .irq                    = RK29_PIN5_PA3,
+               .platform_data  = &mpu3050_data,
+       },
+#endif
 };
 #endif
 
old mode 100644 (file)
new mode 100755 (executable)
index 69ee202..210953f
-\r
-menu "Motion Sensors Support"\r
-\r
-choice\r
-    tristate "Motion Processing Unit"\r
-    depends on I2C\r
-    default MPU_NONE\r
-\r
-config MPU_NONE\r
-    bool "None"\r
-    help\r
-      This disables support for motion processing using the MPU family of \r
-      motion processing units.\r
-\r
-config SENSORS_MPU3050\r
-    tristate "MPU3050"\r
-    depends on I2C\r
-    help\r
-      If you say yes here you get support for the MPU3050 Gyroscope driver\r
-      This driver can also be built as a module.  If so, the module\r
-      will be called mpu3050.\r
-\r
-config SENSORS_MPU6000\r
-    tristate "MPU6000"\r
-    depends on I2C\r
-    help\r
-      If you say yes here you get support for the MPU6000 Gyroscope driver\r
-      This driver can also be built as a module.  If so, the module\r
-      will be called mpu6000.\r
-\r
-endchoice\r
-\r
-choice\r
-    prompt "Accelerometer Type"\r
-    depends on SENSORS_MPU3050\r
-    default SENSORS_BMA150\r
-\r
-config SENSORS_ACCELEROMETER_NONE\r
-    bool "NONE"\r
-    depends on SENSORS_MPU3050 || SENSORS_MPU6000\r
-    help\r
-      This disables accelerometer support for the MPU3050\r
-\r
-config SENSORS_ADXL346\r
-    bool "ADI adxl346"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the ADI adxl346 accelerometer\r
-\r
-config SENSORS_BMA150\r
-    bool "Bosch BMA150"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Bosch BMA150 accelerometer\r
\r
-config SENSORS_BMA222\r
-    bool "Bosch BMA222"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Bosch BMA222 accelerometer\r
-      \r
-config SENSORS_KXSD9\r
-    bool "Kionix KXSD9"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Kionix KXSD9 accelerometer\r
-\r
-config SENSORS_KXTF9\r
-    bool "Kionix KXTF9"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Kionix KXFT9 accelerometer\r
-\r
-config SENSORS_LIS331DLH\r
-    bool "ST lis331dlh"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the ST lis331dlh accelerometer\r
-\r
-config SENSORS_LSM303DLHA\r
-    bool "ST lsm303dlh"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the ST lsm303dlh accelerometer\r
-\r
-config SENSORS_MMA8450\r
-    bool "Freescale mma8450"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Freescale mma8450 accelerometer\r
-\r
-config SENSORS_MMA8451\r
-    bool "Freescale mma8451"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Freescale mma8451 accelerometer\r
-\r
-endchoice\r
-\r
-choice\r
-    prompt "Compass Type"\r
-    depends on SENSORS_MPU6000 || SENSORS_MPU3050\r
-    default SENSORS_AK8975\r
-\r
-config SENSORS_COMPASS_NONE\r
-    bool "NONE"\r
-    depends on SENSORS_MPU6000 || SENSORS_MPU3050\r
-    help\r
-      This disables compass support for the MPU6000\r
-\r
-config SENSORS_AK8975\r
-    bool "AKM ak8975"\r
-    depends on SENSORS_MPU6000 || SENSORS_MPU3050\r
-    help\r
-      This enables support for the AKM ak8975 compass\r
-\r
-config SENSORS_MMC314X\r
-    bool "MEMSIC mmc314x"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the MEMSIC mmc314x compass\r
-\r
-config SENSORS_AMI30X\r
-    bool "Aichi Steel ami30X"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Aichi Steel ami304/ami305 compass\r
-\r
-config SENSORS_HMC5883\r
-    bool "Honeywell hmc5883"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Honeywell hmc5883 compass\r
-\r
-config SENSORS_LSM303DLHM\r
-    bool "ST lsm303dlh"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the ST lsm303dlh compass\r
-\r
-config SENSORS_MMC314X\r
-    bool "MEMSIC mmc314xMS"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the MEMSIC mmc314xMS compass\r
-\r
-config SENSORS_YAS529\r
-    bool "Yamaha yas529"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Yamaha yas529 compass\r
-\r
-config SENSORS_HSCDTD00XX\r
-    bool "Alps hscdtd00XX"\r
-    depends on SENSORS_MPU3050\r
-    help\r
-      This enables support for the Alps hscdtd002b/hscdtd004a compass\r
-\r
-endchoice\r
-\r
-choice\r
-    prompt "Pressure Type"\r
-    depends on SENSORS_MPU6000 || SENSORS_MPU3050\r
-    default SENSORS_BMA085\r
-\r
-config SENSORS_PRESSURE_NONE\r
-    bool "NONE"\r
-    depends on SENSORS_MPU6000 || SENSORS_MPU3050\r
-    help\r
-      This disables pressure sensor support for the MPU6000\r
-\r
-config SENSORS_BMA085\r
-    bool "Bosch BMA085"\r
-    depends on SENSORS_MPU6000 || SENSORS_MPU3050\r
-    help\r
-      This enables support for the Bosch bma085 pressure sensor\r
-\r
-endchoice\r
-\r
-config SENSORS_MPU_DEBUG\r
-    bool "MPU debug"\r
-    depends on SENSORS_MPU3050 || SENSORS_MPU6000\r
-    help\r
-      If you say yes here you get extra debug messages from the MPU3050\r
-      and other slave sensors.\r
-\r
-endmenu\r
-\r
+
+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 MPU_SENSORS_MPU3050
+    tristate "MPU3050"
+    depends on I2C
+    help
+      If you say yes here you get support for the MPU3050 Gyroscope driver
+      This driver can also be built as a module.  If so, the module
+      will be called mpu3050.
+
+config MPU_SENSORS_MPU6000
+    tristate "MPU6000"
+    depends on I2C
+    help
+      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"
+    depends on MPU_SENSORS_MPU3050
+    default MPU_SENSORS_BMA150
+
+config MPU_SENSORS_ACCELEROMETER_NONE
+    bool "NONE"
+    depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6000
+    help
+      This disables accelerometer support for the MPU3050
+
+config MPU_SENSORS_ADXL346
+    bool "ADI adxl346"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ADI adxl346 accelerometer
+
+config MPU_SENSORS_BMA150
+    bool "Bosch BMA150"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Bosch BMA150 accelerometer
+config MPU_SENSORS_BMA222
+    bool "Bosch BMA222"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Bosch BMA222 accelerometer
+      
+config MPU_SENSORS_KXSD9
+    bool "Kionix KXSD9"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Kionix KXSD9 accelerometer
+
+config MPU_SENSORS_KXTF9
+    bool "Kionix KXTF9"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Kionix KXFT9 accelerometer
+
+config MPU_SENSORS_LIS331DLH
+    bool "ST lis331dlh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lis331dlh accelerometer
+
+config MPU_SENSORS_LIS3DH
+    bool "ST lis3dh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lis3dh accelerometer
+
+config MPU_SENSORS_LSM303DLHA
+    bool "ST lsm303dlh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lsm303dlh accelerometer
+
+config MPU_SENSORS_MMA8450
+    bool "Freescale mma8450"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Freescale mma8450 accelerometer
+
+config MPU_SENSORS_MMA845X
+    bool "Freescale mma8451/8452/8453"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Freescale mma8451/8452/8453 accelerometer
+
+endchoice
+
+choice
+    prompt "Compass Type"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    default MPU_SENSORS_AK8975
+
+config MPU_SENSORS_COMPASS_NONE
+    bool "NONE"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    help
+      This disables compass support for the MPU6000
+
+config MPU_SENSORS_AK8975
+    bool "AKM ak8975"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    help
+      This enables support for the AKM ak8975 compass
+
+config MPU_SENSORS_MMC314X
+    bool "MEMSIC mmc314x"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the MEMSIC mmc314x compass
+
+config MPU_SENSORS_AMI30X
+    bool "Aichi Steel ami30X"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Aichi Steel ami304/ami305 compass
+
+config MPU_SENSORS_AMI306
+    bool "Aichi Steel ami306"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Aichi Steel ami306 compass
+
+config MPU_SENSORS_HMC5883
+    bool "Honeywell hmc5883"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Honeywell hmc5883 compass
+
+config MPU_SENSORS_LSM303DLHM
+    bool "ST lsm303dlh"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the ST lsm303dlh compass
+
+config MPU_SENSORS_MMC314X
+    bool "MEMSIC mmc314xMS"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the MEMSIC mmc314xMS compass
+
+config MPU_SENSORS_YAS529
+    bool "Yamaha yas529"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Yamaha yas529 compass
+
+config MPU_SENSORS_YAS530
+    bool "Yamaha yas530"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Yamaha yas530 compass
+
+config MPU_SENSORS_HSCDTD002B
+    bool "Alps hscdtd002b"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Alps hscdtd002b compass
+
+config MPU_SENSORS_HSCDTD004A
+    bool "Alps hscdtd004a"
+    depends on MPU_SENSORS_MPU3050
+    help
+      This enables support for the Alps hscdtd004a compass
+
+endchoice
+
+choice
+    prompt "Pressure Type"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    default MPU_SENSORS_BMA085
+
+config MPU_SENSORS_PRESSURE_NONE
+    bool "NONE"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    help
+      This disables pressure sensor support for the MPU6000
+
+config MPU_SENSORS_BMA085
+    bool "Bosch BMA085"
+    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
+    help
+      This enables support for the Bosch bma085 pressure sensor
+
+endchoice
+
+config MPU_SENSORS_TIMERIRQ
+    tristate "Timer IRQ"
+    help
+      If you say yes here you get access to the timerirq device handle which
+      can be used to select on.  This can be used instead of IRQ's, sleeping,
+      or timer threads.  Reading from this device returns the same type of
+      information as reading from the MPU and slave IRQ's.
+
+endmenu
+
old mode 100644 (file)
new mode 100755 (executable)
index 5114e43..935915a
-\r
-# Kernel makefile for motions sensors\r
-#\r
-# \r
-\r
-# MPU\r
-obj-$(CONFIG_SENSORS_MPU3050)  += mpu3050.o\r
-mpu3050-objs += mpuirq.o \\r
-       slaveirq.o \\r
-       mpu-dev.o \\r
-       mpu-i2c.o \\r
-       mlsl-kernel.o \\r
-       mlos-kernel.o \\r
-       $(MLLITE_DIR)mldl_cfg.o\r
-\r
-#\r
-# Accel options\r
-#\r
-ifdef CONFIG_SENSORS_ADXL346\r
-mpu3050-objs += $(MLLITE_DIR)accel/adxl346.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_BMA150\r
-mpu3050-objs += $(MLLITE_DIR)accel/bma150.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_BMA222\r
-mpu3050-objs += $(MLLITE_DIR)accel/bma222.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_KXSD9\r
-mpu3050-objs += $(MLLITE_DIR)accel/kxsd9.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_KXTF9\r
-mpu3050-objs += $(MLLITE_DIR)accel/kxtf9.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_LIS331DLH\r
-mpu3050-objs += $(MLLITE_DIR)accel/lis331.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_LSM303DLHA\r
-mpu3050-objs += $(MLLITE_DIR)accel/lsm303a.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_MMA8450\r
-mpu3050-objs += $(MLLITE_DIR)accel/mma8450.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_MMA8451\r
-mpu3050-objs += $(MLLITE_DIR)accel/mma8451.o\r
-endif\r
-\r
-#\r
-# Compass options\r
-#\r
-ifdef CONFIG_SENSORS_AK8975\r
-mpu3050-objs += $(MLLITE_DIR)compass/ak8975.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_AMI30X\r
-mpu3050-objs += $(MLLITE_DIR)compass/ami30x.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_HMC5883\r
-mpu3050-objs += $(MLLITE_DIR)compass/hmc5883.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_LSM303DLHM\r
-mpu3050-objs += $(MLLITE_DIR)compass/lsm303m.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_MMC314X\r
-mpu3050-objs += $(MLLITE_DIR)compass/mmc314x.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_YAS529\r
-mpu3050-objs += $(MLLITE_DIR)compass/yas529-kernel.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_HSCDTD00XX\r
-mpu3050-objs += $(MLLITE_DIR)compass/hscdtd00xx.o\r
-endif\r
-\r
-#\r
-# Pressure options\r
-#\r
-ifdef CONFIG_SENSORS_BMA085\r
-mpu3050-objs += $(MLLITE_DIR)pressure/bma085.o\r
-endif\r
-\r
-EXTRA_CFLAGS += -I$(M)/$(MLLITE_DIR) \\r
-                -I$(M)/../../include \\r
-               -Idrivers/misc/mpu3050 \\r
-                -Iinclude/linux\r
-\r
-ifdef CONFIG_SENSORS_MPU_DEBUG\r
-EXTRA_CFLAGS += -DDEBUG \r
-endif\r
-\r
-obj-$(CONFIG_SENSORS_MPU6000)= mpu6000.o\r
-mpu6000-objs += mpuirq.o \\r
-       mpu-dev.o \\r
-       mpu-i2c.o \\r
-       mlsl-kernel.o \\r
-       mlos-kernel.o \\r
-       $(MLLITE_DIR)mldl_cfg.o \\r
-       $(MLLITE_DIR)accel/mantis.o\r
-\r
-ifdef CONFIG_SENSORS_AK8975\r
-mpu6000-objs += $(MLLITE_DIR)compass/ak8975.o\r
-endif\r
-\r
-ifdef CONFIG_SENSORS_MPU6000\r
-EXTRA_CFLAGS += -DM_HW\r
-endif\r
+
+# Kernel makefile for motions sensors
+#
+# 
+
+# MPU
+obj-$(CONFIG_MPU_SENSORS_MPU3050)      += mpu3050.o
+mpu3050-objs += mpuirq.o \
+       slaveirq.o \
+       mpu-dev.o \
+       mpu-i2c.o \
+       mlsl-kernel.o \
+       mlos-kernel.o \
+       $(MLLITE_DIR)mldl_cfg.o
+
+#
+# Accel options
+#
+ifdef CONFIG_MPU_SENSORS_ADXL346
+mpu3050-objs += $(MLLITE_DIR)accel/adxl346.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_BMA150
+mpu3050-objs += $(MLLITE_DIR)accel/bma150.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_BMA222
+mpu3050-objs += $(MLLITE_DIR)accel/bma222.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_KXSD9
+mpu3050-objs += $(MLLITE_DIR)accel/kxsd9.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_KXTF9
+mpu3050-objs += $(MLLITE_DIR)accel/kxtf9.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LIS331DLH
+mpu3050-objs += $(MLLITE_DIR)accel/lis331.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LIS3DH
+mpu3050-objs += $(MLLITE_DIR)accel/lis3dh.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LSM303DLHA
+mpu3050-objs += $(MLLITE_DIR)accel/lsm303a.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MMA8450
+mpu3050-objs += $(MLLITE_DIR)accel/mma8450.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MMA845X
+mpu3050-objs += $(MLLITE_DIR)accel/mma845x.o
+endif
+
+#
+# Compass options
+#
+ifdef CONFIG_MPU_SENSORS_AK8975
+mpu3050-objs += $(MLLITE_DIR)compass/ak8975.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_AMI30X
+mpu3050-objs += $(MLLITE_DIR)compass/ami30x.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_AMI306
+mpu3050-objs += $(MLLITE_DIR)compass/ami306.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_HMC5883
+mpu3050-objs += $(MLLITE_DIR)compass/hmc5883.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_LSM303DLHM
+mpu3050-objs += $(MLLITE_DIR)compass/lsm303m.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MMC314X
+mpu3050-objs += $(MLLITE_DIR)compass/mmc314x.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_YAS529
+mpu3050-objs += $(MLLITE_DIR)compass/yas529-kernel.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_YAS530
+mpu3050-objs += $(MLLITE_DIR)compass/yas530.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_HSCDTD002B
+mpu3050-objs += $(MLLITE_DIR)compass/hscdtd002b.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_HSCDTD004A
+mpu3050-objs += $(MLLITE_DIR)compass/hscdtd004a.o
+endif
+#
+# Pressure options
+#
+ifdef CONFIG_MPU_SENSORS_BMA085
+mpu3050-objs += $(MLLITE_DIR)pressure/bma085.o
+endif
+
+EXTRA_CFLAGS += -I$(M)/$(MLLITE_DIR) \
+                -I$(M)/../../include \
+                               -Idrivers/misc/mpu3050 \
+                -Iinclude/linux
+
+obj-$(CONFIG_MPU_SENSORS_MPU6000)+= mpu6000.o
+mpu6000-objs += mpuirq.o \
+       slaveirq.o \
+       mpu-dev.o \
+       mpu-i2c.o \
+       mlsl-kernel.o \
+       mlos-kernel.o \
+       $(MLLITE_DIR)mldl_cfg.o \
+       $(MLLITE_DIR)accel/mantis.o
+
+ifdef CONFIG_MPU_SENSORS_AK8975
+mpu6000-objs += $(MLLITE_DIR)compass/ak8975.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MPU6000
+EXTRA_CFLAGS += -DM_HW
+endif
+
+obj-$(CONFIG_MPU_SENSORS_TIMERIRQ)+= timerirq.o
+
old mode 100644 (file)
new mode 100755 (executable)
index 2734dc1..047b6ba
@@ -108,7 +108,7 @@ should be modified for your platform.
 \r
 #include <linux/mpu.h>\r
 \r
-#if defined(CONFIG_SENSORS_MPU3050) || defined(CONFIG_SENSORS_MPU3050_MODULE)\r
+#if defined(CONFIG_MPU_SENSORS_MPU3050) || defined(CONFIG_MPU_SENSORS_MPU3050_MODULE)\r
 \r
 #define SENSOR_MPU_NAME "mpu3050"\r
 \r
@@ -119,7 +119,7 @@ static struct mpu3050_platform_data mpu_data = {
                           0,  0, -1 },\r
        /* accel */\r
        .accel = {\r
-#ifdef CONFIG_SENSORS_MPU3050_MODULE\r
+#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE\r
                 .get_slave_descr = NULL,\r
 #else\r
                 .get_slave_descr = get_accel_slave_descr,\r
@@ -133,7 +133,7 @@ static struct mpu3050_platform_data mpu_data = {
         },\r
        /* compass */\r
        .compass = {\r
-#ifdef CONFIG_SENSORS_MPU3050_MODULE\r
+#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE\r
                 .get_slave_descr = NULL,\r
 #else\r
                 .get_slave_descr = get_compass_slave_descr,\r
@@ -147,7 +147,7 @@ static struct mpu3050_platform_data mpu_data = {
         },\r
        /* pressure */\r
        .pressure = {\r
-#ifdef CONFIG_SENSORS_MPU3050_MODULE\r
+#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE\r
                 .get_slave_descr = NULL,\r
 #else\r
                 .get_slave_descr = get_pressure_slave_descr,\r
@@ -162,7 +162,7 @@ static struct mpu3050_platform_data mpu_data = {
 };\r
 #endif\r
 \r
-#if defined(CONFIG_SENSORS_MPU6000) || defined(CONFIG_SENSORS_MPU6000_MODULE)\r
+#if defined(CONFIG_MPU_SENSORS_MPU6000) || defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)\r
 \r
 #define SENSOR_MPU_NAME "mpu6000"\r
 \r
@@ -173,7 +173,7 @@ static struct mpu3050_platform_data mpu_data = {
                           0,  0, -1 },\r
        /* accel */\r
        .accel = {\r
-#ifdef CONFIG_SENSORS_MPU6000_MODULE\r
+#ifdef CONFIG_MPU_SENSORS_MPU6000_MODULE\r
                 .get_slave_descr = NULL,\r
 #else\r
                 .get_slave_descr = get_accel_slave_descr,\r
@@ -187,7 +187,7 @@ static struct mpu3050_platform_data mpu_data = {
         },\r
        /* compass */\r
        .compass = {\r
-#ifdef CONFIG_SENSORS_MPU6000_MODULE\r
+#ifdef CONFIG_MPU_SENSORS_MPU6000_MODULE\r
                 .get_slave_descr = NULL,\r
 #else\r
                 .get_slave_descr = get_compass_slave_descr,\r
@@ -201,7 +201,7 @@ static struct mpu3050_platform_data mpu_data = {
         },\r
        /* pressure */\r
        .pressure = {\r
-#ifdef CONFIG_SENSORS_MPU6000_MODULE\r
+#ifdef CONFIG_MPU_SENSORS_MPU6000_MODULE\r
                 .get_slave_descr = NULL,\r
 #else\r
                 .get_slave_descr = get_pressure_slave_descr,\r
@@ -234,6 +234,17 @@ done as well:
     gpio_request(MPU_GPIO_IRQ,"MPUIRQ");\r
     gpio_direction_input(MPU_GPIO_IRQ)\r
 \r
+NOTE:\r
+=====\r
+In previous releases, the sensors were defined using CONFIG_SENSORS_SENSORNAME convention. \r
+From this release onwards this convention will be changed to CONFIG_MPU_SENSORS_SENSORNAME. \r
+Please make note of this change.\r
+\r
+Dynamic Debug\r
+=============\r
+\r
+The mpu3050 makes use of dynamic debug.  For details on how to use this\r
+refer to Documentation/dynamic-debug-howto.txt\r
 \r
 Android File Permissions\r
 ========================\r
@@ -243,8 +254,17 @@ To set up the file permissions on an android system, the /dev/mpu and
 inside the perms_ structure.\r
 \r
 static struct perms_ devperms[] = {\r
-    { "/dev/mpu"           ,0640,   AID_SYSTEM,    AID_SYSTEM,     1 },\r
+    { "/dev/mpu"           ,0660,   AID_SYSTEM,    AID_SYSTEM,     1 },\r
 };\r
 \r
 Sufficient file permissions need to be give to read and write it by the system.\r
 \r
+For gingerbread and later the system/core/rootdir/ueventd.rc file needs to be\r
+modified with the appripriate lines added.\r
+\r
+# MPU sensors and IRQ\r
+/dev/mpu                  0660   system     system\r
+/dev/mpuirq               0660   system     system\r
+/dev/accelirq             0660   system     system\r
+/dev/compassirq           0660   system     system\r
+/dev/pressureirq          0660   system     system\r
old mode 100644 (file)
new mode 100755 (executable)
index 2f76313..14cb38a
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -116,7 +129,10 @@ int adxl346_read(void *mlsl_handle,
                 struct ext_slave_platform_data *pdata,
                 unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       return result;
 }
 
 struct ext_slave_descr adxl346_descr = {
@@ -126,6 +142,7 @@ struct ext_slave_descr adxl346_descr = {
        /*.resume           = */ adxl346_resume,
        /*.read             = */ adxl346_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "adx1346",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_ADI346,
old mode 100644 (file)
new mode 100755 (executable)
index f5e99d1..30fed15
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -61,7 +74,7 @@ static int bma150_resume(void *mlsl_handle,
        result =
            MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0a, 0x02);
        ERROR_CHECK(result);
-       MLOSSleep(10);
+       MLOSSleep(3);
 
        result =
            MLSLSerialRead(mlsl_handle, pdata->address, 0x14, 1, &reg);
@@ -95,7 +108,10 @@ static int bma150_read(void *mlsl_handle,
                       struct ext_slave_platform_data *pdata,
                       unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       return result;
 }
 
 static struct ext_slave_descr bma150_descr = {
@@ -105,6 +121,7 @@ static struct ext_slave_descr bma150_descr = {
        /*.resume           = */ bma150_resume,
        /*.read             = */ bma150_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "bma150",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_BMA150,
old mode 100644 (file)
new mode 100755 (executable)
index bd0c87c..534a1e5
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /*
@@ -95,7 +108,10 @@ static int bma222_read(void *mlsl_handle,
                       struct ext_slave_platform_data *pdata,
                       unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       return result;
 }
 
 static struct ext_slave_descr bma222_descr = {
@@ -105,6 +121,7 @@ static struct ext_slave_descr bma222_descr = {
        /*.resume           = */ bma222_resume,
        /*.read             = */ bma222_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "bma222",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_BMA222,
old mode 100644 (file)
new mode 100755 (executable)
index 8c6b3c8..0592595
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -65,7 +78,10 @@ int cma3000_read(void *mlsl_handle,
                 struct ext_slave_platform_data *pdata,
                 unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       return result;
 }
 
 struct ext_slave_descr cma3000_descr = {
old mode 100644 (file)
new mode 100755 (executable)
index 10ed3b2..77bc52c
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -44,7 +57,6 @@ static int kxsd9_suspend(void *mlsl_handle,
                         struct ext_slave_platform_data *pdata)
 {
        int result;
-       (void *) slave;
        /* CTRL_REGB: low-power standby mode */
        result =
            MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0d, 0x0);
@@ -99,7 +111,10 @@ static int kxsd9_read(void *mlsl_handle,
                      struct ext_slave_platform_data *pdata,
                      unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       return result;
 }
 
 static struct ext_slave_descr kxsd9_descr = {
@@ -109,6 +124,7 @@ static struct ext_slave_descr kxsd9_descr = {
        /*.resume           = */ kxsd9_resume,
        /*.read             = */ kxsd9_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "kxsd9",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_KXSD9,
old mode 100644 (file)
new mode 100755 (executable)
index 9eae342..e2490af
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -18,6 +31,9 @@
 /* - Include Files. - */
 /* ------------------ */
 
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 1
+
 #ifdef __KERNEL__
 #include <linux/module.h>
 #endif
 #undef MPL_LOG_TAG
 #define MPL_LOG_TAG "MPL-acc"
 
+#define KXTF9_XOUT_HPF_L                (0x00) /* 0000 0000 */
+#define KXTF9_XOUT_HPF_H                (0x01) /* 0000 0001 */
+#define KXTF9_YOUT_HPF_L                (0x02) /* 0000 0010 */
+#define KXTF9_YOUT_HPF_H                (0x03) /* 0000 0011 */
+#define KXTF9_ZOUT_HPF_L                (0x04) /* 0001 0100 */
+#define KXTF9_ZOUT_HPF_H                (0x05) /* 0001 0101 */
+#define KXTF9_XOUT_L                    (0x06) /* 0000 0110 */
+#define KXTF9_XOUT_H                    (0x07) /* 0000 0111 */
+#define KXTF9_YOUT_L                    (0x08) /* 0000 1000 */
+#define KXTF9_YOUT_H                    (0x09) /* 0000 1001 */
+#define KXTF9_ZOUT_L                    (0x0A) /* 0001 1010 */
+#define KXTF9_ZOUT_H                    (0x0B) /* 0001 1011 */
+#define KXTF9_ST_RESP                   (0x0C) /* 0000 1100 */
+#define KXTF9_WHO_AM_I                  (0x0F) /* 0000 1111 */
+#define KXTF9_TILT_POS_CUR              (0x10) /* 0001 0000 */
+#define KXTF9_TILT_POS_PRE              (0x11) /* 0001 0001 */
+#define KXTF9_INT_SRC_REG1              (0x15) /* 0001 0101 */
+#define KXTF9_INT_SRC_REG2              (0x16) /* 0001 0110 */
+#define KXTF9_STATUS_REG                (0x18) /* 0001 1000 */
+#define KXTF9_INT_REL                   (0x1A) /* 0001 1010 */
+#define KXTF9_CTRL_REG1                 (0x1B) /* 0001 1011 */
+#define KXTF9_CTRL_REG2                 (0x1C) /* 0001 1100 */
+#define KXTF9_CTRL_REG3                 (0x1D) /* 0001 1101 */
+#define KXTF9_INT_CTRL_REG1             (0x1E) /* 0001 1110 */
+#define KXTF9_INT_CTRL_REG2             (0x1F) /* 0001 1111 */
+#define KXTF9_INT_CTRL_REG3             (0x20) /* 0010 0000 */
+#define KXTF9_DATA_CTRL_REG             (0x21) /* 0010 0001 */
+#define KXTF9_TILT_TIMER                (0x28) /* 0010 1000 */
+#define KXTF9_WUF_TIMER                 (0x29) /* 0010 1001 */
+#define KXTF9_TDT_TIMER                 (0x2B) /* 0010 1011 */
+#define KXTF9_TDT_H_THRESH              (0x2C) /* 0010 1100 */
+#define KXTF9_TDT_L_THRESH              (0x2D) /* 0010 1101 */
+#define KXTF9_TDT_TAP_TIMER             (0x2E) /* 0010 1110 */
+#define KXTF9_TDT_TOTAL_TIMER           (0x2F) /* 0010 1111 */
+#define KXTF9_TDT_LATENCY_TIMER         (0x30) /* 0011 0000 */
+#define KXTF9_TDT_WINDOW_TIMER          (0x31) /* 0011 0001 */
+#define KXTF9_WUF_THRESH                (0x5A) /* 0101 1010 */
+#define KXTF9_TILT_ANGLE                (0x5C) /* 0101 1100 */
+#define KXTF9_HYST_SET                  (0x5F) /* 0101 1111 */
+
+#define KXTF9_MAX_DUR (0xFF)
+#define KXTF9_MAX_THS (0xFF)
+#define KXTF9_THS_COUNTS_P_G (32)
+
 /* --------------------- */
 /* -    Variables.     - */
 /* --------------------- */
 
+struct kxtf9_config {
+       unsigned int odr; /* Output data rate mHz */
+       unsigned int fsr; /* full scale range mg */
+       unsigned int ths; /* Motion no-motion thseshold mg */
+       unsigned int dur; /* Motion no-motion duration ms */
+       unsigned int irq_type;
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char reg_odr;
+       unsigned char reg_int_cfg1;
+       unsigned char reg_int_cfg2;
+       unsigned char ctrl_reg1;
+};
+
+struct kxtf9_private_data {
+       struct kxtf9_config suspend;
+       struct kxtf9_config resume;
+};
+
 /*****************************************
     Accelerometer Initialization Functions
 *****************************************/
 
+static int kxtf9_set_ths(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct kxtf9_config *config,
+                       int apply,
+                       long ths)
+{
+       int result = ML_SUCCESS;
+       if ((ths * KXTF9_THS_COUNTS_P_G / 1000) > KXTF9_MAX_THS)
+               ths = (KXTF9_MAX_THS * 1000) / KXTF9_THS_COUNTS_P_G;
+
+       if (ths < 0)
+               ths = 0;
+
+       config->ths = ths;
+       config->reg_ths = (unsigned char)
+               ((long)(ths * KXTF9_THS_COUNTS_P_G) / 1000);
+       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_WUF_THRESH,
+                                       config->reg_ths);
+       return result;
+}
+
+static int kxtf9_set_dur(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct kxtf9_config *config,
+                       int apply,
+                       long dur)
+{
+       int result = ML_SUCCESS;
+       long reg_dur = (dur * config->odr) / 1000000;
+       config->dur = dur;
+
+       if (reg_dur > KXTF9_MAX_DUR)
+               reg_dur = KXTF9_MAX_DUR;
+
+       config->reg_dur = (unsigned char) reg_dur;
+       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_WUF_TIMER,
+                                       (unsigned char)reg_dur);
+       return result;
+}
+
+/**
+ * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
+ * duration will not be used uless the type is MOT or NMOT.
+ *
+ * @param config configuration to apply to, suspend or resume
+ * @param irq_type The type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ */
+static int kxtf9_set_irq(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct kxtf9_config *config,
+                       int apply,
+                       long irq_type)
+{
+       int result = ML_SUCCESS;
+       struct kxtf9_private_data *private_data = pdata->private_data;
+
+       config->irq_type = (unsigned char)irq_type;
+       config->ctrl_reg1 &= ~0x22;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               config->ctrl_reg1 |= 0x20;
+               config->reg_int_cfg1 = 0x38;
+               config->reg_int_cfg2 = 0x00;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               config->ctrl_reg1 |= 0x02;
+               if ((unsigned long) config ==
+                       (unsigned long) &private_data->suspend)
+                       config->reg_int_cfg1 = 0x34;
+               else
+                       config->reg_int_cfg1 = 0x24;
+               config->reg_int_cfg2 = 0xE0;
+       } else {
+               config->reg_int_cfg1 = 0x00;
+               config->reg_int_cfg2 = 0x00;
+       }
+
+       if (apply) {
+               /* Must clear bit 7 before writing new configuration */
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_CTRL_REG1, 0x40);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_INT_CTRL_REG1,
+                                       config->reg_int_cfg1);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_INT_CTRL_REG2,
+                                       config->reg_int_cfg2);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_CTRL_REG1,
+                                       config->ctrl_reg1);
+       }
+       MPL_LOGV("CTRL_REG1: %lx, INT_CFG1: %lx, INT_CFG2: %lx\n",
+               (unsigned long)config->ctrl_reg1,
+               (unsigned long)config->reg_int_cfg1,
+               (unsigned long)config->reg_int_cfg2);
+
+       return result;
+}
+
+/**
+ * Set the Output data rate for the particular configuration
+ *
+ * @param config Config to modify with new ODR
+ * @param odr Output data rate in units of 1/1000Hz
+ */
+static int kxtf9_set_odr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct kxtf9_config *config,
+                       int apply,
+                       long odr)
+{
+       unsigned char bits;
+       int result = ML_SUCCESS;
+
+       /* Data sheet says there is 12.5 hz, but that seems to produce a single
+        * correct data value, thus we remove it from the table */
+       if (odr > 400000) {
+               config->odr = 800000;
+               bits = 0x06;
+       } else if (odr > 200000) {
+               config->odr = 400000;
+               bits = 0x05;
+       } else if (odr > 100000) {
+               config->odr = 200000;
+               bits = 0x04;
+       } else if (odr > 50000) {
+               config->odr = 100000;
+               bits = 0x03;
+       } else if (odr > 25000) {
+               config->odr = 50000;
+               bits = 0x02;
+       } else if (odr != 0) {
+               config->odr = 25000;
+               bits = 0x01;
+       } else {
+               config->odr = 0;
+               bits = 0;
+       }
+
+       if (odr != 0)
+               config->ctrl_reg1 |= 0x80;
+
+       config->reg_odr = bits;
+       kxtf9_set_dur(mlsl_handle, pdata,
+               config, apply, config->dur);
+       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       if (apply) {
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_DATA_CTRL_REG,
+                                       config->reg_odr);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_CTRL_REG1,
+                                       0x40);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_CTRL_REG1,
+                                       config->ctrl_reg1);
+       }
+       return result;
+}
+
+/**
+ * Set the full scale range of the accels
+ *
+ * @param config pointer to configuration
+ * @param fsr requested full scale range
+ */
+static int kxtf9_set_fsr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct kxtf9_config *config,
+                       int apply,
+                       long fsr)
+{
+       int result = ML_SUCCESS;
+
+       config->ctrl_reg1 = (config->ctrl_reg1 & 0xE7);
+       if (fsr <= 2000) {
+               config->fsr = 2000;
+               config->ctrl_reg1 |= 0x00;
+       } else if (fsr <= 4000) {
+               config->fsr = 4000;
+               config->ctrl_reg1 |= 0x08;
+       } else {
+               config->fsr = 8000;
+               config->ctrl_reg1 |= 0x10;
+       }
+
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply) {
+               /* Must clear bit 7 before writing new configuration */
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_CTRL_REG1, 0x40);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       KXTF9_CTRL_REG1, config->ctrl_reg1);
+       }
+       return result;
+}
+
 static int kxtf9_suspend(void *mlsl_handle,
                         struct ext_slave_descr *slave,
                         struct ext_slave_platform_data *pdata)
 {
        int result;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, 0);
+       unsigned char data;
+       struct kxtf9_private_data *private_data = pdata->private_data;
+
+       /* Wake up */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_CTRL_REG1, 0x40);
+       ERROR_CHECK(result);
+       /* INT_CTRL_REG1: */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_INT_CTRL_REG1,
+                               private_data->suspend.reg_int_cfg1);
+       ERROR_CHECK(result);
+       /* WUF_THRESH: */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_WUF_THRESH,
+                               private_data->suspend.reg_ths);
        ERROR_CHECK(result);
+       /* DATA_CTRL_REG */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_DATA_CTRL_REG,
+                               private_data->suspend.reg_odr);
+       ERROR_CHECK(result);
+       /* WUF_TIMER */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_WUF_TIMER, private_data->suspend.reg_dur);
+       ERROR_CHECK(result);
+
+       /* Normal operation  */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_CTRL_REG1,
+                               private_data->suspend.ctrl_reg1);
+       ERROR_CHECK(result);
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               KXTF9_INT_REL, 1, &data);
+       ERROR_CHECK(result);
+
        return result;
 }
 
@@ -58,53 +374,245 @@ static int kxtf9_resume(void *mlsl_handle,
                        struct ext_slave_platform_data *pdata)
 {
        int result = ML_SUCCESS;
-       unsigned char reg;
+       unsigned char data;
+       struct kxtf9_private_data *private_data = pdata->private_data;
 
-       /* RAM reset */
-       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,
+                               KXTF9_CTRL_REG1, 0x40);
        ERROR_CHECK(result);
        /* INT_CTRL_REG1: */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1e, 0x14);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_INT_CTRL_REG1,
+                               private_data->resume.reg_int_cfg1);
        ERROR_CHECK(result);
        /* WUF_THRESH: */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x5a, 0x00);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_WUF_THRESH, private_data->resume.reg_ths);
        ERROR_CHECK(result);
        /* DATA_CTRL_REG */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x21, 0x04);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_DATA_CTRL_REG,
+                               private_data->resume.reg_odr);
        ERROR_CHECK(result);
        /* WUF_TIMER */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x29, 0x02);
-       ERROR_CHECK(result);
-
-       /* Full Scale */
-       reg = 0xc2;
-       reg &= ~ACCEL_KIONIX_CTRL_MASK;
-       reg |= 0x00;
-       if (slave->range.mantissa == 4)
-               reg |= 0x08;
-       else if (slave->range.mantissa == 8)
-               reg |= 0x10;
-       else {
-               slave->range.mantissa = 2;
-               reg |= 0x00;
-       }
-       slave->range.fraction = 0;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_WUF_TIMER, private_data->resume.reg_dur);
+       ERROR_CHECK(result);
 
        /* Normal operation  */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1b, reg);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_CTRL_REG1,
+                               private_data->resume.ctrl_reg1);
+       ERROR_CHECK(result);
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               KXTF9_INT_REL, 1, &data);
        ERROR_CHECK(result);
-       MLOSSleep(50);
+
+       return ML_SUCCESS;
+}
+
+static int kxtf9_init(void *mlsl_handle,
+               struct ext_slave_descr *slave,
+               struct ext_slave_platform_data *pdata)
+{
+
+       struct kxtf9_private_data *private_data;
+       int result = ML_SUCCESS;
+
+       private_data = (struct kxtf9_private_data *)
+               MLOSMalloc(sizeof(struct kxtf9_private_data));
+
+       if (!private_data)
+               return ML_ERROR_MEMORY_EXAUSTED;
+
+       /* RAM reset */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_CTRL_REG1,
+                               0x40); /* Fastest Reset */
+       ERROR_CHECK(result);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_DATA_CTRL_REG,
+                               0x36); /* Fastest Reset */
+       ERROR_CHECK(result);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               KXTF9_CTRL_REG3, 0xcd); /* Reset */
+       ERROR_CHECK(result);
+       MLOSSleep(2);
+
+       pdata->private_data = private_data;
+
+       private_data->resume.ctrl_reg1 = 0xC0;
+       private_data->suspend.ctrl_reg1 = 0x40;
+
+       result = kxtf9_set_dur(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 1000);
+       ERROR_CHECK(result);
+       result = kxtf9_set_dur(mlsl_handle, pdata, &private_data->resume,
+                       FALSE,  2540);
+       ERROR_CHECK(result);
+
+       result = kxtf9_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 50000);
+       ERROR_CHECK(result);
+       result = kxtf9_set_odr(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 200000);
+
+       result = kxtf9_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 2000);
+       ERROR_CHECK(result);
+       result = kxtf9_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 2000);
+       ERROR_CHECK(result);
+
+       result = kxtf9_set_ths(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 80);
+       ERROR_CHECK(result);
+       result = kxtf9_set_ths(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 40);
+       ERROR_CHECK(result);
+
+       result = kxtf9_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
+       ERROR_CHECK(result);
+       result = kxtf9_set_irq(mlsl_handle, pdata, &private_data->resume,
+                       FALSE,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
+       ERROR_CHECK(result);
+       return result;
+}
+
+static int kxtf9_exit(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       if (pdata->private_data)
+               return MLOSFree(pdata->private_data);
+       else
+               return ML_SUCCESS;
+}
+
+static int kxtf9_config(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config *data)
+{
+       struct kxtf9_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return kxtf9_set_odr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return kxtf9_set_odr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return kxtf9_set_fsr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return kxtf9_set_fsr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return kxtf9_set_ths(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return kxtf9_set_ths(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return kxtf9_set_dur(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return kxtf9_set_dur(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return kxtf9_set_irq(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return kxtf9_set_irq(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return ML_SUCCESS;
+}
+
+static int kxtf9_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct kxtf9_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
+               break;
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
 
        return ML_SUCCESS;
 }
@@ -114,16 +622,29 @@ static int kxtf9_read(void *mlsl_handle,
                      struct ext_slave_platform_data *pdata,
                      unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       unsigned char reg;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               KXTF9_INT_SRC_REG2, 1, &reg);
+       ERROR_CHECK(result);
+
+       if (!(reg & 0x10))
+               return ML_ERROR_ACCEL_DATA_NOT_READY;
+
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       ERROR_CHECK(result);
+       return result;
 }
 
 static struct ext_slave_descr kxtf9_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
+       /*.init             = */ kxtf9_init,
+       /*.exit             = */ kxtf9_exit,
        /*.suspend          = */ kxtf9_suspend,
        /*.resume           = */ kxtf9_resume,
        /*.read             = */ kxtf9_read,
-       /*.config           = */ NULL,
+       /*.config           = */ kxtf9_config,
+       /*.get_config       = */ kxtf9_get_config,
        /*.name             = */ "kxtf9",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_KXTF9,
old mode 100644 (file)
new mode 100755 (executable)
index b98dbc6..53c599b
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -18,6 +31,9 @@
 /* - Include Files. - */
 /* ------------------ */
 
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 1
+
 #ifdef __KERNEL__
 #include <linux/module.h>
 #endif
@@ -73,6 +89,8 @@ struct lis331dlh_config {
        unsigned char reg_ths;
        unsigned char reg_dur;
        unsigned char ctrl_reg1;
+       unsigned char irq_type;
+       unsigned char mot_int1_cfg;
 };
 
 struct lis331dlh_private_data {
@@ -85,23 +103,36 @@ struct lis331dlh_private_data {
     Accelerometer Initialization Functions
 *****************************************/
 
-void lis331dlh_set_ths(struct lis331dlh_config *config,
-               long ths)
+static int lis331dlh_set_ths(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis331dlh_config *config,
+                       int apply,
+                       long ths)
 {
-       if ((unsigned int) ths > 1000 * config->fsr)
-               ths = (long) 1000 * config->fsr;
+       int result = ML_SUCCESS;
+       if ((unsigned int) ths >= config->fsr)
+               ths = (long) config->fsr - 1;
 
        if (ths < 0)
                ths = 0;
 
        config->ths = ths;
        config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
-       MPL_LOGD("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS331_INT1_THS,
+                                       config->reg_ths);
+       return result;
 }
 
-void lis331dlh_set_dur(struct lis331dlh_config *config,
-               long dur)
+static int lis331dlh_set_dur(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis331dlh_config *config,
+                       int apply,
+                       long dur)
 {
+       int result = ML_SUCCESS;
        long reg_dur = (dur * config->odr) / 1000000L;
        config->dur = dur;
 
@@ -109,7 +140,54 @@ void lis331dlh_set_dur(struct lis331dlh_config *config,
                reg_dur = LIS331_MAX_DUR;
 
        config->reg_dur = (unsigned char) reg_dur;
-       MPL_LOGD("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS331_INT1_DURATION,
+                                       (unsigned char)reg_dur);
+       return result;
+}
+
+/**
+ * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
+ * duration will not be used uless the type is MOT or NMOT.
+ *
+ * @param config configuration to apply to, suspend or resume
+ * @param irq_type The type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ */
+static int lis331dlh_set_irq(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis331dlh_config *config,
+                       int apply,
+                       long irq_type)
+{
+       int result = ML_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+
+       config->irq_type = (unsigned char)irq_type;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = config->mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+
+       if (apply) {
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS331_CTRL_REG3, reg1);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS331_INT1_CFG, reg2);
+       }
+
+       return result;
 }
 
 /**
@@ -118,11 +196,14 @@ void lis331dlh_set_dur(struct lis331dlh_config *config,
  * @param config Config to modify with new ODR
  * @param odr Output data rate in units of 1/1000Hz
  */
-static void lis331dlh_set_odr(
-       struct lis331dlh_config *config,
-       long odr)
+static int lis331dlh_set_odr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis331dlh_config *config,
+                       int apply,
+                       long odr)
 {
        unsigned char bits;
+       int result = ML_SUCCESS;
 
        if (odr > 400000) {
                config->odr = 1000000;
@@ -157,31 +238,58 @@ static void lis331dlh_set_odr(
        }
 
        config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0x7);
-       lis331dlh_set_dur(config, config->dur);
-       MPL_LOGD("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       lis331dlh_set_dur(mlsl_handle, pdata,
+                       config, apply, config->dur);
+       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS331_CTRL_REG1,
+                                       config->ctrl_reg1);
+       return result;
 }
 
-static void lis331dlh_set_fsr(
-       struct lis331dlh_config *config,
-       long fsr)
+/**
+ * Set the full scale range of the accels
+ *
+ * @param config pointer to configuration
+ * @param fsr requested full scale range
+ */
+static int lis331dlh_set_fsr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis331dlh_config *config,
+                       int apply,
+                       long fsr)
 {
-       if (fsr <= 2048)
+       unsigned char reg1 = 0x40;
+       int result = ML_SUCCESS;
+
+       if (fsr <= 2048) {
                config->fsr = 2048;
-       else if (fsr <= 4096)
+       } else if (fsr <= 4096) {
+               reg1 |= 0x30;
                config->fsr = 4096;
-       else
+       } else {
+               reg1 |= 0x10;
                config->fsr = 8192;
+       }
+
+       lis331dlh_set_ths(mlsl_handle, pdata,
+                       config, apply, config->ths);
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS331_CTRL_REG4, reg1);
 
-       lis331dlh_set_ths(config, config->ths);
-       MPL_LOGD("FSR: %d\n", config->fsr);
+       return result;
 }
 
-int lis331dlh_suspend(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata)
+static int lis331dlh_suspend(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata)
 {
-       int result;
-       unsigned char reg;
+       int result = ML_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
        struct lis331dlh_private_data *private_data = pdata->private_data;
 
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
@@ -190,36 +298,49 @@ int lis331dlh_suspend(void *mlsl_handle,
 
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
                                       LIS331_CTRL_REG2, 0x0f);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG3, 0x00);
-       reg = 0x40;
+       reg1 = 0x40;
        if (private_data->suspend.fsr == 8192)
-               reg |= 0x30;
+               reg1 |= 0x30;
        else if (private_data->suspend.fsr == 4096)
-               reg |= 0x10;
+               reg1 |= 0x10;
        /* else bits [4..5] are already zero */
 
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG4, reg);
+                                      LIS331_CTRL_REG4, reg1);
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
                                       LIS331_INT1_THS,
                                       private_data->suspend.reg_ths);
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
                                       LIS331_INT1_DURATION,
                                       private_data->suspend.reg_dur);
+
+       if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (private_data->suspend.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = private_data->suspend.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS331_CTRL_REG3, reg1);
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_CFG, 0x2a);
+                                      LIS331_INT1_CFG, reg2);
        result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS331_HP_FILTER_RESET, 1, &reg);
+                               LIS331_HP_FILTER_RESET, 1, &reg1);
        return result;
 }
 
-int lis331dlh_resume(void *mlsl_handle,
-                    struct ext_slave_descr *slave,
-                    struct ext_slave_platform_data *pdata)
+static int lis331dlh_resume(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata)
 {
        int result = ML_SUCCESS;
-       unsigned char reg;
+       unsigned char reg1;
+       unsigned char reg2;
        struct lis331dlh_private_data *private_data = pdata->private_data;
 
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
@@ -229,45 +350,66 @@ int lis331dlh_resume(void *mlsl_handle,
        MLOSSleep(6);
 
        /* Full Scale */
-       reg = 0x40;
-       reg &= ~LIS331_CTRL_MASK;
+       reg1 = 0x40;
        if (private_data->resume.fsr == 8192)
-               reg |= 0x30;
+               reg1 |= 0x30;
        else if (private_data->resume.fsr == 4096)
-               reg |= 0x10;
+               reg1 |= 0x10;
 
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG4, reg);
+                                      LIS331_CTRL_REG4, reg1);
        ERROR_CHECK(result);
 
        /* Configure high pass filter */
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
                                       LIS331_CTRL_REG2, 0x0F);
        ERROR_CHECK(result);
+
+       if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (private_data->resume.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = private_data->resume.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG3, 0x00);
+                                      LIS331_CTRL_REG3, reg1);
        ERROR_CHECK(result);
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_THS, 0x02);
+                                      LIS331_INT1_THS,
+                                      private_data->resume.reg_ths);
        ERROR_CHECK(result);
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_DURATION, 0x7F);
+                                      LIS331_INT1_DURATION,
+                                      private_data->resume.reg_dur);
        ERROR_CHECK(result);
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_CFG, 0x95);
+                                      LIS331_INT1_CFG, reg2);
        ERROR_CHECK(result);
        result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS331_HP_FILTER_RESET, 1, &reg);
+                               LIS331_HP_FILTER_RESET, 1, &reg1);
        ERROR_CHECK(result);
        return result;
 }
 
-int lis331dlh_read(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata,
-                  unsigned char *data)
+static int lis331dlh_read(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result = ML_SUCCESS;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               LIS331_STATUS_REG, 1, data);
+       if (data[0] & 0x0F) {
+               result = MLSLSerialRead(mlsl_handle, pdata->address,
+                                       slave->reg, slave->len, data);
+               return result;
+       } else
+               return ML_ERROR_ACCEL_DATA_NOT_READY;
 }
 
 static int lis331dlh_init(void *mlsl_handle,
@@ -285,15 +427,31 @@ static int lis331dlh_init(void *mlsl_handle,
 
        private_data->resume.ctrl_reg1 = 0x37;
        private_data->suspend.ctrl_reg1 = 0x47;
-
-       lis331dlh_set_odr(&private_data->suspend, 50000);
-       lis331dlh_set_odr(&private_data->resume, 200000);
-       lis331dlh_set_fsr(&private_data->suspend, 2048);
-       lis331dlh_set_fsr(&private_data->resume, 2048);
-       lis331dlh_set_ths(&private_data->suspend, 80);
-       lis331dlh_set_ths(&private_data->resume, 40);
-       lis331dlh_set_dur(&private_data->suspend, 1000);
-       lis331dlh_set_dur(&private_data->resume,  2540);
+       private_data->resume.mot_int1_cfg = 0x95;
+       private_data->suspend.mot_int1_cfg = 0x2a;
+
+       lis331dlh_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 0);
+       lis331dlh_set_odr(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 200000);
+       lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 2048);
+       lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 2048);
+       lis331dlh_set_ths(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 80);
+       lis331dlh_set_ths(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 40);
+       lis331dlh_set_dur(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 1000);
+       lis331dlh_set_dur(mlsl_handle, pdata, &private_data->resume,
+                       FALSE,  2540);
+       lis331dlh_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
+       lis331dlh_set_irq(mlsl_handle, pdata, &private_data->resume,
+                       FALSE,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
        return ML_SUCCESS;
 }
 
@@ -318,36 +476,111 @@ static int lis331dlh_config(void *mlsl_handle,
 
        switch (data->key) {
        case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               lis331dlh_set_odr(&private_data->suspend,
-                               *((long *)data->data));
+               return lis331dlh_set_odr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return lis331dlh_set_odr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return lis331dlh_set_fsr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return lis331dlh_set_fsr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return lis331dlh_set_ths(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return lis331dlh_set_ths(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return lis331dlh_set_dur(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return lis331dlh_set_dur(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return lis331dlh_set_irq(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return lis331dlh_set_irq(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return ML_SUCCESS;
+}
+
+static int lis331dlh_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct lis331dlh_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
                break;
        case MPU_SLAVE_CONFIG_ODR_RESUME:
-               lis331dlh_set_odr(&private_data->resume,
-                               *((long *)data->data));
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
                break;
        case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               lis331dlh_set_fsr(&private_data->suspend,
-                               *((long *)data->data));
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
                break;
        case MPU_SLAVE_CONFIG_FSR_RESUME:
-               lis331dlh_set_fsr(&private_data->resume,
-                               *((long *)data->data));
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
                break;
        case MPU_SLAVE_CONFIG_MOT_THS:
-               lis331dlh_set_ths(&private_data->suspend,
-                               *((long *)data->data));
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.ths;
                break;
        case MPU_SLAVE_CONFIG_NMOT_THS:
-               lis331dlh_set_ths(&private_data->resume,
-                               *((long *)data->data));
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.ths;
                break;
        case MPU_SLAVE_CONFIG_MOT_DUR:
-               lis331dlh_set_dur(&private_data->suspend,
-                               *((long *)data->data));
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.dur;
                break;
        case MPU_SLAVE_CONFIG_NMOT_DUR:
-               lis331dlh_set_dur(&private_data->resume,
-                               *((long *)data->data));
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
                break;
        default:
                return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
@@ -356,13 +589,14 @@ static int lis331dlh_config(void *mlsl_handle,
        return ML_SUCCESS;
 }
 
-struct ext_slave_descr lis331dlh_descr = {
+static struct ext_slave_descr lis331dlh_descr = {
        /*.init             = */ lis331dlh_init,
        /*.exit             = */ lis331dlh_exit,
        /*.suspend          = */ lis331dlh_suspend,
        /*.resume           = */ lis331dlh_resume,
        /*.read             = */ lis331dlh_read,
        /*.config           = */ lis331dlh_config,
+       /*.get_config       = */ lis331dlh_get_config,
        /*.name             = */ "lis331dlh",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_LIS331,
diff --git a/drivers/misc/mpu3050/accel/lis3dh.c b/drivers/misc/mpu3050/accel/lis3dh.c
new file mode 100755 (executable)
index 0000000..ee5e353
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ $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/>.
+  $
+ */
+
+/**
+ *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
+ *  @brief      Provides the interface to setup and handle an accelerometers
+ *              connected to the secondary I2C interface of the gyroscope.
+ *
+ *  @{
+ *      @file   lis3dh.c
+ *      @brief  Accelerometer setup and handling methods for ST LIS3DH
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 0
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* full scale setting - register & mask */
+#define LIS3DH_CTRL_REG1         (0x20)
+#define LIS3DH_CTRL_REG2         (0x21)
+#define LIS3DH_CTRL_REG3         (0x22)
+#define LIS3DH_CTRL_REG4         (0x23)
+#define LIS3DH_CTRL_REG5         (0x24)
+#define LIS3DH_CTRL_REG6         (0x25)
+#define LIS3DH_REFERENCE         (0x26)
+#define LIS3DH_STATUS_REG        (0x27)
+#define LIS3DH_OUT_X_L           (0x28)
+#define LIS3DH_OUT_X_H           (0x29)
+#define LIS3DH_OUT_Y_L           (0x2a)
+#define LIS3DH_OUT_Y_H           (0x2b)
+#define LIS3DH_OUT_Z_L           (0x2b)
+#define LIS3DH_OUT_Z_H           (0x2d)
+
+#define LIS3DH_INT1_CFG          (0x30)
+#define LIS3DH_INT1_SRC          (0x31)
+#define LIS3DH_INT1_THS          (0x32)
+#define LIS3DH_INT1_DURATION     (0x33)
+
+#define LIS3DH_MAX_DUR (0x7F)
+
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+
+struct lis3dh_config {
+       unsigned int odr;
+       unsigned int fsr; /* full scale range mg */
+       unsigned int ths; /* Motion no-motion thseshold mg */
+       unsigned int dur; /* Motion no-motion duration ms */
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char ctrl_reg1;
+       unsigned char irq_type;
+       unsigned char mot_int1_cfg;
+};
+
+struct lis3dh_private_data {
+       struct lis3dh_config suspend;
+       struct lis3dh_config resume;
+};
+
+
+/*****************************************
+    Accelerometer Initialization Functions
+*****************************************/
+
+static int lis3dh_set_ths(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis3dh_config *config,
+                       int apply,
+                       long ths)
+{
+       int result = ML_SUCCESS;
+       if ((unsigned int) ths > 1000 * config->fsr)
+               ths = (long) 1000 * config->fsr;
+
+       if (ths < 0)
+               ths = 0;
+
+       config->ths = ths;
+       config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
+       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS3DH_INT1_THS,
+                                       config->reg_ths);
+       return result;
+}
+
+static int lis3dh_set_dur(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis3dh_config *config,
+                       int apply,
+                       long dur)
+{
+       int result = ML_SUCCESS;
+       long reg_dur = (dur * config->odr) / 1000000L;
+       config->dur = dur;
+
+       if (reg_dur > LIS3DH_MAX_DUR)
+               reg_dur = LIS3DH_MAX_DUR;
+
+       config->reg_dur = (unsigned char) reg_dur;
+       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS3DH_INT1_DURATION,
+                                       (unsigned char)reg_dur);
+       return result;
+}
+
+/**
+ * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
+ * duration will not be used uless the type is MOT or NMOT.
+ *
+ * @param config configuration to apply to, suspend or resume
+ * @param irq_type The type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ */
+static int lis3dh_set_irq(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis3dh_config *config,
+                       int apply,
+                       long irq_type)
+{
+       int result = ML_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+
+       config->irq_type = (unsigned char)irq_type;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x10;
+               reg2 = 0x00;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x40;
+               reg2 = config->mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+
+       if (apply) {
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS3DH_CTRL_REG3, reg1);
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS3DH_INT1_CFG, reg2);
+       }
+
+       return result;
+}
+
+/**
+ * Set the Output data rate for the particular configuration
+ *
+ * @param config Config to modify with new ODR
+ * @param odr Output data rate in units of 1/1000Hz
+ */
+static int lis3dh_set_odr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis3dh_config *config,
+                       int apply,
+                       long odr)
+{
+       unsigned char bits;
+       int result = ML_SUCCESS;
+
+       if (odr > 400000) {
+               config->odr = 1250000;
+               bits = 0x90;
+       } else if (odr > 200000) {
+               config->odr = 400000;
+               bits = 0x70;
+       } else if (odr > 100000) {
+               config->odr = 200000;
+               bits = 0x60;
+       } else if (odr > 50000) {
+               config->odr = 100000;
+               bits = 0x50;
+       } else if (odr > 25000) {
+               config->odr = 50000;
+               bits = 0x40;
+       } else if (odr > 10000) {
+               config->odr = 25000;
+               bits = 0x30;
+       } else if (odr > 1000) {
+               config->odr = 10000;
+               bits = 0x20;
+       } else if (odr > 500) {
+               config->odr = 1000;
+               bits = 0x10;
+       } else {
+               config->odr = 0;
+               bits = 0;
+       }
+
+       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0xf);
+       lis3dh_set_dur(mlsl_handle, pdata,
+                       config, apply, config->dur);
+       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS3DH_CTRL_REG1,
+                                       config->ctrl_reg1);
+       return result;
+}
+
+/**
+ * Set the full scale range of the accels
+ *
+ * @param config pointer to configuration
+ * @param fsr requested full scale range
+ */
+static int lis3dh_set_fsr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct lis3dh_config *config,
+                       int apply,
+                       long fsr)
+{
+       int result = ML_SUCCESS;
+       unsigned char reg1 = 0x48;
+
+       if (fsr <= 2048) {
+               config->fsr = 2048;
+       } else if (fsr <= 4096) {
+               reg1 |= 0x10;
+               config->fsr = 4096;
+       } else if (fsr <= 8192) {
+               reg1 |= 0x20;
+               config->fsr = 8192;
+       } else {
+               reg1 |= 0x30;
+               config->fsr = 16348;
+       }
+
+       lis3dh_set_ths(mlsl_handle, pdata,
+                       config, apply, config->ths);
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply)
+               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                       LIS3DH_CTRL_REG4, reg1);
+
+       return result;
+}
+
+static int lis3dh_suspend(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lis3dh_private_data *private_data = pdata->private_data;
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG1,
+                                      private_data->suspend.ctrl_reg1);
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG2, 0x31);
+       reg1 = 0x48;
+       if (private_data->suspend.fsr == 16384)
+               reg1 |= 0x30;
+       else if (private_data->suspend.fsr == 8192)
+               reg1 |= 0x20;
+       else if (private_data->suspend.fsr == 4096)
+               reg1 |= 0x10;
+       else if (private_data->suspend.fsr == 2048)
+               reg1 |= 0x00;
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG4, reg1);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_INT1_THS,
+                                      private_data->suspend.reg_ths);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_INT1_DURATION,
+                                      private_data->suspend.reg_dur);
+
+       if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x10;
+               reg2 = 0x00;
+       } else if (private_data->suspend.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x40;
+               reg2 = private_data->suspend.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG3, reg1);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_INT1_CFG, reg2);
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               LIS3DH_CTRL_REG6, 1, &reg1);
+
+       return result;
+}
+
+static int lis3dh_resume(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata)
+{
+       tMLError result;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lis3dh_private_data *private_data = pdata->private_data;
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG1,
+                                      private_data->resume.ctrl_reg1);
+       ERROR_CHECK(result);
+       MLOSSleep(6);
+
+       /* Full Scale */
+       reg1 = 0x48;
+       if (private_data->suspend.fsr == 16384)
+               reg1 |= 0x30;
+       else if (private_data->suspend.fsr == 8192)
+               reg1 |= 0x20;
+       else if (private_data->suspend.fsr == 4096)
+               reg1 |= 0x10;
+       else if (private_data->suspend.fsr == 2048)
+               reg1 |= 0x00;
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG4, reg1);
+       ERROR_CHECK(result);
+
+       /* Configure high pass filter */
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG2, 0x31);
+       ERROR_CHECK(result);
+
+       if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x10;
+               reg2 = 0x00;
+       } else if (private_data->resume.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x40;
+               reg2 = private_data->resume.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG3, reg1);
+       ERROR_CHECK(result);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_INT1_THS,
+                                      private_data->resume.reg_ths);
+       ERROR_CHECK(result);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_INT1_DURATION,
+                                      private_data->resume.reg_dur);
+       ERROR_CHECK(result);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_INT1_CFG, reg2);
+       ERROR_CHECK(result);
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               LIS3DH_CTRL_REG6, 1, &reg1);
+       ERROR_CHECK(result);
+       return result;
+}
+
+static int lis3dh_read(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       unsigned char *data)
+{
+       int result = ML_SUCCESS;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               LIS3DH_STATUS_REG, 1, data);
+       if (data[0] & 0x0F) {
+               result = MLSLSerialRead(mlsl_handle, pdata->address,
+                                       slave->reg, slave->len, data);
+               return result;
+       } else
+               return ML_ERROR_ACCEL_DATA_NOT_READY;
+}
+
+static int lis3dh_init(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       tMLError result;
+
+       struct lis3dh_private_data *private_data;
+       private_data = (struct lis3dh_private_data *)
+               MLOSMalloc(sizeof(struct lis3dh_private_data));
+
+       if (!private_data)
+               return ML_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       private_data->resume.ctrl_reg1 = 0x67;
+       private_data->suspend.ctrl_reg1 = 0x18;
+       private_data->resume.mot_int1_cfg = 0x95;
+       private_data->suspend.mot_int1_cfg = 0x2a;
+
+       lis3dh_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 0);
+       lis3dh_set_odr(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 200000);
+       lis3dh_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 2048);
+       lis3dh_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 2048);
+       lis3dh_set_ths(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 80);
+       lis3dh_set_ths(mlsl_handle, pdata, &private_data->resume,
+                       FALSE, 40);
+       lis3dh_set_dur(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE, 1000);
+       lis3dh_set_dur(mlsl_handle, pdata, &private_data->resume,
+                       FALSE,  2540);
+       lis3dh_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                       FALSE,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
+       lis3dh_set_irq(mlsl_handle, pdata, &private_data->resume,
+                       FALSE,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                      LIS3DH_CTRL_REG1, 0x07);
+       MLOSSleep(6);
+
+       return ML_SUCCESS;
+}
+
+static int lis3dh_exit(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       if (pdata->private_data)
+               return MLOSFree(pdata->private_data);
+       else
+               return ML_SUCCESS;
+}
+
+static int lis3dh_config(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config *data)
+{
+       struct lis3dh_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return lis3dh_set_odr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return lis3dh_set_odr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return lis3dh_set_fsr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return lis3dh_set_fsr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return lis3dh_set_ths(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return lis3dh_set_ths(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return lis3dh_set_dur(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return lis3dh_set_dur(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return lis3dh_set_irq(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return lis3dh_set_irq(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+       return ML_SUCCESS;
+}
+
+static int lis3dh_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct lis3dh_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
+               break;
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return ML_SUCCESS;
+}
+
+static struct ext_slave_descr lis3dh_descr = {
+       /*.init             = */ lis3dh_init,
+       /*.exit             = */ lis3dh_exit,
+       /*.suspend          = */ lis3dh_suspend,
+       /*.resume           = */ lis3dh_resume,
+       /*.read             = */ lis3dh_read,
+       /*.config           = */ lis3dh_config,
+       /*.get_config       = */ lis3dh_get_config,
+       /*.name             = */ "lis3dh",
+       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
+       /*.id               = */ ACCEL_ID_LIS3DH,
+       /*.reg              = */ 0x28 | 0x80, /* 0x80 for burst reads */
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
+       /*.range            = */ {2, 480},
+};
+
+struct ext_slave_descr *lis3dh_get_slave_descr(void)
+{
+       return &lis3dh_descr;
+}
+EXPORT_SYMBOL(lis3dh_get_slave_descr);
+
+/*
+ *  @}
+*/
old mode 100644 (file)
new mode 100755 (executable)
index 47e2ac1..b849496
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -131,7 +144,10 @@ int lsm303dlha_read(void *mlsl_handle,
                    struct ext_slave_platform_data *pdata,
                    unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       return result;
 }
 
 struct ext_slave_descr lsm303dlha_descr = {
@@ -141,6 +157,7 @@ struct ext_slave_descr lsm303dlha_descr = {
        /*.resume           = */ lsm303dlha_resume,
        /*.read             = */ lsm303dlha_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "lsm303dlha",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_LSM303,
old mode 100644 (file)
new mode 100755 (executable)
index 9e6f3e4..1cb9847
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 /**
  *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
@@ -10,7 +23,7 @@
  *
  *  @{
  *      @file   lis331.c
- *      @brief  Accelerometer setup and handling methods for ST LIS331
+ *      @brief  Accelerometer setup and handling methods for Invensense MANTIS
  */
 
 /* ------------------ */
 #undef MPL_LOG_TAG
 #define MPL_LOG_TAG "MPL-acc"
 
-#define ACCEL_ST_SLEEP_REG          (0x20)
-#define ACCEL_ST_SLEEP_MASK         (0x20)
-
 /* --------------------- */
 /* -    Variables.     - */
 /* --------------------- */
 
+struct mantis_config {
+       unsigned int odr; /* output data rate 1/1000 Hz*/
+       unsigned int fsr; /* full scale range mg */
+       unsigned int ths; /* Motion no-motion thseshold mg */
+       unsigned int dur; /* Motion no-motion duration ms */
+};
+
+struct mantis_private_data {
+       struct mantis_config suspend;
+       struct mantis_config resume;
+};
+
+
 /*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
+ *Accelerometer Initialization Functions
+ *****************************************/
+/**
+ * Record the odr for use in computing duration values.
+ *
+ * @param config Config to set, suspend or resume structure
+ * @param odr output data rate in 1/1000 hz
+ */
+void mantis_set_odr(struct mantis_config *config,
+               long odr)
+{
+       config->odr = odr;
+}
+
+void mantis_set_ths(struct mantis_config *config,
+               long ths)
+{
+       if (ths < 0)
+               ths = 0;
+
+       config->ths = ths;
+       MPL_LOGV("THS: %d\n", config->ths);
+}
+
+void mantis_set_dur(struct mantis_config *config,
+               long dur)
+{
+       if (dur < 0)
+               dur = 0;
+
+       config->dur = dur;
+       MPL_LOGV("DUR: %d\n", config->dur);
+}
+
+static void mantis_set_fsr(
+       struct mantis_config *config,
+       long fsr)
+{
+       if (fsr <= 2000)
+               config->fsr = 2000;
+       else if (fsr <= 4000)
+               config->fsr = 4000;
+       else
+               config->fsr = 8000;
+
+       MPL_LOGV("FSR: %d\n", config->fsr);
+}
+
+static int mantis_init(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       struct mantis_private_data *private_data;
+       private_data = (struct mantis_private_data *)
+               MLOSMalloc(sizeof(struct mantis_private_data));
+
+       if (!private_data)
+               return ML_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       mantis_set_odr(&private_data->suspend, 0);
+       mantis_set_odr(&private_data->resume, 200000);
+       mantis_set_fsr(&private_data->suspend, 2000);
+       mantis_set_fsr(&private_data->resume, 2000);
+       mantis_set_ths(&private_data->suspend, 80);
+       mantis_set_ths(&private_data->resume, 40);
+       mantis_set_dur(&private_data->suspend, 1000);
+       mantis_set_dur(&private_data->resume,  2540);
+       return ML_SUCCESS;
+}
+
+static int mantis_exit(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       if (pdata->private_data)
+               return MLOSFree(pdata->private_data);
+       else
+               return ML_SUCCESS;
+}
 
 int mantis_suspend(void *mlsl_handle,
                   struct ext_slave_descr *slave,
                   struct ext_slave_platform_data *pdata)
 {
+       unsigned char reg;
+       int result;
+
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               MPUREG_PWR_MGMT_2, 1, &reg);
+       ERROR_CHECK(result);
+       reg |= (BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               MPUREG_PWR_MGMT_2, reg);
+       ERROR_CHECK(result);
+
        return ML_SUCCESS;
 }
 
-/* full scale setting - register & mask */
-#define ACCEL_ST_CTRL_REG          (0x23)
-#define ACCEL_ST_CTRL_MASK         (0x30)
-
 int mantis_resume(void *mlsl_handle,
                  struct ext_slave_descr *slave,
                  struct ext_slave_platform_data *pdata)
 {
        int result = ML_SUCCESS;
-#ifdef M_HW
        unsigned char reg;
+       struct mantis_private_data *private_data;
+
+       private_data = (struct mantis_private_data *) pdata->private_data;
+
+       MLSLSerialRead(mlsl_handle, pdata->address,
+               MPUREG_PWR_MGMT_2, 1, &reg);
+
+       reg &= ~(BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               MPUREG_PWR_MGMT_2, reg);
+       ERROR_CHECK(result);
 
        if (slave->range.mantissa == 2)
                reg = 0;
@@ -72,7 +193,28 @@ int mantis_resume(void *mlsl_handle,
 
        result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
                                       MPUREG_ACCEL_CONFIG, reg);
-#endif
+       ERROR_CHECK(result);
+
+       reg = (unsigned char) private_data->suspend.ths / ACCEL_MOT_THR_LSB;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               MPUREG_ACCEL_MOT_THR, reg);
+       ERROR_CHECK(result);
+
+       reg = (unsigned char)
+               ACCEL_ZRMOT_THR_LSB_CONVERSION(private_data->resume.ths);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               MPUREG_ACCEL_ZRMOT_THR, reg);
+       ERROR_CHECK(result);
+
+       reg = (unsigned char) private_data->suspend.ths / ACCEL_MOT_DUR_LSB;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               MPUREG_ACCEL_MOT_DUR, reg);
+       ERROR_CHECK(result);
+
+       reg = (unsigned char) private_data->resume.ths / ACCEL_ZRMOT_DUR_LSB;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               MPUREG_ACCEL_ZRMOT_DUR, reg);
+       ERROR_CHECK(result);
        return result;
 }
 
@@ -80,16 +222,69 @@ int mantis_read(void *mlsl_handle,
                struct ext_slave_descr *slave,
                struct ext_slave_platform_data *pdata, unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, slave->len, data);
+       return result;
+}
+
+static int mantis_config(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config *data)
+{
+       struct mantis_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               mantis_set_odr(&private_data->suspend,
+                               *((long *)data->data));
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               mantis_set_odr(&private_data->resume,
+                               *((long *)data->data));
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               mantis_set_fsr(&private_data->suspend,
+                               *((long *)data->data));
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               mantis_set_fsr(&private_data->resume,
+                               *((long *)data->data));
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               mantis_set_ths(&private_data->suspend,
+                              (*((long *)data->data)));
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               mantis_set_ths(&private_data->resume,
+                              (*((long *)data->data)));
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               mantis_set_dur(&private_data->suspend,
+                              (*((long *)data->data)));
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               mantis_set_dur(&private_data->resume,
+                              (*((long *)data->data)));
+               break;
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return ML_SUCCESS;
 }
 
 struct ext_slave_descr mantis_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
+       /*.init             = */ mantis_init,
+       /*.exit             = */ mantis_exit,
        /*.suspend          = */ mantis_suspend,
        /*.resume           = */ mantis_resume,
        /*.read             = */ mantis_read,
-       /*.config           = */ NULL,
+       /*.config           = */ mantis_config,
+       /*.get_config       = */ NULL,
        /*.name             = */ "mantis",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_MPU6000,
old mode 100644 (file)
new mode 100755 (executable)
index fec9c74..ffc92fd
@@ -1,7 +1,20 @@
 /*
  $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 Files. - */
 /* ------------------ */
 
+#include <stdlib.h>
 #include "mpu.h"
 #include "mlsl.h"
 #include "mlos.h"
+#include <string.h>
 
 #include <log.h>
 #undef MPL_LOG_TAG
@@ -90,7 +105,8 @@ int mma8450_resume(void *mlsl_handle,
 
        /* XYZ_DATA_CFG: event flag enabled on all axis */
        result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x16, 0x05);
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 0x16, 0x05);
        ERROR_CHECK(result);
        /* CTRL_REG1: rate + scale config + wakeup */
        result =
@@ -106,7 +122,13 @@ int mma8450_read(void *mlsl_handle,
                 struct ext_slave_platform_data *pdata,
                 unsigned char *data)
 {
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       int result;
+       unsigned char local_data[4]; /* Status register + 3 bytes data */
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, sizeof(local_data), local_data);
+    ERROR_CHECK(result);
+    memcpy(data, &local_data[1], (slave->len)-1);
+    return result;
 }
 
 struct ext_slave_descr mma8450_descr = {
@@ -116,11 +138,12 @@ struct ext_slave_descr mma8450_descr = {
        /*.resume           = */ mma8450_resume,
        /*.read             = */ mma8450_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "mma8450",
        /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
        /*.id               = */ ACCEL_ID_MMA8450,
        /*.reg              = */ 0x00,
-       /*.len              = */ 3,
+       /*.len              = */ 4,
        /*.endian           = */ EXT_SLAVE_FS8_BIG_ENDIAN,
        /*.range            = */ {2, 0},
 };
diff --git a/drivers/misc/mpu3050/accel/mma845x.c b/drivers/misc/mpu3050/accel/mma845x.c
new file mode 100755 (executable)
index 0000000..27150ad
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ $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/>.
+  $
+ */
+
+/**
+ *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
+ *  @brief      Provides the interface to setup and handle an accelerometers
+ *              connected to the secondary I2C interface of the gyroscope.
+ *
+ *  @{
+ *      @file   mma845x.c
+ *      @brief  Accelerometer setup and handling methods for Freescale MMA845X
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include <stdlib.h>
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+#include <string.h>
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+#define ACCEL_MMA845X_CTRL_REG1      (0x2A)
+#define ACCEL_MMA845X_SLEEP_MASK     (0x01)
+
+/* full scale setting - register & mask */
+#define ACCEL_MMA845X_CFG_REG       (0x0E)
+#define ACCEL_MMA845X_CTRL_MASK     (0x03)
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+
+/*****************************************
+    Accelerometer Initialization Functions
+*****************************************/
+
+int mma845x_suspend(void *mlsl_handle,
+                   struct ext_slave_descr *slave,
+                   struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char reg;
+       result =
+           MLSLSerialRead(mlsl_handle, pdata->address,
+                          ACCEL_MMA845X_CTRL_REG1, 1, &reg);
+       ERROR_CHECK(result);
+       reg &= ~ACCEL_MMA845X_SLEEP_MASK;
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 ACCEL_MMA845X_CTRL_REG1, reg);
+       ERROR_CHECK(result);
+       return result;
+}
+
+
+int mma845x_resume(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+       unsigned char reg;
+
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               ACCEL_MMA845X_CFG_REG, 1, &reg);
+       ERROR_CHECK(result);
+
+       /* data rate = 200Hz */
+
+       /* Full Scale */
+       reg &= ~ACCEL_MMA845X_CTRL_MASK;
+       if (slave->range.mantissa == 4)
+               reg |= 0x1;
+       else if (slave->range.mantissa == 8)
+               reg |= 0x2;
+       else {
+               slave->range.mantissa = 2;
+               reg |= 0x0;
+       }
+       slave->range.fraction = 0;
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                               ACCEL_MMA845X_CFG_REG, reg);
+       ERROR_CHECK(result);
+       /* 200Hz + active mode */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                           ACCEL_MMA845X_CTRL_REG1, 0x11);
+       ERROR_CHECK(result);
+
+       return result;
+}
+
+int mma845x_read(void *mlsl_handle,
+                struct ext_slave_descr *slave,
+                struct ext_slave_platform_data *pdata,
+                unsigned char *data)
+{
+       int result;
+       unsigned char local_data[7]; /* Status register + 6 bytes data */
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+                               slave->reg, sizeof(local_data), local_data);
+       ERROR_CHECK(result);
+       memcpy(data, &local_data[1], slave->len);
+       return result;
+}
+
+struct ext_slave_descr mma845x_descr = {
+       /*.init             = */ NULL,
+       /*.exit             = */ NULL,
+       /*.suspend          = */ mma845x_suspend,
+       /*.resume           = */ mma845x_resume,
+       /*.read             = */ mma845x_read,
+       /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
+       /*.name             = */ "mma845x",
+       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
+       /*.id               = */ ACCEL_ID_MMA845X,
+       /*.reg              = */ 0x00,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_FS16_BIG_ENDIAN,
+       /*.range            = */ {2, 0},
+};
+
+struct ext_slave_descr *mma845x_get_slave_descr(void)
+{
+       return &mma845x_descr;
+}
+EXPORT_SYMBOL(mma845x_get_slave_descr);
+
+/**
+ *  @}
+ */
old mode 100644 (file)
new mode 100755 (executable)
index 5f020cf..b8aed30
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -147,13 +160,84 @@ int ak8975_read(void *mlsl_handle,
        return status;
 }
 
+static int ak8975_config(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config *data)
+{
+       int result;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_WRITE_REGISTERS:
+               result = MLSLSerialWrite(mlsl_handle, pdata->address,
+                                       data->len,
+                                       (unsigned char *)data->data);
+               ERROR_CHECK(result);
+               break;
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return ML_SUCCESS;
+}
+
+static int ak8975_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       int result;
+       if (!data->data)
+               return ML_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_READ_REGISTERS:
+       {
+               unsigned char *serial_data = (unsigned char *)data->data;
+               result = MLSLSerialRead(mlsl_handle, pdata->address,
+                                       serial_data[0],
+                                       data->len - 1,
+                                       &serial_data[1]);
+               ERROR_CHECK(result);
+               break;
+       }
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return ML_SUCCESS;
+}
+
 struct ext_slave_descr ak8975_descr = {
        /*.init             = */ NULL,
        /*.exit             = */ NULL,
        /*.suspend          = */ ak8975_suspend,
        /*.resume           = */ ak8975_resume,
        /*.read             = */ ak8975_read,
-       /*.config           = */ NULL,
+       /*.config           = */ ak8975_config,
+       /*.get_config       = */ ak8975_get_config,
        /*.name             = */ "ak8975",
        /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
        /*.id               = */ COMPASS_ID_AKM,
diff --git a/drivers/misc/mpu3050/compass/ami306.c b/drivers/misc/mpu3050/compass/ami306.c
new file mode 100755 (executable)
index 0000000..75ca007
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ $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/>.
+  $
+ */
+
+/**
+ *  @defgroup   COMPASSDL (Motion Library - Accelerometer Driver Layer)
+ *  @brief      Provides the interface to setup and handle an accelerometers
+ *              connected to the secondary I2C interface of the gyroscope.
+ *
+ *  @{
+ *     @file   ami306.c
+ *     @brief  Magnetometer setup and handling methods for Aichi AMI306
+ *             compass.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include <delay.h>
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+#define AMI306_REG_DATAX (0x10)
+#define AMI306_REG_STAT1 (0x18)
+#define AMI306_REG_CNTL1 (0x1B)
+#define AMI306_REG_CNTL2 (0x1C)
+#define AMI306_REG_CNTL3 (0x1D)
+#define AMI306_REG_CNTL4_1 (0x5C)
+#define AMI306_REG_CNTL4_2 (0x5D)
+
+#define AMI306_BIT_CNTL1_PC1  (0x80)
+#define AMI306_BIT_CNTL1_ODR1 (0x10)
+#define AMI306_BIT_CNTL1_FS1  (0x02)
+
+#define AMI306_BIT_CNTL2_IEN  (0x10)
+#define AMI306_BIT_CNTL2_DREN (0x08)
+#define AMI306_BIT_CNTL2_DRP  (0x04)
+#define AMI306_BIT_CNTL3_F0RCE (0x40)
+
+int ami306_suspend(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char reg;
+       result =
+           MLSLSerialRead(mlsl_handle, pdata->address, AMI306_REG_CNTL1,
+                          1, &reg);
+       ERROR_CHECK(result);
+
+       reg &= ~(AMI306_BIT_CNTL1_PC1|AMI306_BIT_CNTL1_FS1);
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 AMI306_REG_CNTL1, reg);
+       ERROR_CHECK(result);
+
+       return result;
+}
+
+int ami306_resume(void *mlsl_handle,
+                 struct ext_slave_descr *slave,
+                 struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+       unsigned char regs[] = {
+                AMI306_REG_CNTL4_1,
+                0x7E,
+                0xA0
+       };
+    /* Step1. Set CNTL1 reg to power model active (Write CNTL1:PC1=1) */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 AMI306_REG_CNTL1,
+                                 AMI306_BIT_CNTL1_PC1|AMI306_BIT_CNTL1_FS1);
+       ERROR_CHECK(result);
+
+    /* Step2. Set CNTL2 reg to DRDY active high and enabled
+       (Write CNTL2:DREN=1) */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 AMI306_REG_CNTL2,
+                                 AMI306_BIT_CNTL2_DREN |
+                                 AMI306_BIT_CNTL2_DRP);
+       ERROR_CHECK(result);
+
+    /* Step3. Set CNTL4 reg to for measurement speed (Write CNTL4, 0xA07E) */
+       result =
+           MLSLSerialWrite(mlsl_handle, pdata->address, DIM(regs), regs);
+       ERROR_CHECK(result);
+
+    /* Step4. skipped */
+
+    /* Step5. Set CNTL3 reg to forced measurement period
+       (Write CNTL3:FORCE=1) */
+       result =
+               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 AMI306_REG_CNTL3, AMI306_BIT_CNTL3_F0RCE);
+
+       return result;
+}
+
+int ami306_read(void *mlsl_handle,
+               struct ext_slave_descr *slave,
+               struct ext_slave_platform_data *pdata, unsigned char *data)
+{
+       unsigned char stat;
+       int result = ML_SUCCESS;
+       int status = ML_SUCCESS;
+
+
+       /* Measurement(x,y,z) */
+       result =
+               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                     AMI306_REG_CNTL3,
+                                     AMI306_BIT_CNTL3_F0RCE);
+       ERROR_CHECK(result);
+       udelay(500);
+
+    /* Step6. Read status reg and check if data ready (DRDY) */
+       result =
+           MLSLSerialRead(mlsl_handle, pdata->address, AMI306_REG_STAT1,
+                          1, &stat);
+       ERROR_CHECK(result);
+
+    /* Step6. Does DRDY output the rising edge? */
+       if (stat & 0x40) {
+               result =
+                   MLSLSerialRead(mlsl_handle, pdata->address,
+                                  AMI306_REG_DATAX, 6,
+                                  (unsigned char *) data);
+               ERROR_CHECK(result);
+               status = ML_SUCCESS;
+       } else if (stat & 0x20)
+               status = ML_ERROR_COMPASS_DATA_OVERFLOW;
+
+       return status;
+}
+
+struct ext_slave_descr ami306_descr = {
+       /*.init             = */ NULL,
+       /*.exit             = */ NULL,
+       /*.suspend          = */ ami306_suspend,
+       /*.resume           = */ ami306_resume,
+       /*.read             = */ ami306_read,
+       /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
+       /*.name             = */ "ami306",
+       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+       /*.id               = */ COMPASS_ID_AMI306,
+       /*.reg              = */ 0x10,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
+       /*.range            = */ {5461, 3333}
+       /* For AMI305,the range field needs to be modified to {9830.4f}*/
+};
+
+struct ext_slave_descr *ami306_get_slave_descr(void)
+{
+       return &ami306_descr;
+}
+EXPORT_SYMBOL(ami306_get_slave_descr);
+
+/**
+ *  @}
+ */
old mode 100644 (file)
new mode 100755 (executable)
index 28cd5f4..5e4a33e
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -132,6 +145,7 @@ struct ext_slave_descr ami30x_descr = {
        /*.resume           = */ ami30x_resume,
        /*.read             = */ ami30x_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "ami30x",
        /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
        /*.id               = */ COMPASS_ID_AMI30X,
old mode 100644 (file)
new mode 100755 (executable)
index 3e67d2e..02afd58
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -220,6 +233,7 @@ struct ext_slave_descr hmc5883_descr = {
        /*.resume           = */ hmc5883_resume,
        /*.read             = */ hmc5883_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "hmc5883",
        /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
        /*.id               = */ COMPASS_ID_HMC5883,
diff --git a/drivers/misc/mpu3050/compass/hscdtd002b.c b/drivers/misc/mpu3050/compass/hscdtd002b.c
new file mode 100755 (executable)
index 0000000..bf26cae
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ $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/>.
+  $
+ */
+
+/**
+ *  @brief      Provides the interface to setup and handle a compass
+ *              connected to the primary I2C interface of the gyroscope.
+ *
+ *  @{
+ *      @file   hscdtd002b.c
+ *      @brief  Magnetometer setup and handling methods for Alps hscdtd002b
+ *              compass.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/*----- ALPS HSCDTD002B Registers ------*/
+#define COMPASS_HSCDTD002B_STAT          (0x18)
+#define COMPASS_HSCDTD002B_CTRL1         (0x1B)
+#define COMPASS_HSCDTD002B_CTRL2         (0x1C)
+#define COMPASS_HSCDTD002B_CTRL3         (0x1D)
+#define COMPASS_HSCDTD002B_DATAX         (0x10)
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+
+/*****************************************
+    Compass Initialization Functions
+*****************************************/
+
+int hscdtd002b_suspend(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       /* Power mode: stand-by */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD002B_CTRL1, 0x00);
+       ERROR_CHECK(result);
+       MLOSSleep(1);           /* turn-off time */
+
+       return result;
+}
+
+int hscdtd002b_resume(void *mlsl_handle,
+                     struct ext_slave_descr *slave,
+                     struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       /* Soft reset */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD002B_CTRL3, 0x80);
+       ERROR_CHECK(result);
+       /* Force state; Power mode: active */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD002B_CTRL1, 0x82);
+       ERROR_CHECK(result);
+       /* Data ready enable */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD002B_CTRL2, 0x08);
+       ERROR_CHECK(result);
+       MLOSSleep(1);           /* turn-on time */
+
+       return result;
+}
+
+int hscdtd002b_read(void *mlsl_handle,
+                   struct ext_slave_descr *slave,
+                   struct ext_slave_platform_data *pdata,
+                   unsigned char *data)
+{
+       unsigned char stat;
+       tMLError result = ML_SUCCESS;
+       int status = ML_SUCCESS;
+
+       /* Read status reg. to check if data is ready */
+       result =
+           MLSLSerialRead(mlsl_handle, pdata->address,
+                          COMPASS_HSCDTD002B_STAT, 1, &stat);
+       ERROR_CHECK(result);
+       if (stat & 0x40) {
+               result =
+                   MLSLSerialRead(mlsl_handle, pdata->address,
+                                  COMPASS_HSCDTD002B_DATAX, 6,
+                                  (unsigned char *) data);
+               ERROR_CHECK(result);
+               status = ML_SUCCESS;
+       } else if (stat & 0x20) {
+               status = ML_ERROR_COMPASS_DATA_OVERFLOW;
+       } else {
+               status = ML_ERROR_COMPASS_DATA_NOT_READY;
+       }
+       /* trigger next measurement read */
+       result =
+               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                         COMPASS_HSCDTD002B_CTRL3, 0x40);
+       ERROR_CHECK(result);
+
+       return status;
+}
+
+struct ext_slave_descr hscdtd002b_descr = {
+       /*.init             = */ NULL,
+       /*.exit             = */ NULL,
+       /*.suspend          = */ hscdtd002b_suspend,
+       /*.resume           = */ hscdtd002b_resume,
+       /*.read             = */ hscdtd002b_read,
+       /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
+       /*.name             = */ "hscdtd002b",
+       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+       /*.id               = */ COMPASS_ID_HSCDTD002B,
+       /*.reg              = */ 0x10,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
+       /*.range            = */ {9830, 4000},
+};
+
+struct ext_slave_descr *hscdtd002b_get_slave_descr(void)
+{
+       return &hscdtd002b_descr;
+}
+EXPORT_SYMBOL(hscdtd002b_get_slave_descr);
+
+/**
+ *  @}
+**/
diff --git a/drivers/misc/mpu3050/compass/hscdtd004a.c b/drivers/misc/mpu3050/compass/hscdtd004a.c
new file mode 100755 (executable)
index 0000000..43fc14a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ $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/>.
+  $
+ */
+
+/**
+ *  @brief      Provides the interface to setup and handle a compass
+ *              connected to the primary I2C interface of the gyroscope.
+ *
+ *  @{
+ *      @file   hscdtd004a.c
+ *      @brief  Magnetometer setup and handling methods for Alps hscdtd004a
+ *              compass.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/*----- ALPS HSCDTD004A Registers ------*/
+#define COMPASS_HSCDTD004A_STAT          (0x18)
+#define COMPASS_HSCDTD004A_CTRL1         (0x1B)
+#define COMPASS_HSCDTD004A_CTRL2         (0x1C)
+#define COMPASS_HSCDTD004A_CTRL3         (0x1D)
+#define COMPASS_HSCDTD004A_DATAX         (0x10)
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+
+/*****************************************
+    Compass Initialization Functions
+*****************************************/
+
+int hscdtd004a_suspend(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       /* Power mode: stand-by */
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD004A_CTRL1, 0x00);
+       ERROR_CHECK(result);
+       MLOSSleep(1);           /* turn-off time */
+
+       return result;
+}
+
+int hscdtd004a_resume(void *mlsl_handle,
+                     struct ext_slave_descr *slave,
+                     struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       /* Soft reset */
+       result =
+               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD004A_CTRL3, 0x80);
+       ERROR_CHECK(result);
+       /* Normal state; Power mode: active */
+       result =
+               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD004A_CTRL1, 0x82);
+       ERROR_CHECK(result);
+       /* Data ready enable */
+       result =
+               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 COMPASS_HSCDTD004A_CTRL2, 0x7C);
+       ERROR_CHECK(result);
+       MLOSSleep(1);           /* turn-on time */
+       return result;
+}
+
+int hscdtd004a_read(void *mlsl_handle,
+                   struct ext_slave_descr *slave,
+                   struct ext_slave_platform_data *pdata,
+                   unsigned char *data)
+{
+       unsigned char stat;
+       tMLError result = ML_SUCCESS;
+       int status = ML_SUCCESS;
+
+       /* Read status reg. to check if data is ready */
+       result =
+               MLSLSerialRead(mlsl_handle, pdata->address,
+                          COMPASS_HSCDTD004A_STAT, 1, &stat);
+       ERROR_CHECK(result);
+       if (stat & 0x48) {
+               result =
+                        MLSLSerialRead(mlsl_handle, pdata->address,
+                                  COMPASS_HSCDTD004A_DATAX, 6,
+                                  (unsigned char *) data);
+               ERROR_CHECK(result);
+               status = ML_SUCCESS;
+       } else if (stat & 0x68) {
+               status = ML_ERROR_COMPASS_DATA_OVERFLOW;
+       } else {
+               status = ML_ERROR_COMPASS_DATA_NOT_READY;
+       }
+       /* trigger next measurement read */
+       result =
+               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                       COMPASS_HSCDTD004A_CTRL3, 0x40);
+       ERROR_CHECK(result);
+       return status;
+
+}
+
+struct ext_slave_descr hscdtd004a_descr = {
+       /*.init             = */ NULL,
+       /*.exit             = */ NULL,
+       /*.suspend          = */ hscdtd004a_suspend,
+       /*.resume           = */ hscdtd004a_resume,
+       /*.read             = */ hscdtd004a_read,
+       /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
+       /*.name             = */ "hscdtd004a",
+       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+       /*.id               = */ COMPASS_ID_HSCDTD004A,
+       /*.reg              = */ 0x10,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
+       /*.range            = */ {9830, 4000},
+};
+
+struct ext_slave_descr *hscdtd004a_get_slave_descr(void)
+{
+       return &hscdtd004a_descr;
+}
+EXPORT_SYMBOL(hscdtd004a_get_slave_descr);
+
+/**
+ *  @}
+**/
old mode 100644 (file)
new mode 100755 (executable)
index 082ee45..871d002
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -210,6 +223,7 @@ struct ext_slave_descr lsm303dlhm_descr = {
        /*.resume           = */ lsm303dlhm_resume,
        /*.read             = */ lsm303dlhm_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "lsm303dlhm",
        /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
        /*.id               = */ COMPASS_ID_LSM303,
old mode 100644 (file)
new mode 100755 (executable)
index 4bff05d..010d7a7
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -150,6 +163,7 @@ struct ext_slave_descr mmc314x_descr = {
        /*.resume           = */ mmc314x_resume,
        /*.read             = */ mmc314x_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "mmc314x",
        /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
        /*.id               = */ COMPASS_ID_MMC314X,
old mode 100644 (file)
new mode 100755 (executable)
index b4be440..239ab66
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 /**
  *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
@@ -443,6 +456,7 @@ struct ext_slave_descr yas529_descr = {
        /*.resume           = */ yas529_resume,
        /*.read             = */ yas529_read,
        /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
        /*.name             = */ "yas529",
        /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
        /*.id               = */ COMPASS_ID_YAS529,
diff --git a/drivers/misc/mpu3050/compass/yas530-kernel.c b/drivers/misc/mpu3050/compass/yas530-kernel.c
new file mode 100755 (executable)
index 0000000..f6dbb56
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ $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/>.
+  $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/>.
+  $
+  */
+ /**
+  *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
+  *  @brief      Provides the interface to setup and handle an accelerometers
+  *              connected to the secondary I2C interface of the gyroscope.
+  *
+  *  @{
+  *      @file   yas530.c
+  *      @brief  Magnetometer setup and handling methods for Yamaha yas530
+  *              compass.
+  */
+
+ /* ------------------ */
+ /* - Include Files. - */
+ /* ------------------ */
+
+#include "mpu.h"
+#include "mltypes.h"
+
+#include "mlsl.h"
+#include "mlos.h"
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <i2c.h>
+#endif
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-yas530:"
+
+
+extern int geomagnetic_api_resume(void);
+extern int geomagnetic_api_suspend(void);
+extern int geomagnetic_api_read(int *xyz, int *raw, int *xy1y2, int *accuracy);
+
+ /*****************************************
+     Compass Initialization Functions
+ *****************************************/
+
+static int
+yas530_suspend
+(
+   void *mlsl_handle,
+   struct ext_slave_descr *slave,
+   struct ext_slave_platform_data *pdata
+)
+{
+  int result = ML_SUCCESS;
+
+  geomagnetic_api_suspend();
+
+  return result;
+}
+
+
+static int
+yas530_resume
+(
+   void *mlsl_handle,
+   struct ext_slave_descr *slave,
+   struct ext_slave_platform_data *pdata
+)
+{
+  geomagnetic_api_resume();
+  return ML_SUCCESS;
+}
+
+
+static int
+yas530_read
+(
+     void *mlsl_handle,
+     struct ext_slave_descr *slave,
+     struct ext_slave_platform_data *pdata,
+     unsigned char *data
+)
+{
+  int xyz[3];
+  int raw[3];
+  short rawfixed[3];
+  int xy1y2[3];
+  int accuracy;
+
+  geomagnetic_api_read(xyz, raw, xy1y2, &accuracy);
+
+  rawfixed[0] = (short) (xyz[0]/100);
+  rawfixed[1] = (short) (xyz[1]/100);
+  rawfixed[2] = (short) (xyz[2]/100);
+
+  data[0] = rawfixed[0] >> 8;
+  data[1] = rawfixed[0] & 0xFF;
+  data[2] = rawfixed[1] >> 8;
+  data[3] = rawfixed[1] & 0xFF;
+  data[4] = rawfixed[2] >> 8;
+  data[5] = rawfixed[2] & 0xFF;
+
+  return ML_SUCCESS;
+}
+
+
+
+struct ext_slave_descr yas530_descr = {
+     /*.init          = */ NULL,
+     /*.exit          = */ NULL,
+     /*.suspend          = */ yas530_suspend,
+     /*.resume           = */ yas530_resume,
+     /*.read             = */ yas530_read,
+     /*.config           = */ NULL,
+     /*.name             = */ "yas530",
+     /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+     /*.id               = */ COMPASS_ID_YAS530,
+     /*.reg              = */ 0x06,
+     /*.len              = */ 6,
+     /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
+     /*.range            = */ {3276, 8001},
+};
+
+struct ext_slave_descr *yas530_get_slave_descr(void)
+{
+     return &yas530_descr;
+}
+
+#ifdef __KERNEL__
+ EXPORT_SYMBOL(yas530_get_slave_descr);
+#endif
+
+ /**
+  *  @}
+ **/
diff --git a/drivers/misc/mpu3050/compass/yas530.c b/drivers/misc/mpu3050/compass/yas530.c
new file mode 100755 (executable)
index 0000000..9fc9acb
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ $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/>.
+  $
+ */
+/**
+ *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
+ *  @brief      Provides the interface to setup and handle an accelerometers
+ *              connected to the secondary I2C interface of the gyroscope.
+ *
+ *  @{
+ *      @file   yas530.c
+ *      @brief  Magnetometer setup and handling methods for Yamaha yas530
+ *              compass.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#ifdef __KERNEL__
+#include <linux/module.h>
+#endif
+
+#include "mpu.h"
+#include "mlsl.h"
+#include "mlos.h"
+
+#include <log.h>
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/*----- YAMAHA YAS529 Registers ------*/
+#define YAS530_REGADDR_DEVICE_ID          (0x80)
+#define YAS530_REGADDR_ACTUATE_INIT_COIL  (0x81)
+#define YAS530_REGADDR_MEASURE_COMMAND    (0x82)
+#define YAS530_REGADDR_CONFIG             (0x83)
+#define YAS530_REGADDR_MEASURE_INTERVAL   (0x84)
+#define YAS530_REGADDR_OFFSET_X           (0x85)
+#define YAS530_REGADDR_OFFSET_Y1          (0x86)
+#define YAS530_REGADDR_OFFSET_Y2          (0x87)
+#define YAS530_REGADDR_TEST1              (0x88)
+#define YAS530_REGADDR_TEST2              (0x89)
+#define YAS530_REGADDR_CAL                (0x90)
+#define YAS530_REGADDR_MEASURE_DATA       (0xb0)
+
+
+/* --------------------- */
+/* -    Variables.     - */
+/* --------------------- */
+static int Cx, Cy1, Cy2;
+static int /*a1, */a2, a3, a4, a5, a6, a7, a8, a9;
+static int k;
+
+static char dx, dy1, dy2;
+static char d2, d3, d4, d5, d6, d7, d8, d9, d0;
+static char dck;
+
+/*****************************************
+    Accelerometer Initialization Functions
+*****************************************/
+
+int set_hardware_offset(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata,
+                  char offset_x, char offset_y1, char offset_y2)
+{
+       char data;
+       int result = ML_SUCCESS;
+
+       data = offset_x & 0x3f;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_OFFSET_X, data);
+       ERROR_CHECK(result);
+
+       data = offset_y1 & 0x3f;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_OFFSET_Y1, data);
+       ERROR_CHECK(result);
+
+       data = offset_y2 & 0x3f;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_OFFSET_Y2, data);
+       ERROR_CHECK(result);
+
+       return result;
+}
+
+int set_measure_command(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata,
+                  int ldtc, int fors, int dlymes)
+{
+       int result = ML_SUCCESS;
+
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_MEASURE_COMMAND, 0x01);
+       ERROR_CHECK(result);
+
+       return result;
+}
+
+int measure_normal(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata,
+                  int *busy, unsigned short *t,
+                  unsigned short *x, unsigned short *y1, unsigned short *y2)
+{
+       unsigned char data[8];
+       unsigned short b, to, xo, y1o, y2o;
+       int result;
+
+       result = set_measure_command(mlsl_handle, slave, pdata, 0, 0, 0);
+       MLOSSleep(2);
+
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+               YAS530_REGADDR_MEASURE_DATA, 8, data);
+       ERROR_CHECK(result);
+       MLOSSleep(2);
+
+       b = (data[0]>>7) & 0x01;
+       to = ((data[0]<<2) & 0x1fc) | ((data[1]>>6) & 0x03);
+       xo = ((data[2]<<5) & 0xfe0) | ((data[3]>>3) & 0x1f);
+       y1o = ((data[4]<<5) & 0xfe0) | ((data[5]>>3) & 0x1f);
+       y2o = ((data[6]<<5) & 0xfe0) | ((data[7]>>3) & 0x1f);
+
+       *busy = b;
+       *t = to;
+       *x = xo;
+       *y1 = y1o;
+       *y2 = y2o;
+
+       return result;
+}
+
+int check_offset(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata,
+                  char offset_x, char offset_y1, char offset_y2,
+                  int *flag_x, int *flag_y1, int *flag_y2)
+{
+       int result;
+       int busy;
+       short t, x, y1, y2;
+
+       result = set_hardware_offset(mlsl_handle, slave, pdata,
+               offset_x, offset_y1, offset_y2);
+       ERROR_CHECK(result);
+
+       result = measure_normal(mlsl_handle, slave, pdata,
+               &busy, &t, &x, &y1, &y2);
+       ERROR_CHECK(result);
+
+       *flag_x = 0;
+       *flag_y1 = 0;
+       *flag_y2 = 0;
+
+       if (x > 2048)
+               *flag_x = 1;
+       if (y1 > 2048)
+               *flag_y1 = 1;
+       if (y2 > 2048)
+               *flag_y2 = 1;
+       if (x < 2048)
+               *flag_x = -1;
+       if (y1 < 2048)
+               *flag_y1 = -1;
+       if (y2 < 2048)
+               *flag_y2 = -1;
+
+       return result;
+}
+
+int measure_and_set_offset(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata,
+                  char *offset)
+{
+       int i;
+       int result = ML_SUCCESS;
+       char offset_x = 0, offset_y1 = 0, offset_y2 = 0;
+       int flag_x = 0, flag_y1 = 0, flag_y2 = 0;
+       static const int correct[5] = {16, 8, 4, 2, 1};
+
+       for (i = 0; i < 5; i++) {
+               result = check_offset(mlsl_handle, slave, pdata,
+                       offset_x, offset_y1, offset_y2,
+                       &flag_x, &flag_y1, &flag_y2);
+               ERROR_CHECK(result);
+
+               if (flag_x)
+                       offset_x += flag_x * correct[i];
+               if (flag_y1)
+                       offset_y1 += flag_y1 * correct[i];
+               if (flag_y2)
+                       offset_y2 += flag_y2 * correct[i];
+       }
+
+       result = set_hardware_offset(mlsl_handle, slave, pdata,
+               offset_x, offset_y1, offset_y2);
+       ERROR_CHECK(result);
+
+       offset[0] = offset_x;
+       offset[1] = offset_y1;
+       offset[2] = offset_y2;
+
+       return result;
+}
+
+void coordinate_conversion(short x, short y1, short y2, short t,
+                                                 int *xo, int *yo, int *zo)
+{
+       int sx, sy1, sy2, sy, sz;
+       int hx, hy, hz;
+
+       sx  = x - (Cx  * t) / 100;
+       sy1 = y1 - (Cy1 * t) / 100;
+       sy2 = y2 - (Cy2 * t) / 100;
+
+       sy = sy1 - sy2;
+       sz = -sy1 - sy2;
+
+       hx = k * ((100 * sx + a2 * sy + a3 * sz) / 10);
+       hy = k * ((a4 * sx + a5 * sy + a6 * sz) / 10);
+       hz = k * ((a7 * sx + a8 * sy + a9 * sz) / 10);
+
+       *xo = hx;
+       *yo = hy;
+       *zo = hz;
+}
+
+int yas530_suspend(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       return result;
+}
+
+int yas530_resume(void *mlsl_handle,
+                 struct ext_slave_descr *slave,
+                 struct ext_slave_platform_data *pdata)
+{
+       int result = ML_SUCCESS;
+
+       unsigned char dummyData = 0x00;
+       char offset[3] = {0, 0, 0};
+       unsigned char data[16];
+       unsigned char read_reg[1];
+
+       /* =============================================== */
+
+       /* Step 1 - Test register initialization */
+       dummyData = 0x00;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_TEST1, dummyData);
+       ERROR_CHECK(result);
+
+       result =
+           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+                                 YAS530_REGADDR_TEST2, dummyData);
+       ERROR_CHECK(result);
+
+       /* Device ID read  */
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+               YAS530_REGADDR_DEVICE_ID, 1, read_reg);
+
+       /*Step 2 Read the CAL register */
+       /* CAL data read */
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+               YAS530_REGADDR_CAL, 16, data);
+       ERROR_CHECK(result);
+       /* CAL data Second Read */
+       result = MLSLSerialRead(mlsl_handle, pdata->address,
+               YAS530_REGADDR_CAL, 16, data);
+       ERROR_CHECK(result);
+
+       /*Cal data */
+       dx = data[0];
+       dy1 = data[1];
+       dy2 = data[2];
+       d2 = (data[3]>>2) & 0x03f;
+       d3 = ((data[3]<<2) & 0x0c) | ((data[4]>>6) & 0x03);
+       d4 = data[4] & 0x3f;
+       d5 = (data[5]>>2) & 0x3f;
+       d6 = ((data[5]<<4) & 0x30) | ((data[6]>>4) & 0x0f);
+       d7 = ((data[6]<<3) & 0x78) | ((data[7]>>5) & 0x07);
+       d8 = ((data[7]<<1) & 0x3e) | ((data[8]>>7) & 0x01);
+       d9 = ((data[8]<<1) & 0xfe) | ((data[9]>>7) & 0x01);
+       d0 = (data[9]>>2) & 0x1f;
+       dck = ((data[9]<<1) & 0x06) | ((data[10]>>7) & 0x01);
+
+
+       /*Correction Data */
+       Cx = dx * 6 - 768;
+       Cy1 = dy1 * 6 - 768;
+       Cy2 = dy2 * 6 - 768;
+       a2 = d2 - 32;
+       a3 = d3 - 8;
+       a4 = d4 - 32;
+       a5 = d5 + 38;
+       a6 = d6 - 32;
+       a7 = d7 - 64;
+       a8 = d8 - 32;
+       a9 = d9;
+       k = d0 + 10;
+
+       /*Obtain the [49:47] bits */
+       dck &= 0x07;
+
+       /*Step 3 : Storing the CONFIG with the CLK value */
+       dummyData = 0x00 | (dck << 2);
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_CONFIG, dummyData);
+       ERROR_CHECK(result);
+
+       /*Step 4 : Set Acquisition Interval Register */
+       dummyData = 0x00;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_MEASURE_INTERVAL, dummyData);
+       ERROR_CHECK(result);
+
+       /*Step 5 : Reset Coil */
+       dummyData = 0x00;
+       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
+               YAS530_REGADDR_ACTUATE_INIT_COIL, dummyData);
+       ERROR_CHECK(result);
+
+       /* Offset Measurement and Set*/
+       result = measure_and_set_offset(mlsl_handle, slave, pdata, offset);
+       ERROR_CHECK(result);
+
+       return result;
+}
+
+int yas530_read(void *mlsl_handle,
+               struct ext_slave_descr *slave,
+               struct ext_slave_platform_data *pdata, unsigned char *data)
+{
+       int result = ML_SUCCESS;
+
+       int busy;
+       short t, x, y1, y2;
+       int xyz[3];
+       short rawfixed[3];
+
+       result = measure_normal(mlsl_handle, slave, pdata,
+                       &busy, &t, &x, &y1, &y2);
+       ERROR_CHECK(result);
+
+       coordinate_conversion(x, y1, y2, t, &xyz[0], &xyz[1], &xyz[2]);
+
+       rawfixed[0] = (short) (xyz[0]/100);
+       rawfixed[1] = (short) (xyz[1]/100);
+       rawfixed[2] = (short) (xyz[2]/100);
+
+       data[0] = rawfixed[0]>>8;
+       data[1] = rawfixed[0] & 0xFF;
+       data[2] = rawfixed[1]>>8;
+       data[3] = rawfixed[1] & 0xFF;
+       data[4] = rawfixed[2]>>8;
+       data[5] = rawfixed[2] & 0xFF;
+
+       return result;
+}
+
+struct ext_slave_descr yas530_descr = {
+       /*.init             = */ NULL,
+       /*.exit             = */ NULL,
+       /*.suspend          = */ yas530_suspend,
+       /*.resume           = */ yas530_resume,
+       /*.read             = */ yas530_read,
+       /*.config           = */ NULL,
+       /*.get_config       = */ NULL,
+       /*.name             = */ "yas530",
+       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
+       /*.id               = */ COMPASS_ID_YAS530,
+       /*.reg              = */ 0x06,
+       /*.len              = */ 6,
+       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
+       /*.range            = */ {3276, 8001},
+};
+
+struct ext_slave_descr *yas530_get_slave_descr(void)
+{
+       return &yas530_descr;
+}
+EXPORT_SYMBOL(yas530_get_slave_descr);
+
+/**
+ *  @}
+**/
old mode 100644 (file)
new mode 100755 (executable)
index ceee285..f2f9ea7
@@ -70,14 +70,14 @@ extern "C" {
 #else
        /* Based off the log priorities in android
           /system/core/include/android/log.h */
-#define MPL_LOG_UNKNOWN (0)
-#define MPL_LOG_DEFAULT (1)
-#define MPL_LOG_VERBOSE (2)
-#define MPL_LOG_DEBUG (3)
-#define MPL_LOG_INFO (4)
-#define MPL_LOG_WARN (5)
-#define MPL_LOG_ERROR (6)
-#define MPL_LOG_SILENT (8)
+#define MPL_LOG_UNKNOWN                (0)
+#define MPL_LOG_DEFAULT                (1)
+#define MPL_LOG_VERBOSE                (2)
+#define MPL_LOG_DEBUG          (3)
+#define MPL_LOG_INFO           (4)
+#define MPL_LOG_WARN           (5)
+#define MPL_LOG_ERROR          (6)
+#define MPL_LOG_SILENT         (8)
 #endif
 
 
@@ -101,9 +101,13 @@ extern "C" {
  */
 #ifndef MPL_LOGV
 #if MPL_LOG_NDEBUG
-#define MPL_LOGV(...) ((void)0)
+#define MPL_LOGV(fmt, ...)                                             \
+       do {                                                            \
+               if (0)                                                  \
+                       MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__);\
+       } while (0)
 #else
-#define MPL_LOGV(...) ((void)MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, __VA_ARGS__))
+#define MPL_LOGV(fmt, ...) MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
 #endif
 #endif
 
@@ -113,11 +117,12 @@ extern "C" {
 
 #ifndef MPL_LOGV_IF
 #if MPL_LOG_NDEBUG
-#define MPL_LOGV_IF(cond, ...)   ((void)0)
+#define MPL_LOGV_IF(cond, fmt, ...)  \
+       do { if (0) MPL_LOG(fmt, ##__VA_ARGS__); } while (0)
 #else
-#define MPL_LOGV_IF(cond, ...) \
+#define MPL_LOGV_IF(cond, fmt, ...) \
        ((CONDITION(cond))                                              \
-               ? ((void)MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, __VA_ARGS__)) \
+               ? MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__) \
                : (void)0)
 #endif
 #endif
@@ -126,13 +131,13 @@ extern "C" {
  * Simplified macro to send a debug log message using the current MPL_LOG_TAG.
  */
 #ifndef MPL_LOGD
-#define MPL_LOGD(...) ((void)MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, __VA_ARGS__))
+#define MPL_LOGD(fmt, ...) MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
 #endif
 
 #ifndef MPL_LOGD_IF
-#define MPL_LOGD_IF(cond, ...) \
+#define MPL_LOGD_IF(cond, fmt, ...) \
        ((CONDITION(cond))                                             \
-               ? ((void)MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, __VA_ARGS__)) \
+               ? MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, fmt, ##__VA_ARGS__)  \
                : (void)0)
 #endif
 
@@ -140,13 +145,13 @@ extern "C" {
  * Simplified macro to send an info log message using the current MPL_LOG_TAG.
  */
 #ifndef MPL_LOGI
-#define MPL_LOGI(...) ((void)MPL_LOG(LOG_INFO, MPL_LOG_TAG, __VA_ARGS__))
+#define MPL_LOGI(fmt, ...) MPL_LOG(LOG_INFO, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
 #endif
 
 #ifndef MPL_LOGI_IF
-#define MPL_LOGI_IF(cond, ...) \
+#define MPL_LOGI_IF(cond, fmt, ...) \
        ((CONDITION(cond))                                              \
-               ? ((void)MPL_LOG(LOG_INFO, MPL_LOG_TAG, __VA_ARGS__))   \
+               ? MPL_LOG(LOG_INFO, MPL_LOG_TAG, fmt, ##__VA_ARGS__)   \
                : (void)0)
 #endif
 
@@ -154,13 +159,17 @@ extern "C" {
  * Simplified macro to send a warning log message using the current MPL_LOG_TAG.
  */
 #ifndef MPL_LOGW
-#define MPL_LOGW(...) ((void)MPL_LOG(LOG_WARN, MPL_LOG_TAG, __VA_ARGS__))
+#ifdef __KERNEL__
+#define MPL_LOGW(fmt, ...) printk(KERN_WARNING MPL_LOG_TAG fmt, ##__VA_ARGS__)
+#else
+#define MPL_LOGW(fmt, ...) MPL_LOG(LOG_WARN, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
+#endif
 #endif
 
 #ifndef MPL_LOGW_IF
-#define MPL_LOGW_IF(cond, ...) \
+#define MPL_LOGW_IF(cond, fmt, ...) \
        ((CONDITION(cond))                                             \
-               ? ((void)MPL_LOG(LOG_WARN, MPL_LOG_TAG, __VA_ARGS__))  \
+               ? MPL_LOG(LOG_WARN, MPL_LOG_TAG, fmt, ##__VA_ARGS__)   \
                : (void)0)
 #endif
 
@@ -168,13 +177,17 @@ extern "C" {
  * Simplified macro to send an error log message using the current MPL_LOG_TAG.
  */
 #ifndef MPL_LOGE
-#define MPL_LOGE(...) ((void)MPL_LOG(LOG_ERROR, MPL_LOG_TAG, __VA_ARGS__))
+#ifdef __KERNEL__
+#define MPL_LOGE(fmt, ...) printk(KERN_ERR MPL_LOG_TAG fmt, ##__VA_ARGS__)
+#else
+#define MPL_LOGE(fmt, ...) MPL_LOG(LOG_ERROR, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
+#endif
 #endif
 
 #ifndef MPL_LOGE_IF
-#define MPL_LOGE_IF(cond, ...) \
+#define MPL_LOGE_IF(cond, fmt, ...) \
        ((CONDITION(cond))                                             \
-               ? ((void)MPL_LOG(LOG_ERROR, MPL_LOG_TAG, __VA_ARGS__)) \
+               ? MPL_LOG(LOG_ERROR, MPL_LOG_TAG, fmt, ##__VA_ARGS__)  \
                : (void)0)
 #endif
 
@@ -186,35 +199,43 @@ extern "C" {
  * It is NOT stripped from release builds.  Note that the condition test
  * is -inverted- from the normal assert() semantics.
  */
-#define MPL_LOG_ALWAYS_FATAL_IF(cond, ...) \
+#define MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ...) \
        ((CONDITION(cond))                                         \
-               ? ((void)android_printAssert(#cond, MPL_LOG_TAG, __VA_ARGS__)) \
+               ? ((void)android_printAssert(#cond, MPL_LOG_TAG,   \
+                                               fmt, ##__VA_ARGS__))    \
                : (void)0)
 
-#define MPL_LOG_ALWAYS_FATAL(...) \
-       (((void)android_printAssert(NULL, MPL_LOG_TAG, __VA_ARGS__)))
+#define MPL_LOG_ALWAYS_FATAL(fmt, ...) \
+       (((void)android_printAssert(NULL, MPL_LOG_TAG, fmt, ##__VA_ARGS__)))
 
 /*
  * Versions of MPL_LOG_ALWAYS_FATAL_IF and MPL_LOG_ALWAYS_FATAL that
  * are stripped out of release builds.
  */
 #if MPL_LOG_NDEBUG
-
-#define MPL_LOG_FATAL_IF(cond, ...) ((void)0)
-#define MPL_LOG_FATAL(...)          ((void)0)
-
+#define MPL_LOG_FATAL_IF(cond, fmt, ...)                               \
+       do {                                                            \
+               if (0)                                                  \
+                       MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ##__VA_ARGS__); \
+       } while (0)
+#define MPL_LOG_FATAL(fmt, ...)                                                \
+       do {                                                            \
+               if (0)                                                  \
+                       MPL_LOG_ALWAYS_FATAL(fmt, ##__VA_ARGS__)        \
+       } while (0)
 #else
-
-#define MPL_LOG_FATAL_IF(cond, ...) MPL_LOG_ALWAYS_FATAL_IF(cond, __VA_ARGS__)
-#define MPL_LOG_FATAL(...)          MPL_LOG_ALWAYS_FATAL(__VA_ARGS__)
-
+#define MPL_LOG_FATAL_IF(cond, fmt, ...) \
+       MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ##__VA_ARGS__)
+#define MPL_LOG_FATAL(fmt, ...) \
+       MPL_LOG_ALWAYS_FATAL(fmt, ##__VA_ARGS__)
 #endif
 
 /*
  * Assertion that generates a log message when the assertion fails.
  * 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, fmt, ...)                 \
+       MPL_LOG_FATAL_IF(!(cond), fmt, ##__VA_ARGS__)
 
 /* --------------------------------------------------------------------- */
 
@@ -227,8 +248,8 @@ extern "C" {
  * The second argument may be NULL or "" to indicate the "global" tag.
  */
 #ifndef MPL_LOG
-#define MPL_LOG(priority, tag, ...) \
-    MPL_LOG_PRI(priority, tag, __VA_ARGS__)
+#define MPL_LOG(priority, tag, fmt, ...)               \
+       MPL_LOG_PRI(priority, tag, fmt, ##__VA_ARGS__)
 #endif
 
 /*
@@ -236,14 +257,14 @@ extern "C" {
  */
 #ifndef MPL_LOG_PRI
 #ifdef ANDROID
-#define MPL_LOG_PRI(priority, tag, ...) \
-       LOG(priority, tag, __VA_ARGS__)
+#define MPL_LOG_PRI(priority, tag, fmt, ...) \
+       LOG(priority, tag, fmt, ##__VA_ARGS__)
 #elif defined __KERNEL__
-#define MPL_LOG_PRI(priority, tag, ...) \
-       printk(MPL_##priority tag __VA_ARGS__)
+#define MPL_LOG_PRI(priority, tag, fmt, ...) \
+       pr_debug(MPL_##priority tag fmt, ##__VA_ARGS__)
 #else
-#define MPL_LOG_PRI(priority, tag, ...) \
-       _MLPrintLog(MPL_##priority, tag, __VA_ARGS__)
+#define MPL_LOG_PRI(priority, tag, fmt, ...) \
+       _MLPrintLog(MPL_##priority, tag, fmt, ##__VA_ARGS__)
 #endif
 #endif
 
@@ -255,8 +276,7 @@ extern "C" {
 #define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
     android_vprintLog(priority, NULL, tag, fmt, args)
 #elif defined __KERNEL__
-#define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
-    vprintk(MPL_##priority tag fmt, args)
+/* not allowed in the Kernel because there is no dev_dbg that takes a va_list */
 #else
 #define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
     _MLPrintVaLog(priority, NULL, tag, fmt, args)
old mode 100644 (file)
new mode 100755 (executable)
index 220103b..9cc4cf6
@@ -1,13 +1,21 @@
 /*
  $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/>.
+  $
  */
-/*******************************************************************************
- *
- * $Id: mldl_cfg.c 4635 2011-01-27 07:49:49Z nroyer $
- *
- ******************************************************************************/
 
 /**
  *  @addtogroup MLDL
@@ -289,7 +297,7 @@ static int MLDLGetSiliconRev(struct mldl_cfg *pdata,
 
        result = MLSLSerialReadMem(mlsl_handle, pdata->addr,
                                   memAddr, 1, &index);
-       ERROR_CHECK(result)
+       ERROR_CHECK(result);
        if (result)
                return result;
        index >>= 2;
@@ -298,7 +306,7 @@ static int MLDLGetSiliconRev(struct mldl_cfg *pdata,
        result =
            MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
                                  MPUREG_BANK_SEL, 0);
-       ERROR_CHECK(result)
+       ERROR_CHECK(result);
        if (result)
                return result;
 
@@ -322,20 +330,28 @@ static int MLDLGetSiliconRev(struct mldl_cfg *pdata,
 }
 
 /**
- *  @brief      Enable/Disable the use MPU's VDDIO level shifters.
- *              When enabled the voltage interface with AUX or other external
- *              accelerometer is using Vlogic instead of VDD (supply).
+ *  @brief  Enable / Disable the use MPU's secondary I2C interface level
+ *          shifters.
+ *          When enabled the secondary I2C interface to which the external
+ *          device is connected runs at VDD voltage (main supply).
+ *          When disabled the 2nd interface runs at VDDIO voltage.
+ *          See the device specification for more details.
+ *
+ *  @note   using this API may produce unpredictable results, depending on how
+ *          the MPU and slave device are setup on the target platform.
+ *          Use of this API should entirely be restricted to system
+ *          integrators. Once the correct value is found, there should be no
+ *          need to change the level shifter at runtime.
  *
- *  @note       Must be called after MLSerialOpen().
- *  @note       Typically be called before MLDmpOpen().
- *              If called after MLDmpOpen(), must be followed by a call to
- *              MLDLApplyLevelShifterBit() to write the setting on the hw.
+ *  @pre    Must be called after MLSerialOpen().
+ *  @note   Typically called before MLDmpOpen().
  *
- *  @param[in]  enable
- *                  1 to enable, 0 to disable
+ *  @param[in]  enable:
+ *                  0 to run at VDDIO (default),
+ *                  1 to run at VDD.
  *
- *  @return     ML_SUCCESS if successfull, a non-zero error code otherwise.
-**/
+ *  @return ML_SUCCESS if successfull, a non-zero error code otherwise.
+ */
 static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
                                  void *mlsl_handle,
                                  unsigned char enable)
@@ -350,9 +366,9 @@ static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
                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 --*/
+       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;
@@ -551,6 +567,7 @@ static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
 
        /* Reset if requested */
        if (reset) {
+               MPL_LOGV("Reset MPU3050\n");
                result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
                                        MPUREG_PWR_MGM, b | BIT_H_RESET);
                ERROR_CHECK(result);
@@ -1114,6 +1131,7 @@ int mpu3050_open(struct mldl_cfg *mldl_cfg,
 {
        int result;
        /* Default is Logic HIGH, pushpull, latch disabled, anyread to clear */
+       mldl_cfg->ignore_system_suspend = FALSE;
        mldl_cfg->int_config = BIT_INT_ANYRD_2CLEAR | BIT_DMP_INT_EN;
        mldl_cfg->clk_src = MPU_CLK_SEL_PLLGYROZ;
        mldl_cfg->lpf = MPU_FILTER_42HZ;
@@ -1294,7 +1312,10 @@ int mpu3050_close(struct mldl_cfg *mldl_cfg,
 /**
  *  @brief  resume the MPU3050 device and all the other sensor
  *          devices from their low power state.
- *  @param  mlsl_handle
+ *
+ *  @param  mldl_cfg
+ *              pointer to the configuration structure
+ *  @param  gyro_handle
  *              the main file handle to the MPU3050 device.
  *  @param  accel_handle
  *              an handle to the accelerometer device, if sitting
@@ -1311,6 +1332,10 @@ int mpu3050_close(struct mldl_cfg *mldl_cfg,
  *              onto a separate bus. Can match mlsl_handle if
  *              the pressure sensor device operates on the same
  *              primary bus of MPU.
+ *  @param  resume_gyro
+ *              whether resuming the gyroscope device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
  *  @param  resume_accel
  *              whether resuming the accelerometer device is
  *              actually needed (if the device supports low power
@@ -1337,7 +1362,7 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg,
 {
        int result = ML_SUCCESS;
 
-#ifdef CONFIG_SENSORS_MPU_DEBUG
+#ifdef CONFIG_MPU_SENSORS_DEBUG
        mpu_print_cfg(mldl_cfg);
 #endif
 
@@ -1367,15 +1392,15 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg,
                                                 &mldl_cfg->pdata->accel);
                ERROR_CHECK(result);
                mldl_cfg->accel_is_suspended = FALSE;
+       }
 
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
-                       result = mpu_set_slave(mldl_cfg,
-                                              gyro_handle,
-                                              mldl_cfg->accel,
-                                              &mldl_cfg->pdata->accel);
-                       ERROR_CHECK(result);
-               }
+       if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->accel_is_suspended &&
+               EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
+               result = mpu_set_slave(mldl_cfg,
+                               gyro_handle,
+                               mldl_cfg->accel,
+                               &mldl_cfg->pdata->accel);
+               ERROR_CHECK(result);
        }
 
        if (resume_compass && mldl_cfg->compass_is_suspended) {
@@ -1390,15 +1415,15 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg,
                                                   compass);
                ERROR_CHECK(result);
                mldl_cfg->compass_is_suspended = FALSE;
+       }
 
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
-                       result = mpu_set_slave(mldl_cfg,
-                                              gyro_handle,
-                                              mldl_cfg->compass,
-                                              &mldl_cfg->pdata->compass);
-                       ERROR_CHECK(result);
-               }
+       if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->compass_is_suspended &&
+               EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
+               result = mpu_set_slave(mldl_cfg,
+                               gyro_handle,
+                               mldl_cfg->compass,
+                               &mldl_cfg->pdata->compass);
+               ERROR_CHECK(result);
        }
 
        if (resume_pressure && mldl_cfg->pressure_is_suspended) {
@@ -1412,17 +1437,18 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg,
                                                    &mldl_cfg->pdata->
                                                    pressure);
                ERROR_CHECK(result);
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
-                       result = mpu_set_slave(mldl_cfg,
-                                              gyro_handle,
-                                              mldl_cfg->pressure,
-                                              &mldl_cfg->pdata->pressure);
-                       ERROR_CHECK(result);
-               }
                mldl_cfg->pressure_is_suspended = FALSE;
        }
 
+       if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->pressure_is_suspended &&
+               EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
+               result = mpu_set_slave(mldl_cfg,
+                               gyro_handle,
+                               mldl_cfg->pressure,
+                               &mldl_cfg->pdata->pressure);
+               ERROR_CHECK(result);
+       }
+
        /* Now start */
        if (resume_gyro) {
                result = dmp_start(mldl_cfg, gyro_handle);
@@ -1432,7 +1458,6 @@ int mpu3050_resume(struct mldl_cfg *mldl_cfg,
        return result;
 }
 
-
 /**
  *  @brief  suspend the MPU3050 device and all the other sensor
  *          devices into their low power state.
@@ -1481,13 +1506,14 @@ int mpu3050_suspend(struct mldl_cfg *mldl_cfg,
 
        if (suspend_gyro && !mldl_cfg->gyro_is_suspended) {
 #ifdef M_HW
+               return ML_SUCCESS;
                /* This puts the bus into bypass mode */
                result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, 1);
                ERROR_CHECK(result);
                result = mpu60xx_pwr_mgmt(mldl_cfg, gyro_handle, 0, SLEEP);
 #else
                result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle,
-                                         0, SLEEP, 0, 0, 0);
+                                       0, SLEEP, 0, 0, 0);
 #endif
                ERROR_CHECK(result);
        }
@@ -1545,6 +1571,10 @@ int mpu3050_suspend(struct mldl_cfg *mldl_cfg,
 /**
  *  @brief  read raw sensor data from the accelerometer device
  *          in use.
+ *  @param  mldl_cfg
+ *              A pointer to the struct mldl_cfg data structure.
+ *  @param  accel_handle
+ *              The handle to the device the accelerometer is connected to.
  *  @param  data
  *              a buffer to store the raw sensor data.
  *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
@@ -1553,10 +1583,14 @@ int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
                       void *accel_handle, unsigned char *data)
 {
        if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->read)
-               return mldl_cfg->accel->read(accel_handle,
-                                            mldl_cfg->accel,
-                                            &mldl_cfg->pdata->accel,
-                                            data);
+               if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus)
+                       && (!mldl_cfg->gyro_is_bypassed))
+                       return ML_ERROR_FEATURE_NOT_ENABLED;
+               else
+                       return mldl_cfg->accel->read(accel_handle,
+                                                    mldl_cfg->accel,
+                                                    &mldl_cfg->pdata->accel,
+                                                    data);
        else
                return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
 }
@@ -1564,6 +1598,10 @@ int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
 /**
  *  @brief  read raw sensor data from the compass device
  *          in use.
+ *  @param  mldl_cfg
+ *              A pointer to the struct mldl_cfg data structure.
+ *  @param  compass_handle
+ *              The handle to the device the compass is connected to.
  *  @param  data
  *              a buffer to store the raw sensor data.
  *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
@@ -1572,10 +1610,14 @@ int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
                         void *compass_handle, unsigned char *data)
 {
        if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->read)
-               return mldl_cfg->compass->read(compass_handle,
-                                              mldl_cfg->compass,
-                                              &mldl_cfg->pdata->compass,
-                                              data);
+               if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus)
+                       && (!mldl_cfg->gyro_is_bypassed))
+                       return ML_ERROR_FEATURE_NOT_ENABLED;
+               else
+                       return mldl_cfg->compass->read(compass_handle,
+                                               mldl_cfg->compass,
+                                               &mldl_cfg->pdata->compass,
+                                               data);
        else
                return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
 }
@@ -1583,6 +1625,10 @@ int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
 /**
  *  @brief  read raw sensor data from the pressure device
  *          in use.
+ *  @param  mldl_cfg
+ *              A pointer to the struct mldl_cfg data structure.
+ *  @param  pressure_handle
+ *              The handle to the device the pressure sensor is connected to.
  *  @param  data
  *              a buffer to store the raw sensor data.
  *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
@@ -1591,10 +1637,15 @@ int mpu3050_read_pressure(struct mldl_cfg *mldl_cfg,
                         void *pressure_handle, unsigned char *data)
 {
        if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->read)
-               return mldl_cfg->pressure->read(pressure_handle,
-                                               mldl_cfg->pressure,
-                                               &mldl_cfg->pdata->pressure,
-                                               data);
+               if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus)
+                       && (!mldl_cfg->gyro_is_bypassed))
+                       return ML_ERROR_FEATURE_NOT_ENABLED;
+               else
+                       return mldl_cfg->pressure->read(
+                               pressure_handle,
+                               mldl_cfg->pressure,
+                               &mldl_cfg->pdata->pressure,
+                               data);
        else
                return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
 }
@@ -1640,6 +1691,48 @@ int mpu3050_config_pressure(struct mldl_cfg *mldl_cfg,
                return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
 }
 
+int mpu3050_get_config_accel(struct mldl_cfg *mldl_cfg,
+                       void *accel_handle,
+                       struct ext_slave_config *data)
+{
+       if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->get_config)
+               return mldl_cfg->accel->get_config(accel_handle,
+                                               mldl_cfg->accel,
+                                               &mldl_cfg->pdata->accel,
+                                               data);
+       else
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+}
+
+int mpu3050_get_config_compass(struct mldl_cfg *mldl_cfg,
+                       void *compass_handle,
+                       struct ext_slave_config *data)
+{
+       if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->get_config)
+               return mldl_cfg->compass->get_config(compass_handle,
+                                               mldl_cfg->compass,
+                                               &mldl_cfg->pdata->compass,
+                                               data);
+       else
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+}
+
+int mpu3050_get_config_pressure(struct mldl_cfg *mldl_cfg,
+                               void *pressure_handle,
+                               struct ext_slave_config *data)
+{
+       if (NULL != mldl_cfg->pressure &&
+           NULL != mldl_cfg->pressure->get_config)
+               return mldl_cfg->pressure->get_config(pressure_handle,
+                                               mldl_cfg->pressure,
+                                               &mldl_cfg->pdata->pressure,
+                                               data);
+       else
+               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
 
 /**
  *@}
old mode 100644 (file)
new mode 100755 (executable)
index 91f349e..ad6a211
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -80,6 +93,7 @@
 struct mldl_cfg {
        /* MPU related configuration */
        unsigned long requested_sensors;
+       unsigned char ignore_system_suspend;
        unsigned char addr;
        unsigned char int_config;
        unsigned char ext_sync;
@@ -167,6 +181,16 @@ int mpu3050_config_pressure(struct mldl_cfg *mldl_cfg,
                            void *pressure_handle,
                            struct ext_slave_config *data);
 
+int mpu3050_get_config_accel(struct mldl_cfg *mldl_cfg,
+                            void *accel_handle,
+                            struct ext_slave_config *data);
+int mpu3050_get_config_compass(struct mldl_cfg *mldl_cfg,
+                              void *compass_handle,
+                              struct ext_slave_config *data);
+int mpu3050_get_config_pressure(struct mldl_cfg *mldl_cfg,
+                               void *pressure_handle,
+                               struct ext_slave_config *data);
+
 
 #endif                         /* __MLDL_CFG_H__ */
 
old mode 100644 (file)
new mode 100755 (executable)
index 091c0a6..ced9ba4
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 /**
  * @defgroup
old mode 100644 (file)
new mode 100755 (executable)
index e65dd62..4ebb86c
@@ -1,7 +1,20 @@
 /*
  $License:
     Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
- $
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
  */
 
 #ifndef _MLOS_H
old mode 100644 (file)
new mode 100755 (executable)
index d1bcf88..cb16051
@@ -1,7 +1,20 @@
 /*
  $License:
     Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
- $
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
  */
 
 #include "mlsl.h"
@@ -83,7 +96,8 @@ tMLError MLSLSerialWriteSingle(void *sl_handle,
  */
 tMLError MLSLSerialWrite(void *sl_handle,
                         unsigned char slaveAddr,
-                        unsigned short length, unsigned char const *data)
+                        unsigned short length,
+                        unsigned char const *data)
 {
        tMLError result;
        const unsigned short dataLength = length - 1;
@@ -174,10 +188,9 @@ tMLError MLSLSerialWriteMem(void *sl_handle,
        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);
+               pr_err("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) {
old mode 100644 (file)
new mode 100755 (executable)
index 4f01293..76f69c7
@@ -1,7 +1,20 @@
 /*
  $License:
     Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
- $
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
  */
 
 #ifndef __MSSL_H__
old mode 100644 (file)
new mode 100755 (executable)
index 3521c00..d0b27fa
@@ -1,13 +1,21 @@
 /*
  $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/>.
+  $
  */
-/******************************************************************************
- *
- * $Id: mltypes.h 4598 2011-01-25 19:33:13Z prao $
- *
- *****************************************************************************/
 
 /**
  *  @defgroup MLERROR
 ---------------------------*/
 
 /**
- * @struct tMLError The MPL Error Code return type.
+ *  @struct tMLError mltypes.h "mltypes"
+ *  @brief  The MPL Error Code return type.
  *
- * @code
+ *  @code
  *      typedef unsigned char tMLError;
- * @endcode
+ *  @endcode
  */
 typedef unsigned char tMLError;
 
@@ -127,13 +136,13 @@ typedef int_fast8_t bool;
 /* - ML Errors. - */
 #define ERROR_NAME(x)   (#x)
 #define ERROR_CHECK(x)                                                  \
-       {                                                               \
+       do {                                                            \
                if (ML_SUCCESS != x) {                                  \
                        MPL_LOGE("%s|%s|%d returning %d\n",             \
                                __FILE__, __func__, __LINE__, x);       \
                        return x;                                       \
                }                                                       \
-       }
+       } while (0)
 
 #define ERROR_CHECK_FIRST(first, x)                                     \
        { if (ML_SUCCESS == first) first = x; }
@@ -200,6 +209,12 @@ typedef int_fast8_t bool;
 #define ML_ERROR_CALIBRATION_LEN        (77)
 #define ML_ERROR_CALIBRATION_CHECKSUM   (78)
 
+/* Accel errors */
+#define ML_ERROR_ACCEL_DATA_OVERFLOW    (79)
+#define ML_ERROR_ACCEL_DATA_UNDERFLOW   (80)
+#define ML_ERROR_ACCEL_DATA_NOT_READY   (81)
+#define ML_ERROR_ACCEL_DATA_ERROR       (82)
+
 /* For Linux coding compliance */
 #ifndef __KERNEL__
 #define EXPORT_SYMBOL(x)
old mode 100644 (file)
new mode 100755 (executable)
index 26bcebc..e84b63f
@@ -1,9 +1,5 @@
 /*
-    mpu-dev.c - mpu3050 char device interface
-
-    Copyright (C) 1995-97 Simon G. Vogl
-    Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
-    Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
+ $License:
     Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
 
     This program is free software; you can redistribute it and/or modify
@@ -18,8 +14,7 @@
 
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/* Code inside mpudev_ioctl_rdrw is copied from i2c-dev.c
+  $
  */
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
@@ -36,7 +31,9 @@
 #include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/pm.h>
-
+#include <linux/mutex.h>
+#include <linux/suspend.h>
+#include <linux/poll.h>
 #ifdef CONFIG_HAS_EARLYSUSPEND
 #include <linux/earlysuspend.h>
 #endif
@@ -65,44 +62,97 @@ struct mpu_private_data {
 #ifdef CONFIG_HAS_EARLYSUSPEND
        struct early_suspend early_suspend;
 #endif
+       struct mutex mutex;
+       wait_queue_head_t mpu_event_wait;
+       struct completion completion;
+       struct timer_list timeout;
+       struct notifier_block nb;
+       struct mpuirq_data mpu_pm_event;
+       int response_timeout;   /* In seconds */
+       unsigned long event;
+       int pid;
 };
 
-static int pid;
-struct i2c_msg1 {
-       __u16 addr;     /* slave address                        */
-       __u16 flags;
-#define I2C_M_TEN              0x0010  /* this is a ten bit chip address */
-#define I2C_M_RD               0x0001  /* read data, from slave to master */
-#define I2C_M_NOSTART          0x4000  /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_REV_DIR_ADDR     0x2000  /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_IGNORE_NAK       0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_NO_RD_ACK                0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_RECV_LEN         0x0400  /* length will be first received byte */
-       __u16 len;              /* msg length                           */
-       __u8 *buf;              /* pointer to msg data                  */
-};
-struct i2c_rdwr_ioctl_data1 {
-       struct i2c_msg1 __user *msgs;   /* pointers to i2c_msgs */
-       __u32 nmsgs;                    /* number of i2c_msgs */
-};
 static struct i2c_client *this_client;
 
+
+static void
+mpu_pm_timeout(u_long data)
+{
+       struct mpu_private_data *mpu = (struct mpu_private_data *) data;
+       dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
+       complete(&mpu->completion);
+}
+
+static int mpu_pm_notifier_callback(struct notifier_block *nb,
+                                   unsigned long event,
+                                   void *unused)
+{
+       struct mpu_private_data *mpu =
+               container_of(nb, struct mpu_private_data, nb);
+       struct timeval event_time;
+       dev_dbg(&this_client->adapter->dev, "%s: %ld\n", __func__, event);
+
+       /* Prevent the file handle from being closed before we initialize
+          the completion event */
+       mutex_lock(&mpu->mutex);
+       if (!(mpu->pid) ||
+               (event != PM_SUSPEND_PREPARE && event != PM_POST_SUSPEND)) {
+               mutex_unlock(&mpu->mutex);
+               return NOTIFY_OK;
+       }
+
+       do_gettimeofday(&event_time);
+       mpu->mpu_pm_event.interruptcount++;
+       mpu->mpu_pm_event.irqtime =
+               (((long long) event_time.tv_sec) << 32) +
+               event_time.tv_usec;
+       mpu->mpu_pm_event.data_type = MPUIRQ_DATA_TYPE_PM_EVENT;
+       mpu->mpu_pm_event.data_size = sizeof(unsigned long);
+       mpu->mpu_pm_event.data = &mpu->event;
+
+       if (event == PM_SUSPEND_PREPARE)
+               mpu->event = MPU_PM_EVENT_SUSPEND_PREPARE;
+       if (event == PM_POST_SUSPEND)
+               mpu->event = MPU_PM_EVENT_POST_SUSPEND;
+
+       if (mpu->response_timeout > 0) {
+               mpu->timeout.expires = jiffies + mpu->response_timeout * HZ;
+               add_timer(&mpu->timeout);
+       }
+       INIT_COMPLETION(mpu->completion);
+       mutex_unlock(&mpu->mutex);
+
+       wake_up_interruptible(&mpu->mpu_event_wait);
+       wait_for_completion(&mpu->completion);
+       del_timer_sync(&mpu->timeout);
+       dev_dbg(&this_client->adapter->dev, "%s: %ld DONE\n", __func__, event);
+       return NOTIFY_OK;
+}
+
 static int mpu_open(struct inode *inode, struct file *file)
 {
        struct mpu_private_data *mpu =
            (struct mpu_private_data *) i2c_get_clientdata(this_client);
        struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-
+       int result;
        dev_dbg(&this_client->adapter->dev, "mpu_open\n");
        dev_dbg(&this_client->adapter->dev, "current->pid %d\n",
                current->pid);
-       pid = current->pid;
+       mpu->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 */
 
        /* Reset the sensors to the default */
+       result = mutex_lock_interruptible(&mpu->mutex);
+       if (result) {
+               dev_err(&this_client->adapter->dev,
+                       "%s: mutex_lock_interruptible returned %d\n",
+                       __func__, result);
+               return result;
+       }
        mldl_cfg->requested_sensors = ML_THREE_AXIS_GYRO;
        if (mldl_cfg->accel && mldl_cfg->accel->resume)
                mldl_cfg->requested_sensors |= ML_THREE_AXIS_ACCEL;
@@ -112,7 +162,7 @@ static int mpu_open(struct inode *inode, struct file *file)
 
        if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
                mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
-
+       mutex_unlock(&mpu->mutex);
        return 0;
 }
 
@@ -129,136 +179,80 @@ static int mpu_release(struct inode *inode, struct file *file)
        struct i2c_adapter *pressure_adapter;
        int result = 0;
 
-       pid = 0;
-
        accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
        compass_adapter = i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
        pressure_adapter = i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
+
+       mutex_lock(&mpu->mutex);
        result = mpu3050_suspend(mldl_cfg, client->adapter,
                                 accel_adapter, compass_adapter,
                                 pressure_adapter,
                                 TRUE, TRUE, TRUE, TRUE);
-
+       mpu->pid = 0;
+       mutex_unlock(&mpu->mutex);
+       complete(&mpu->completion);
        dev_dbg(&this_client->adapter->dev, "mpu_release\n");
        return result;
 }
 
-static noinline int mpudev_ioctl_rdrw(struct i2c_client *client,
-                                     unsigned long arg)
+/* read function called when from /dev/mpu is read.  Read from the FIFO */
+static ssize_t mpu_read(struct file *file,
+                       char __user *buf, size_t count, loff_t *offset)
 {
-       struct i2c_rdwr_ioctl_data1 rdwr_arg;
-       struct i2c_msg1 *rdwr_pa;
-       struct i2c_msg *msgs;
-       u8 __user **data_ptrs;
-       int i, res;
-
-       if (copy_from_user(&rdwr_arg,
-                          (struct i2c_rdwr_ioctl_data1 __user *) arg,
-                          sizeof(rdwr_arg)))
-               return -EFAULT;
+       struct mpuirq_data local_mpu_pm_event;
+       struct i2c_client *client =
+           (struct i2c_client *) file->private_data;
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *) i2c_get_clientdata(client);
+       size_t len = sizeof(mpu->mpu_pm_event) + sizeof(unsigned long);
+       int err;
 
-       /* Put an arbitrary limit on the number of messages that can
-        * be sent at once */
-       if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
-               return -EINVAL;
-       msgs = (struct i2c_msg *)kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), GFP_KERNEL);
-       rdwr_pa = (struct i2c_msg1 *)
-           kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg1), GFP_KERNEL);
-       if (!rdwr_pa)
-               return -ENOMEM;
+       if (!mpu->event && (!(file->f_flags & O_NONBLOCK)))
+               wait_event_interruptible(mpu->mpu_event_wait, mpu->event);
 
-       if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
-                          rdwr_arg.nmsgs * sizeof(struct i2c_msg1))) {
-               kfree(rdwr_pa);
-               return -EFAULT;
-       }
+       if (!mpu->event || NULL == buf
+               || count < sizeof(mpu->mpu_pm_event) + sizeof(unsigned long))
+               return 0;
 
-       data_ptrs =
-           kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
-       if (data_ptrs == NULL) {
-               kfree(rdwr_pa);
-               return -ENOMEM;
+       err = copy_from_user(&local_mpu_pm_event, buf,
+                       sizeof(mpu->mpu_pm_event));
+       if (err != 0) {
+               dev_err(&this_client->adapter->dev,
+                       "Copy from user returned %d\n", err);
+               return -EFAULT;
        }
 
-       res = 0;
-       for (i = 0; i < rdwr_arg.nmsgs; i++) {
-               /* Limit the size of the message to a sane amount;
-                * and don't let length change either. */
-               if ((rdwr_pa[i].len > 8192) ||
-                   (rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
-                       res = -EINVAL;
-                       break;
-               }
-               data_ptrs[i] = (u8 __user *) rdwr_pa[i].buf;
-               rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
-               if (rdwr_pa[i].buf == NULL) {
-                       res = -ENOMEM;
-                       break;
-               }
-               if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i],
-                                  rdwr_pa[i].len)) {
-                       ++i;    /* Needs to be kfreed too */
-                       res = -EFAULT;
-                       break;
-               }
-               msgs[i].buf = rdwr_pa[i].buf;
-               msgs[i].len = rdwr_pa[i].len;
-               msgs[i].flags = rdwr_pa[i].flags;
-               msgs[i].addr = rdwr_pa[i].addr;
-
-               msgs[i].scl_rate = 400 * 1000;
-       }
-       if (res < 0) {
-               int j;
-               for (j = 0; j < i; ++j)
-                       kfree(rdwr_pa[j].buf);
-               kfree(data_ptrs);
-               kfree(rdwr_pa);
-               kfree(msgs);
-               return res;
+       mpu->mpu_pm_event.data = local_mpu_pm_event.data;
+       err = copy_to_user((unsigned long __user *)local_mpu_pm_event.data,
+                       &mpu->event,
+                       sizeof(mpu->event));
+       if (err != 0) {
+               dev_err(&this_client->adapter->dev,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
        }
-
-       res = i2c_transfer(client->adapter, msgs,rdwr_arg.nmsgs);
-       while (i-- > 0) {
-               if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
-                       if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
-                                        rdwr_pa[i].len))
-                               res = -EFAULT;
-               }
-               kfree(rdwr_pa[i].buf);
+       err = copy_to_user(buf, &mpu->mpu_pm_event, sizeof(mpu->mpu_pm_event));
+       if (err != 0) {
+               dev_err(&this_client->adapter->dev,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
        }
-       kfree(data_ptrs);
-       kfree(rdwr_pa);
-       kfree(msgs);
-       return res;
+       mpu->event = 0;
+       return len;
 }
 
-/* read function called when from /dev/mpu is read.  Read from the FIFO */
-static ssize_t mpu_read(struct file *file,
-                       char __user *buf, size_t count, loff_t *offset)
+static unsigned int mpu_poll(struct file *file, struct poll_table_struct *poll)
 {
-       char *tmp;
-       int ret;
-
        struct i2c_client *client =
            (struct i2c_client *) file->private_data;
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *) i2c_get_clientdata(client);
+       int mask = 0;
 
-       if (count > 8192)
-               count = 8192;
-
-       tmp = kmalloc(count, GFP_KERNEL);
-       if (tmp == NULL)
-               return -ENOMEM;
-
-       pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n",
-                iminor(file->f_path.dentry->d_inode), count);
-
-/* @todo fix this to do a i2c trasnfer from the FIFO */
-       ret = i2c_master_recv(client, tmp, count);
-       if (ret >= 0)
-               ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
-       kfree(tmp);
-       return ret;
+       poll_wait(file, &mpu->mpu_event_wait, poll);
+       if (mpu->event)
+               mask |= POLLIN | POLLRDNORM;
+       return mask;
 }
 
 static int
@@ -403,51 +397,245 @@ mpu_ioctl_get_mpu_config(struct i2c_client *client, unsigned long arg)
        retval =
            copy_from_user(local_mldl_cfg, (struct mldl_cfg __user *) arg,
                           sizeof(struct mldl_cfg));
-       if (retval)
+       if (retval) {
+               dev_err(&this_client->adapter->dev,
+                       "%s|%s:%d: EFAULT on arg\n",
+                       __FILE__, __func__, __LINE__);
+               retval = -EFAULT;
                goto out;
+       }
 
        /* Fill in the accel, compass, pressure and pdata pointers */
        if (mldl_cfg->accel) {
                retval = copy_to_user((void __user *)local_mldl_cfg->accel,
                                      mldl_cfg->accel,
                                      sizeof(*mldl_cfg->accel));
-               if (retval)
+               if (retval) {
+                       dev_err(&this_client->adapter->dev,
+                               "%s|%s:%d: EFAULT on accel\n",
+                               __FILE__, __func__, __LINE__);
+                       retval = -EFAULT;
                        goto out;
+               }
        }
 
        if (mldl_cfg->compass) {
                retval = copy_to_user((void __user *)local_mldl_cfg->compass,
                                      mldl_cfg->compass,
                                      sizeof(*mldl_cfg->compass));
-               if (retval)
+               if (retval) {
+                       dev_err(&this_client->adapter->dev,
+                               "%s|%s:%d: EFAULT on compass\n",
+                               __FILE__, __func__, __LINE__);
+                       retval = -EFAULT;
                        goto out;
+               }
        }
 
        if (mldl_cfg->pressure) {
-               retval = copy_to_user(local_mldl_cfg->pressure,
+               retval = copy_to_user((void __user *)local_mldl_cfg->pressure,
                                      mldl_cfg->pressure,
                                      sizeof(*mldl_cfg->pressure));
-               if (retval)
+               if (retval) {
+                       dev_err(&this_client->adapter->dev,
+                               "%s|%s:%d: EFAULT on pressure\n",
+                               __FILE__, __func__, __LINE__);
+                       retval = -EFAULT;
                        goto out;
+               }
        }
 
        if (mldl_cfg->pdata) {
                retval = copy_to_user((void __user *)local_mldl_cfg->pdata,
                                      mldl_cfg->pdata,
                                      sizeof(*mldl_cfg->pdata));
-               if (retval)
+               if (retval) {
+                       dev_err(&this_client->adapter->dev,
+                               "%s|%s:%d: EFAULT on pdata\n",
+                               __FILE__, __func__, __LINE__);
+                       retval = -EFAULT;
                        goto out;
+               }
        }
 
        /* Do not modify the accel, compass, pressure and pdata pointers */
        retval = copy_to_user((struct mldl_cfg __user *) arg,
                              mldl_cfg, offsetof(struct mldl_cfg, accel));
 
+       if (retval)
+               retval = -EFAULT;
 out:
        kfree(local_mldl_cfg);
        return retval;
 }
 
+/**
+ * Pass a requested slave configuration to the slave sensor
+ *
+ * @param adapter the adaptor to use to communicate with the slave
+ * @param mldl_cfg the mldl configuration structuer
+ * @param slave pointer to the slave descriptor
+ * @param usr_config The configuration to pass to the slave sensor
+ *
+ * @return 0 or non-zero error code
+ */
+static int slave_config(void *adapter,
+                       struct mldl_cfg *mldl_cfg,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config __user *usr_config)
+{
+       int retval = ML_SUCCESS;
+       struct ext_slave_config config;
+       if ((!slave) || (!slave->config))
+               return retval;
+
+       retval = copy_from_user(&config, usr_config, sizeof(config));
+       if (retval)
+               return -EFAULT;
+
+       if (config.len && config.data) {
+               int *data;
+               data = kzalloc(config.len, GFP_KERNEL);
+               if (!data)
+                       return ML_ERROR_MEMORY_EXAUSTED;
+
+               retval = copy_from_user(data,
+                                       (void __user *)config.data,
+                                       config.len);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               config.data = data;
+       }
+       retval = slave->config(adapter, slave, pdata, &config);
+       kfree(config.data);
+       return retval;
+}
+
+/**
+ * Get a requested slave configuration from the slave sensor
+ *
+ * @param adapter the adaptor to use to communicate with the slave
+ * @param mldl_cfg the mldl configuration structuer
+ * @param slave pointer to the slave descriptor
+ * @param usr_config The configuration for the slave to fill out
+ *
+ * @return 0 or non-zero error code
+ */
+static int slave_get_config(void *adapter,
+                       struct mldl_cfg *mldl_cfg,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config __user *usr_config)
+{
+       int retval = ML_SUCCESS;
+       struct ext_slave_config config;
+       void *user_data;
+       if (!(slave) || !(slave->get_config))
+               return ML_SUCCESS;
+
+       retval = copy_from_user(&config, usr_config, sizeof(config));
+       if (retval)
+               return -EFAULT;
+
+       user_data = config.data;
+       if (config.len && config.data) {
+               int *data;
+               data = kzalloc(config.len, GFP_KERNEL);
+               if (!data)
+                       return ML_ERROR_MEMORY_EXAUSTED;
+
+               retval = copy_from_user(data,
+                                       (void __user *)config.data,
+                                       config.len);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               config.data = data;
+       }
+       retval = slave->get_config(adapter, slave, pdata, &config);
+       if (retval) {
+               kfree(config.data);
+               return retval;
+       }
+       retval = copy_to_user((unsigned char __user *) user_data,
+                       config.data,
+                       config.len);
+       kfree(config.data);
+       return retval;
+}
+
+static int mpu_handle_mlsl(void *sl_handle,
+                       unsigned char addr,
+                       unsigned int cmd,
+                       struct mpu_read_write __user *usr_msg)
+{
+       int retval = ML_SUCCESS;
+       struct mpu_read_write msg;
+       unsigned char *user_data;
+       retval = copy_from_user(&msg, usr_msg, sizeof(msg));
+       if (retval)
+               return -EFAULT;
+
+       user_data = msg.data;
+       if (msg.length && msg.data) {
+               unsigned char *data;
+               data = kzalloc(msg.length, GFP_KERNEL);
+               if (!data)
+                       return ML_ERROR_MEMORY_EXAUSTED;
+
+               retval = copy_from_user(data,
+                                       (void __user *)msg.data,
+                                       msg.length);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               msg.data = data;
+       } else {
+               return ML_ERROR_INVALID_PARAMETER;
+       }
+
+       switch (cmd) {
+       case MPU_READ:
+               retval = MLSLSerialRead(sl_handle, addr,
+                                       msg.address, msg.length, msg.data);
+               break;
+       case MPU_WRITE:
+               retval = MLSLSerialWrite(sl_handle, addr,
+                                       msg.length, msg.data);
+               break;
+       case MPU_READ_MEM:
+               retval = MLSLSerialReadMem(sl_handle, addr,
+                                       msg.address, msg.length, msg.data);
+               break;
+       case MPU_WRITE_MEM:
+               retval = MLSLSerialWriteMem(sl_handle, addr,
+                                       msg.address, msg.length, msg.data);
+               break;
+       case MPU_READ_FIFO:
+               retval = MLSLSerialReadFifo(sl_handle, addr,
+                                       msg.length, msg.data);
+               break;
+       case MPU_WRITE_FIFO:
+               retval = MLSLSerialWriteFifo(sl_handle, addr,
+                                       msg.length, msg.data);
+               break;
+
+       };
+       retval = copy_to_user((unsigned char __user *) user_data,
+                       msg.data,
+                       msg.length);
+       kfree(msg.data);
+       return retval;
+}
+
 /* ioctl - I/O control */
 static long mpu_ioctl(struct file *file,
                      unsigned int cmd, unsigned long arg)
@@ -468,233 +656,69 @@ static long mpu_ioctl(struct file *file,
        pressure_adapter =
            i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
 
+       retval = mutex_lock_interruptible(&mpu->mutex);
+       if (retval) {
+               dev_err(&this_client->adapter->dev,
+                       "%s: mutex_lock_interruptible returned %d\n",
+                       __func__, retval);
+               return retval;
+       }
+
        switch (cmd) {
-       case I2C_RDWR:
-               mpudev_ioctl_rdrw(client, arg);
-               break;
-       case I2C_SLAVE:
-               if ((arg & 0x7E) != (client->addr & 0x7E)) {
-                       dev_err(&this_client->adapter->dev,
-                               "%s: Invalid I2C_SLAVE arg %lu\n",
-                               __func__, arg);
-               }
-               break;
        case MPU_SET_MPU_CONFIG:
                retval = mpu_ioctl_set_mpu_config(client, arg);
                break;
-       case MPU_SET_INT_CONFIG:
-               mldl_cfg->int_config = (unsigned char) arg;
-               break;
-       case MPU_SET_EXT_SYNC:
-               mldl_cfg->ext_sync = (enum mpu_ext_sync) arg;
-               break;
-       case MPU_SET_FULL_SCALE:
-               mldl_cfg->full_scale = (enum mpu_fullscale) arg;
-               break;
-       case MPU_SET_LPF:
-               mldl_cfg->lpf = (enum mpu_filter) arg;
-               break;
-       case MPU_SET_CLK_SRC:
-               mldl_cfg->clk_src = (enum mpu_clock_sel) arg;
-               break;
-       case MPU_SET_DIVIDER:
-               mldl_cfg->divider = (unsigned char) arg;
-               break;
-       case MPU_SET_LEVEL_SHIFTER:
-               mldl_cfg->pdata->level_shifter = (unsigned char) arg;
-               break;
-       case MPU_SET_DMP_ENABLE:
-               mldl_cfg->dmp_enable = (unsigned char) arg;
-               break;
-       case MPU_SET_FIFO_ENABLE:
-               mldl_cfg->fifo_enable = (unsigned char) arg;
-               break;
-       case MPU_SET_DMP_CFG1:
-               mldl_cfg->dmp_cfg1 = (unsigned char) arg;
-               break;
-       case MPU_SET_DMP_CFG2:
-               mldl_cfg->dmp_cfg2 = (unsigned char) arg;
-               break;
-       case MPU_SET_OFFSET_TC:
-               retval = copy_from_user(mldl_cfg->offset_tc,
-                                       (unsigned char __user *) arg,
-                                       sizeof(mldl_cfg->offset_tc));
-               break;
-       case MPU_SET_RAM:
-               retval = copy_from_user(mldl_cfg->ram,
-                                       (unsigned char __user *) arg,
-                                       sizeof(mldl_cfg->ram));
-               break;
        case MPU_SET_PLATFORM_DATA:
                retval = mpu_ioctl_set_mpu_pdata(client, arg);
                break;
        case MPU_GET_MPU_CONFIG:
                retval = mpu_ioctl_get_mpu_config(client, arg);
                break;
-       case MPU_GET_INT_CONFIG:
-               retval = put_user(mldl_cfg->int_config,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_EXT_SYNC:
-               retval = put_user(mldl_cfg->ext_sync,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_FULL_SCALE:
-               retval = put_user(mldl_cfg->full_scale,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_LPF:
-               retval = put_user(mldl_cfg->lpf,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_CLK_SRC:
-               retval = put_user(mldl_cfg->clk_src,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_DIVIDER:
-               retval = put_user(mldl_cfg->divider,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_LEVEL_SHIFTER:
-               retval = put_user(mldl_cfg->pdata->level_shifter,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_DMP_ENABLE:
-               retval = put_user(mldl_cfg->dmp_enable,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_FIFO_ENABLE:
-               retval = put_user(mldl_cfg->fifo_enable,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_DMP_CFG1:
-               retval = put_user(mldl_cfg->dmp_cfg1,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_DMP_CFG2:
-               retval = put_user(mldl_cfg->dmp_cfg2,
-                                 (unsigned char __user *) arg);
-               break;
-       case MPU_GET_OFFSET_TC:
-               retval = copy_to_user((unsigned char __user *) arg,
-                                     mldl_cfg->offset_tc,
-                                     sizeof(mldl_cfg->offset_tc));
-               break;
-       case MPU_GET_RAM:
-               retval = copy_to_user((unsigned char __user *) arg,
-                                     mldl_cfg->ram,
-                                     sizeof(mldl_cfg->ram));
+       case MPU_READ:
+       case MPU_WRITE:
+       case MPU_READ_MEM:
+       case MPU_WRITE_MEM:
+       case MPU_READ_FIFO:
+       case MPU_WRITE_FIFO:
+               retval = mpu_handle_mlsl(client->adapter, mldl_cfg->addr, cmd,
+                                       (struct mpu_read_write __user *) arg);
                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,
+               retval = slave_config(accel_adapter, mldl_cfg,
                                mldl_cfg->accel,
                                &mldl_cfg->pdata->accel,
-                               &config);
-                       kfree(config.data);
-               }
+                               (struct ext_slave_config __user *) arg);
                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,
+               retval = slave_config(compass_adapter, mldl_cfg,
                                mldl_cfg->compass,
                                &mldl_cfg->pdata->compass,
-                               &config);
-                       kfree(config.data);
-               }
+                               (struct ext_slave_config __user *) arg);
                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,
+               retval = slave_config(pressure_adapter, mldl_cfg,
                                mldl_cfg->pressure,
                                &mldl_cfg->pdata->pressure,
-                               &config);
-                       kfree(config.data);
-               }
+                               (struct ext_slave_config __user *) arg);
+               break;
+       case MPU_GET_CONFIG_ACCEL:
+               retval = slave_get_config(accel_adapter, mldl_cfg,
+                                       mldl_cfg->accel,
+                                       &mldl_cfg->pdata->accel,
+                                       (struct ext_slave_config __user *) arg);
+               break;
+       case MPU_GET_CONFIG_COMPASS:
+               retval = slave_get_config(compass_adapter, mldl_cfg,
+                                       mldl_cfg->compass,
+                                       &mldl_cfg->pdata->compass,
+                                       (struct ext_slave_config __user *) arg);
+               break;
+       case MPU_GET_CONFIG_PRESSURE:
+               retval = slave_get_config(pressure_adapter, mldl_cfg,
+                                       mldl_cfg->pressure,
+                                       &mldl_cfg->pdata->pressure,
+                                       (struct ext_slave_config __user *) arg);
                break;
-       }
-       case MPU_READ_MEMORY:
-       case MPU_WRITE_MEMORY:
        case MPU_SUSPEND:
        {
                unsigned long sensors;
@@ -729,55 +753,59 @@ static long mpu_ioctl(struct file *file,
                                        sensors & ML_THREE_AXIS_PRESSURE);
        }
        break;
-       case MPU_READ_ACCEL:
-               {
-                       unsigned char data[6];
-                       retval =
-                           mpu3050_read_accel(mldl_cfg, client->adapter,
-                                              data);
-                       if (ML_SUCCESS == retval)
-                               retval =
-                                   copy_to_user((unsigned char __user *) arg,
-                                                data, sizeof(data));
-               }
+       case MPU_PM_EVENT_HANDLED:
+               dev_dbg(&this_client->adapter->dev,
+                       "%s: %d\n", __func__, cmd);
+               complete(&mpu->completion);
                break;
+       case MPU_READ_ACCEL:
+       {
+               unsigned char data[6];
+               retval = mpu3050_read_accel(mldl_cfg, client->adapter,
+                                           data);
+               if ((ML_SUCCESS == retval) &&
+                   (copy_to_user((unsigned char __user *) arg,
+                           data, sizeof(data))))
+                       retval = -EFAULT;
+       }
+       break;
        case MPU_READ_COMPASS:
-               {
-                       unsigned char data[6];
-                       struct i2c_adapter *compass_adapt =
-                           i2c_get_adapter(mldl_cfg->pdata->compass.
-                                           adapt_num);
-                       retval =
-                           mpu3050_read_compass(mldl_cfg, compass_adapt,
+       {
+               unsigned char data[6];
+               struct i2c_adapter *compass_adapt =
+                       i2c_get_adapter(mldl_cfg->pdata->compass.
+                                       adapt_num);
+               retval = mpu3050_read_compass(mldl_cfg, compass_adapt,
                                                 data);
-                       if (ML_SUCCESS == retval)
-                               retval =
-                                   copy_to_user((unsigned char *) arg,
-                                                data, sizeof(data));
-               }
-               break;
+               if ((ML_SUCCESS == retval) &&
+                       (copy_to_user((unsigned char *) arg,
+                               data, sizeof(data))))
+                       retval = -EFAULT;
+       }
+       break;
        case MPU_READ_PRESSURE:
-               {
-                       unsigned char data[3];
-                       struct i2c_adapter *pressure_adapt =
-                           i2c_get_adapter(mldl_cfg->pdata->pressure.
-                                           adapt_num);
-                       retval =
-                           mpu3050_read_pressure(mldl_cfg, pressure_adapt,
-                                                data);
-                       if (ML_SUCCESS == retval)
-                               retval =
-                                   copy_to_user((unsigned char __user *) arg,
-                                                data, sizeof(data));
-               }
-               break;
+       {
+               unsigned char data[3];
+               struct i2c_adapter *pressure_adapt =
+                       i2c_get_adapter(mldl_cfg->pdata->pressure.
+                                       adapt_num);
+               retval =
+                       mpu3050_read_pressure(mldl_cfg, pressure_adapt,
+                                       data);
+               if ((ML_SUCCESS == retval) &&
+                   (copy_to_user((unsigned char __user *) arg,
+                           data, sizeof(data))))
+                       retval = -EFAULT;
+       }
+       break;
        default:
                dev_err(&this_client->adapter->dev,
-                       "%s: Unknown cmd %d, arg %lu\n", __func__, cmd,
+                       "%s: Unknown cmd %x, arg %lu\n", __func__, cmd,
                        arg);
                retval = -EINVAL;
        }
 
+       mutex_unlock(&mpu->mutex);
        return retval;
 }
 
@@ -801,10 +829,13 @@ void mpu3050_early_suspend(struct early_suspend *h)
 
        dev_dbg(&this_client->adapter->dev, "%s: %d, %d\n", __func__,
                h->level, mpu->mldl_cfg.gyro_is_suspended);
-       if (MPU3050_EARLY_SUSPEND_IN_DRIVER)
+       if (MPU3050_EARLY_SUSPEND_IN_DRIVER) {
+               mutex_lock(&mpu->mutex);
                (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
                                accel_adapter, compass_adapter,
                                pressure_adapter, TRUE, TRUE, TRUE, TRUE);
+               mutex_unlock(&mpu->mutex);
+       }
 }
 
 void mpu3050_early_resume(struct early_suspend *h)
@@ -825,8 +856,9 @@ void mpu3050_early_resume(struct early_suspend *h)
            i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
 
        if (MPU3050_EARLY_SUSPEND_IN_DRIVER) {
-               if (pid) {
+               if (mpu->pid) {
                        unsigned long sensors = mldl_cfg->requested_sensors;
+                       mutex_lock(&mpu->mutex);
                        (void) mpu3050_resume(mldl_cfg,
                                        this_client->adapter,
                                        accel_adapter,
@@ -836,8 +868,9 @@ void mpu3050_early_resume(struct early_suspend *h)
                                        sensors & ML_THREE_AXIS_ACCEL,
                                        sensors & ML_THREE_AXIS_COMPASS,
                                        sensors & ML_THREE_AXIS_PRESSURE);
+                       mutex_unlock(&mpu->mutex);
                        dev_dbg(&this_client->adapter->dev,
-                               "%s for pid %d\n", __func__, pid);
+                               "%s for pid %d\n", __func__, mpu->pid);
                }
        }
        dev_dbg(&this_client->adapter->dev, "%s: %d\n", __func__, h->level);
@@ -859,9 +892,11 @@ void mpu_shutdown(struct i2c_client *client)
        pressure_adapter =
            i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
 
+       mutex_lock(&mpu->mutex);
        (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
                               accel_adapter, compass_adapter, pressure_adapter,
                               TRUE, TRUE, TRUE, TRUE);
+       mutex_unlock(&mpu->mutex);
        dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
 }
 
@@ -880,7 +915,8 @@ int mpu_suspend(struct i2c_client *client, pm_message_t mesg)
        pressure_adapter =
            i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
 
-       if (!mpu->mldl_cfg.gyro_is_suspended) {
+       mutex_lock(&mpu->mutex);
+       if (!mldl_cfg->ignore_system_suspend) {
                dev_dbg(&this_client->adapter->dev,
                        "%s: suspending on event %d\n", __func__,
                        mesg.event);
@@ -893,6 +929,7 @@ int mpu_suspend(struct i2c_client *client, pm_message_t mesg)
                        "%s: Already suspended %d\n", __func__,
                        mesg.event);
        }
+       mutex_unlock(&mpu->mutex);
        return 0;
 }
 
@@ -911,7 +948,8 @@ int mpu_resume(struct i2c_client *client)
        pressure_adapter =
            i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
 
-       if (pid) {
+       mutex_lock(&mpu->mutex);
+       if (mpu->pid && !mldl_cfg->ignore_system_suspend) {
                unsigned long sensors = mldl_cfg->requested_sensors;
                (void) mpu3050_resume(mldl_cfg, this_client->adapter,
                                      accel_adapter,
@@ -922,8 +960,9 @@ int mpu_resume(struct i2c_client *client)
                                      sensors & ML_THREE_AXIS_COMPASS,
                                      sensors & ML_THREE_AXIS_PRESSURE);
                dev_dbg(&this_client->adapter->dev,
-                       "%s for pid %d\n", __func__, pid);
+                       "%s for pid %d\n", __func__, mpu->pid);
        }
+       mutex_unlock(&mpu->mutex);
        return 0;
 }
 
@@ -931,6 +970,8 @@ int mpu_resume(struct i2c_client *client)
 static const struct file_operations mpu_fops = {
        .owner = THIS_MODULE,
        .read = mpu_read,
+       .poll = mpu_poll,
+
 #if HAVE_COMPAT_IOCTL
        .compat_ioctl = mpu_ioctl,
 #endif
@@ -981,15 +1022,30 @@ int mpu3050_probe(struct i2c_client *client,
        i2c_set_clientdata(client, mpu);
        this_client = client;
        mldl_cfg = &mpu->mldl_cfg;
+
+       init_waitqueue_head(&mpu->mpu_event_wait);
+
+       mutex_init(&mpu->mutex);
+       init_completion(&mpu->completion);
+
+       mpu->response_timeout = 60; /* Seconds */
+       mpu->timeout.function = mpu_pm_timeout;
+       mpu->timeout.data = (u_long) mpu;
+       init_timer(&mpu->timeout);
+
+       mpu->nb.notifier_call = mpu_pm_notifier_callback;
+       mpu->nb.priority = 0;
+       register_pm_notifier(&mpu->nb);
+
        pdata = (struct mpu3050_platform_data *) client->dev.platform_data;
        if (!pdata) {
-               dev_warn(&this_client->adapter->dev,
-                        "Warning no platform data for mpu3050\n");
+               dev_WARN(&this_client->adapter->dev,
+                        "Missing platform data for mpu3050\n");
        } else {
                mldl_cfg->pdata = pdata;
 
-#if defined(CONFIG_SENSORS_MPU3050_MODULE) || \
-    defined(CONFIG_SENSORS_MPU6000_MODULE)
+#if defined(CONFIG_MPU_SENSORS_MPU3050_MODULE) || \
+    defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)
                pdata->accel.get_slave_descr = get_accel_slave_descr;
                pdata->compass.get_slave_descr = get_compass_slave_descr;
                pdata->pressure.get_slave_descr = get_pressure_slave_descr;
@@ -1013,7 +1069,7 @@ int mpu3050_probe(struct i2c_client *client,
                                if (res)
                                        goto out_accelirq_failed;
                        } else {
-                               dev_warn(&this_client->adapter->dev,
+                               dev_WARN(&this_client->adapter->dev,
                                        "WARNING: Accel irq not assigned\n");
                        }
                } else {
@@ -1100,8 +1156,8 @@ int mpu3050_probe(struct i2c_client *client,
                if (res)
                        goto out_mpuirq_failed;
        } else {
-               dev_warn(&this_client->adapter->dev,
-                        "WARNING: %s irq not assigned\n", MPU_NAME);
+               dev_WARN(&this_client->adapter->dev,
+                       "Missing %s IRQ\n", MPU_NAME);
        }
 
 
@@ -1220,20 +1276,17 @@ static struct i2c_driver mpu3050_driver = {
 
 static int __init mpu_init(void)
 {
-       printk("xxm -> enter mpu_init\n");
        int res = i2c_add_driver(&mpu3050_driver);
-       pid = 0;
-       printk(KERN_DEBUG "%s\n", __func__);
-       printk("xxm-> end mpu_init\n");
-       if (res){
-               dev_err(&this_client->adapter->dev, "%s\n",
+       pr_debug("%s\n", __func__);
+       if (res)
+               pr_err("%s failed\n",
                        __func__);
        return res;
-       }
 }
+
 static void __exit mpu_exit(void)
 {
-       printk(KERN_DEBUG "%s\n", __func__);
+       pr_debug("%s\n", __func__);
        i2c_del_driver(&mpu3050_driver);
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 3c7e3ef..b1298d3
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
@@ -17,7 +30,6 @@
 #include <linux/i2c.h>
 #include "mpu.h"
 
-#define MPU_SPEED      400 * 1000
 int sensor_i2c_write(struct i2c_adapter *i2c_adap,
                     unsigned char address,
                     unsigned int len, unsigned char const *data)
@@ -32,7 +44,6 @@ int sensor_i2c_write(struct i2c_adapter *i2c_adap,
        msgs[0].flags = 0;      /* write */
        msgs[0].buf = (unsigned char *) data;
        msgs[0].len = len;
-       msgs[0].scl_rate = MPU_SPEED;
 
        res = i2c_transfer(i2c_adap, msgs, 1);
        if (res < 1)
@@ -51,6 +62,7 @@ int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
        data[1] = value;
        return sensor_i2c_write(i2c_adap, address, 2, data);
 }
+
 int sensor_i2c_read(struct i2c_adapter *i2c_adap,
                    unsigned char address,
                    unsigned char reg,
@@ -66,13 +78,11 @@ int sensor_i2c_read(struct i2c_adapter *i2c_adap,
        msgs[0].flags = 0;      /* write */
        msgs[0].buf = &reg;
        msgs[0].len = 1;
-       msgs[0].scl_rate = MPU_SPEED;
 
        msgs[1].addr = address;
        msgs[1].flags = I2C_M_RD;
        msgs[1].buf = data;
        msgs[1].len = len;
-       msgs[1].scl_rate = MPU_SPEED;
 
        res = i2c_transfer(i2c_adap, msgs, 2);
        if (res < 2)
@@ -109,25 +119,21 @@ int mpu_memory_read(struct i2c_adapter *i2c_adap,
        msgs[0].flags = 0;
        msgs[0].buf = bank;
        msgs[0].len = sizeof(bank);
-       msgs[0].scl_rate = MPU_SPEED;
 
        msgs[1].addr = mpu_addr;
        msgs[1].flags = 0;
        msgs[1].buf = addr;
        msgs[1].len = sizeof(addr);
-       msgs[1].scl_rate = MPU_SPEED;
 
        msgs[2].addr = mpu_addr;
        msgs[2].flags = 0;
        msgs[2].buf = &buf;
        msgs[2].len = 1;
-       msgs[2].scl_rate = MPU_SPEED;
 
        msgs[3].addr = mpu_addr;
        msgs[3].flags = I2C_M_RD;
        msgs[3].buf = data;
        msgs[3].len = len;
-       msgs[3].scl_rate = MPU_SPEED;
 
        ret = i2c_transfer(i2c_adap, msgs, 4);
        if (ret != 4)
@@ -167,20 +173,17 @@ int mpu_memory_write(struct i2c_adapter *i2c_adap,
        msgs[0].flags = 0;
        msgs[0].buf = bank;
        msgs[0].len = sizeof(bank);
-       msgs[0].scl_rate = MPU_SPEED;
 
        msgs[1].addr = mpu_addr;
        msgs[1].flags = 0;
        msgs[1].buf = addr;
        msgs[1].len = sizeof(addr);
-       msgs[1].scl_rate = MPU_SPEED;
 
        msgs[2].addr = mpu_addr;
        msgs[2].flags = 0;
        msgs[2].buf = (unsigned char *) buf;
        msgs[2].len = len + 1;
-       msgs[2].scl_rate = MPU_SPEED;
-       
+
        ret = i2c_transfer(i2c_adap, msgs, 3);
        if (ret != 3)
                return ret;
old mode 100644 (file)
new mode 100755 (executable)
index 7d58027..0bbc8c6
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 /**
  * @defgroup
old mode 100644 (file)
new mode 100755 (executable)
index 01ab307..ce1ad40
@@ -1,7 +1,20 @@
 /*
  $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>
@@ -16,8 +29,6 @@
 #include <linux/i2c-dev.h>
 #include <linux/workqueue.h>
 #include <linux/poll.h>
-#include <linux/gpio.h>
-#include <mach/gpio.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -50,7 +61,7 @@ struct mpuirq_dev_data {
 };
 
 static struct mpuirq_dev_data mpuirq_dev_data;
-static struct irq_data mpuirq_data;
+static struct mpuirq_data mpuirq_data;
 static char *interface = MPUIRQ_NAME;
 
 static void mpu_accel_data_work_fcn(struct work_struct *work);
@@ -61,9 +72,6 @@ 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 */
        return 0;
 }
 
@@ -81,7 +89,9 @@ static ssize_t mpuirq_read(struct file *file,
        int len, err;
        struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
 
-       if (!mpuirq_dev_data.data_ready) {
+       if (!mpuirq_dev_data.data_ready &&
+               mpuirq_dev_data.timeout &&
+               (!(file->f_flags & O_NONBLOCK))) {
                wait_event_interruptible_timeout(mpuirq_wait,
                                                 mpuirq_dev_data.
                                                 data_ready,
@@ -195,23 +205,20 @@ static irqreturn_t mpuirq_handler(int irq, void *dev_id)
 
        /* 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 += 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));
-               }
+       mpuirq_dev_data.data_ready = 1;
+
+       do_gettimeofday(&irqtime);
+       mpuirq_data.irqtime = (((long long) irqtime.tv_sec) << 32);
+       mpuirq_data.irqtime += irqtime.tv_usec;
 
-               wake_up_interruptible(&mpuirq_wait);
+       if ((mpuirq_dev_data.accel_divider >= 0) &&
+               (0 == (mycount % (mpuirq_dev_data.accel_divider + 1)))) {
+               schedule_work((struct work_struct
+                               *) (&mpuirq_dev_data));
        }
 
+       wake_up_interruptible(&mpuirq_wait);
+
        return IRQ_HANDLED;
 
 }
@@ -267,28 +274,14 @@ int mpuirq_init(struct i2c_client *mpu_client)
                        flags = IRQF_TRIGGER_FALLING;
                else
                        flags = IRQF_TRIGGER_RISING;
-               /* mpu irq register xxm*/
-               res = gpio_request(mpuirq_dev_data.irq, "mpu3050_int");
-               if(res)
-               {
-                       printk("failed to request mpu3050_int GPIO %d\n",                       
-                                               gpio_to_irq(mpuirq_dev_data.irq));
-                       return res;
-               }
-               res = gpio_direction_input(mpuirq_dev_data.irq);
-               if(res)
-               {
-                       printk("failed to set mpu3050_int GPIO input\n");
-                       return res;
-               }
-               printk("gpio_to_irq(mpuirq_dev_data.irq) == %d \r\n",   
-                               gpio_to_irq(mpuirq_dev_data.irq));
-               res =request_irq(gpio_to_irq(mpuirq_dev_data.irq), mpuirq_handler, flags,
-                                                       interface,&mpuirq_dev_data.irq);
+
+               res =
+                   request_irq(mpuirq_dev_data.irq, mpuirq_handler, flags,
+                               interface, &mpuirq_dev_data.irq);
                if (res) {
                        dev_err(&mpu_client->adapter->dev,
-                               "myirqtest: cannot register IRQ %d,return value is %d\n",
-                               gpio_to_irq(mpuirq_dev_data.irq),res);
+                               "myirqtest: cannot register IRQ %d\n",
+                               mpuirq_dev_data.irq);
                } else {
                        res = misc_register(&mpuirq_device);
                        if (res < 0) {
old mode 100644 (file)
new mode 100755 (executable)
index 374cd33..a71c79c
@@ -1,7 +1,20 @@
 /*
  $License:
     Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
- $
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
  */
 
 #ifndef __MPUIRQ__
 
 #ifdef __KERNEL__
 #include <linux/i2c-dev.h>
+#include <linux/time.h>
+#else
+#include <sys/time.h>
 #endif
 
-#define MPUIRQ_ENABLE_DEBUG          (1)
-#define MPUIRQ_GET_INTERRUPT_CNT     (2)
-#define MPUIRQ_GET_IRQ_TIME          (3)
-#define MPUIRQ_GET_LED_VALUE         (4)
-#define MPUIRQ_SET_TIMEOUT           (5)
-#define MPUIRQ_SET_ACCEL_INFO        (6)
-#define MPUIRQ_SET_FREQUENCY_DIVIDER (7)
+#define MPUIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x40, unsigned long)
+#define MPUIRQ_GET_INTERRUPT_CNT     _IOR(MPU_IOCTL, 0x41, unsigned long)
+#define MPUIRQ_GET_IRQ_TIME          _IOR(MPU_IOCTL, 0x42, struct timeval)
+#define MPUIRQ_SET_FREQUENCY_DIVIDER _IOW(MPU_IOCTL, 0x43, unsigned long)
 
 #ifdef __KERNEL__
 
old mode 100644 (file)
new mode 100755 (executable)
index e66da3b..a3c7bfe
@@ -1,7 +1,20 @@
 /*
  $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>
@@ -15,8 +28,6 @@
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
 #include <linux/poll.h>
-#include <linux/gpio.h>
-#include <mach/gpio.h>
 
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/wait.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
 
 #include "mpu.h"
 #include "slaveirq.h"
 #include "mldl_cfg.h"
 #include "mpu-i2c.h"
-#include <linux/wait.h>
-#include <linux/delay.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;
+       struct mpuirq_data data;
        wait_queue_head_t slaveirq_wait;
        int irq;
        int pid;
@@ -77,7 +89,9 @@ static ssize_t slaveirq_read(struct file *file,
        struct slaveirq_dev_data *data =
                container_of(file->private_data, struct slaveirq_dev_data, dev);
 
-       if (!data->data_ready) {
+       if (!data->data_ready &&
+               data->timeout &&
+               !(file->f_flags & O_NONBLOCK)) {
                wait_event_interruptible_timeout(data->slaveirq_wait,
                                                 data->data_ready,
                                                 data->timeout);
@@ -100,7 +114,8 @@ static ssize_t slaveirq_read(struct file *file,
        return len;
 }
 
-unsigned int slaveirq_poll(struct file *file, struct poll_table_struct *poll)
+static unsigned int slaveirq_poll(struct file *file,
+                               struct poll_table_struct *poll)
 {
        int mask = 0;
        struct slaveirq_dev_data *data =
@@ -156,17 +171,14 @@ static irqreturn_t slaveirq_handler(int irq, void *dev_id)
        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;
+       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;
+       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);
-       }
+       wake_up_interruptible(&data->slaveirq_wait);
 
        return IRQ_HANDLED;
 
@@ -213,24 +225,10 @@ int slaveirq_init(struct i2c_adapter *slave_adapter,
        data->data_ready = 0;
        data->timeout = 0;
 
-       /* mpu irq register xxm*/
-       res = gpio_request(data->irq, name);
-       if(res)
-       {
-               printk("failed to request %s GPIO %d\n",                        
-                                       name,data->irq);
-               return res;
-       }
-       res = gpio_direction_input(data->irq);
-       if(res)
-       {
-               printk("failed to set %s GPIO input\n",name);
-               return res;
-       }
-       printk("%s registing irq  == %d \r\n",name,gpio_to_irq(data->irq));
-       //gpio_pull_updown(data->irq, GPIOPullUp);
-       //gpio_set_value(data->irq,GPIO_HIGH);
-       res = request_irq(gpio_to_irq(data->irq), slaveirq_handler, IRQF_TRIGGER_FALLING,data->dev.name, data);
+       init_waitqueue_head(&data->slaveirq_wait);
+
+       res = request_irq(data->irq, slaveirq_handler, IRQF_TRIGGER_RISING,
+                         data->dev.name, data);
 
        if (res) {
                dev_err(&slave_adapter->dev,
@@ -247,7 +245,6 @@ int slaveirq_init(struct i2c_adapter *slave_adapter,
                goto out_misc_register;
        }
 
-       init_waitqueue_head(&data->slaveirq_wait);
        return res;
 
 out_misc_register:
old mode 100644 (file)
new mode 100755 (executable)
index ac53f1e..b4e1115
@@ -1,7 +1,20 @@
 /*
  $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__
 #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)
+#define SLAVEIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x50, unsigned long)
+#define SLAVEIRQ_GET_INTERRUPT_CNT     _IOR(MPU_IOCTL, 0x51, unsigned long)
+#define SLAVEIRQ_GET_IRQ_TIME          _IOR(MPU_IOCTL, 0x52, unsigned long)
 
 #ifdef __KERNEL__
 
diff --git a/drivers/misc/mpu3050/timerirq.c b/drivers/misc/mpu3050/timerirq.c
new file mode 100755 (executable)
index 0000000..41c3ac9
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+
+#include "mpu.h"
+#include "mltypes.h"
+#include "timerirq.h"
+
+/* function which gets timer data and sends it to TIMER */
+struct timerirq_data {
+       int pid;
+       int data_ready;
+       int run;
+       int timeout;
+       unsigned long period;
+       struct mpuirq_data data;
+       struct completion timer_done;
+       wait_queue_head_t timerirq_wait;
+       struct timer_list timer;
+       struct miscdevice *dev;
+};
+
+static struct miscdevice *timerirq_dev_data;
+
+static void timerirq_handler(unsigned long arg)
+{
+       struct timerirq_data *data = (struct timerirq_data *)arg;
+       struct timeval irqtime;
+
+       data->data.interruptcount++;
+
+       data->data_ready = 1;
+
+       do_gettimeofday(&irqtime);
+       data->data.irqtime = (((long long) irqtime.tv_sec) << 32);
+       data->data.irqtime += irqtime.tv_usec;
+       data->data.data_type |= 1;
+
+       dev_dbg(data->dev->this_device,
+               "%s, %lld, %ld\n", __func__, data->data.irqtime,
+               (unsigned long)data);
+
+       wake_up_interruptible(&data->timerirq_wait);
+
+       if (data->run)
+               mod_timer(&data->timer,
+                       jiffies + msecs_to_jiffies(data->period));
+       else
+               complete(&data->timer_done);
+}
+
+static int start_timerirq(struct timerirq_data *data)
+{
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %d\n", __func__, current->pid);
+
+       /* Timer already running... success */
+       if (data->run)
+               return 0;
+
+       /* Don't allow a period of 0 since this would fire constantly */
+       if (!data->period)
+               return -EINVAL;
+
+       data->run = TRUE;
+       data->data_ready = FALSE;
+
+       init_completion(&data->timer_done);
+       setup_timer(&data->timer, timerirq_handler, (unsigned long)data);
+
+       return mod_timer(&data->timer,
+                       jiffies + msecs_to_jiffies(data->period));
+}
+
+static int stop_timerirq(struct timerirq_data *data)
+{
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %lx\n", __func__, (unsigned long)data);
+
+       if (data->run) {
+               data->run = FALSE;
+               mod_timer(&data->timer, jiffies + 1);
+               wait_for_completion(&data->timer_done);
+       }
+       return 0;
+}
+
+/* The following depends on patch fa1f68db6ca7ebb6fc4487ac215bffba06c01c28
+ * drivers: misc: pass miscdevice pointer via file private data
+ */
+static int timerirq_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 miscdevice *dev_data = file->private_data;
+       struct timerirq_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->dev = dev_data;
+       file->private_data = data;
+       data->pid = current->pid;
+       init_waitqueue_head(&data->timerirq_wait);
+
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %d\n", __func__, current->pid);
+       return 0;
+}
+
+static int timerirq_release(struct inode *inode, struct file *file)
+{
+       struct timerirq_data *data = file->private_data;
+       dev_dbg(data->dev->this_device, "timerirq_release\n");
+       if (data->run)
+               stop_timerirq(data);
+       kfree(data);
+       return 0;
+}
+
+/* read function called when from /dev/timerirq is read */
+static ssize_t timerirq_read(struct file *file,
+                          char *buf, size_t count, loff_t *ppos)
+{
+       int len, err;
+       struct timerirq_data *data = file->private_data;
+
+       if (!data->data_ready &&
+               data->timeout &&
+               !(file->f_flags & O_NONBLOCK)) {
+               wait_event_interruptible_timeout(data->timerirq_wait,
+                                                data->data_ready,
+                                                data->timeout);
+       }
+
+       if (data->data_ready && NULL != buf
+           && count >= sizeof(data->data)) {
+               err = copy_to_user(buf, &data->data, sizeof(data->data));
+               data->data.data_type = 0;
+       } else {
+               return 0;
+       }
+       if (err != 0) {
+               dev_err(data->dev->this_device,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
+       }
+       data->data_ready = 0;
+       len = sizeof(data->data);
+       return len;
+}
+
+static unsigned int timerirq_poll(struct file *file,
+                               struct poll_table_struct *poll)
+{
+       int mask = 0;
+       struct timerirq_data *data = file->private_data;
+
+       poll_wait(file, &data->timerirq_wait, poll);
+       if (data->data_ready)
+               mask |= POLLIN | POLLRDNORM;
+       return mask;
+}
+
+/* ioctl - I/O control */
+static long timerirq_ioctl(struct file *file,
+                          unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+       int tmp;
+       struct timerirq_data *data = file->private_data;
+
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %d, %d, %ld\n",
+               __func__, current->pid, cmd, arg);
+
+       if (!data)
+               return -EFAULT;
+
+       switch (cmd) {
+       case TIMERIRQ_SET_TIMEOUT:
+               data->timeout = arg;
+               break;
+       case TIMERIRQ_GET_INTERRUPT_CNT:
+               tmp = data->data.interruptcount - 1;
+               if (data->data.interruptcount > 1)
+                       data->data.interruptcount = 1;
+
+               if (copy_to_user((int *) arg, &tmp, sizeof(int)))
+                       return -EFAULT;
+               break;
+       case TIMERIRQ_START:
+               data->period = arg;
+               retval = start_timerirq(data);
+               break;
+       case TIMERIRQ_STOP:
+               retval = stop_timerirq(data);
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+/* define which file operations are supported */
+static const struct file_operations timerirq_fops = {
+       .owner = THIS_MODULE,
+       .read = timerirq_read,
+       .poll = timerirq_poll,
+
+#if HAVE_COMPAT_IOCTL
+       .compat_ioctl = timerirq_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl = timerirq_ioctl,
+#endif
+       .open = timerirq_open,
+       .release = timerirq_release,
+};
+
+static int __init timerirq_init(void)
+{
+
+       int res;
+       static struct miscdevice *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       timerirq_dev_data = data;
+       data->minor = MISC_DYNAMIC_MINOR;
+       data->name = "timerirq";
+       data->fops = &timerirq_fops;
+
+       res = misc_register(data);
+       if (res < 0) {
+               dev_err(data->this_device,
+                       "misc_register returned %d\n",
+                       res);
+               return res;
+       }
+
+       return res;
+}
+module_init(timerirq_init);
+
+static void __exit timerirq_exit(void)
+{
+       struct miscdevice *data = timerirq_dev_data;
+
+       dev_info(data->this_device, "Unregistering %s\n",
+                data->name);
+
+       misc_deregister(data);
+       kfree(data);
+
+       timerirq_dev_data = NULL;
+}
+module_exit(timerirq_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Timer IRQ device driver.");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("timerirq");
diff --git a/drivers/misc/mpu3050/timerirq.h b/drivers/misc/mpu3050/timerirq.h
new file mode 100755 (executable)
index 0000000..ec2c1e2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ $License:
+    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
+ */
+
+#ifndef __TIMERIRQ__
+#define __TIMERIRQ__
+
+#include "mpu.h"
+
+#define TIMERIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x60, unsigned long)
+#define TIMERIRQ_GET_INTERRUPT_CNT     _IOW(MPU_IOCTL, 0x61, unsigned long)
+#define TIMERIRQ_START                 _IOW(MPU_IOCTL, 0x62, unsigned long)
+#define TIMERIRQ_STOP                  _IO(MPU_IOCTL, 0x63)
+
+#endif
old mode 100644 (file)
new mode 100755 (executable)
index da1c6bc..d66d9e7
@@ -1,7 +1,20 @@
 /*
  $License:
     Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
- $
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  $
  */
 
 #ifndef __MPU_H_
@@ -9,6 +22,9 @@
 
 #ifdef __KERNEL__
 #include <linux/types.h>
+#include <linux/ioctl.h>
+#elif defined LINUX
+#include <sys/ioctl.h>
 #endif
 
 #ifdef M_HW
 #define ACCEL_NUM_AXES              (3)
 #define COMPASS_NUM_AXES            (3)
 
+#if defined __KERNEL__ || defined LINUX
+#define MPU_IOCTL (0x81) /* Magic number for MPU Iocts */
 /* IOCTL commands for /dev/mpu */
-#define MPU_SET_MPU_CONFIG          (0x00)
-#define MPU_SET_INT_CONFIG          (0x01)
-#define MPU_SET_EXT_SYNC            (0x02)
-#define MPU_SET_FULL_SCALE          (0x03)
-#define MPU_SET_LPF                 (0x04)
-#define MPU_SET_CLK_SRC             (0x05)
-#define MPU_SET_DIVIDER             (0x06)
-#define MPU_SET_LEVEL_SHIFTER       (0x07)
-#define MPU_SET_DMP_ENABLE          (0x08)
-#define MPU_SET_FIFO_ENABLE         (0x09)
-#define MPU_SET_DMP_CFG1            (0x0a)
-#define MPU_SET_DMP_CFG2            (0x0b)
-#define MPU_SET_OFFSET_TC           (0x0c)
-#define MPU_SET_RAM                 (0x0d)
-
-#define MPU_SET_PLATFORM_DATA       (0x0e)
-
-#define MPU_GET_MPU_CONFIG          (0x80)
-#define MPU_GET_INT_CONFIG          (0x81)
-#define MPU_GET_EXT_SYNC            (0x82)
-#define MPU_GET_FULL_SCALE          (0x83)
-#define MPU_GET_LPF                 (0x84)
-#define MPU_GET_CLK_SRC             (0x85)
-#define MPU_GET_DIVIDER             (0x86)
-#define MPU_GET_LEVEL_SHIFTER       (0x87)
-#define MPU_GET_DMP_ENABLE          (0x88)
-#define MPU_GET_FIFO_ENABLE         (0x89)
-#define MPU_GET_DMP_CFG1            (0x8a)
-#define MPU_GET_DMP_CFG2            (0x8b)
-#define MPU_GET_OFFSET_TC           (0x8c)
-#define MPU_GET_RAM                 (0x8d)
-
-#define MPU_READ_REGISTER           (0x40)
-#define MPU_WRITE_REGISTER          (0x41)
-#define MPU_READ_MEMORY             (0x42)
-#define MPU_WRITE_MEMORY            (0x43)
-
-#define MPU_SUSPEND                 (0x44)
-#define MPU_RESUME                  (0x45)
-#define MPU_READ_COMPASS            (0x46)
-#define MPU_READ_ACCEL              (0x47)
-#define MPU_READ_PRESSURE           (0x48)
-
-#define MPU_CONFIG_ACCEL            (0x20)
-#define MPU_CONFIG_COMPASS          (0x21)
-#define MPU_CONFIG_PRESSURE         (0x22)
+#define MPU_SET_MPU_CONFIG     _IOW(MPU_IOCTL, 0x00, struct mldl_cfg)
+#define MPU_GET_MPU_CONFIG     _IOR(MPU_IOCTL, 0x00, struct mldl_cfg)
+
+#define MPU_SET_PLATFORM_DATA  _IOW(MPU_IOCTL, 0x01, struct mldl_cfg)
+
+#define MPU_READ               _IOR(MPU_IOCTL, 0x10, struct mpu_read_write)
+#define MPU_WRITE              _IOW(MPU_IOCTL, 0x10, struct mpu_read_write)
+#define MPU_READ_MEM           _IOR(MPU_IOCTL, 0x11, struct mpu_read_write)
+#define MPU_WRITE_MEM          _IOW(MPU_IOCTL, 0x11, struct mpu_read_write)
+#define MPU_READ_FIFO          _IOR(MPU_IOCTL, 0x12, struct mpu_read_write)
+#define MPU_WRITE_FIFO         _IOW(MPU_IOCTL, 0x12, struct mpu_read_write)
+
+#define MPU_READ_COMPASS       _IOR(MPU_IOCTL, 0x12, unsigned char)
+#define MPU_READ_ACCEL         _IOR(MPU_IOCTL, 0x13, unsigned char)
+#define MPU_READ_PRESSURE      _IOR(MPU_IOCTL, 0x14, unsigned char)
+
+#define MPU_CONFIG_ACCEL       _IOW(MPU_IOCTL, 0x20, struct ext_slave_config)
+#define MPU_CONFIG_COMPASS     _IOW(MPU_IOCTL, 0x21, struct ext_slave_config)
+#define MPU_CONFIG_PRESSURE    _IOW(MPU_IOCTL, 0x22, struct ext_slave_config)
+
+#define MPU_GET_CONFIG_ACCEL   _IOR(MPU_IOCTL, 0x20, struct ext_slave_config)
+#define MPU_GET_CONFIG_COMPASS _IOR(MPU_IOCTL, 0x21, struct ext_slave_config)
+#define MPU_GET_CONFIG_PRESSURE        _IOR(MPU_IOCTL, 0x22, struct ext_slave_config)
 
+#define MPU_SUSPEND            _IO(MPU_IOCTL, 0x30)
+#define MPU_RESUME             _IO(MPU_IOCTL, 0x31)
+/* Userspace PM Event response */
+#define MPU_PM_EVENT_HANDLED   _IO(MPU_IOCTL, 0x32)
+
+#endif
 /* Structure for the following IOCTL's:
-   MPU_SET_RAM
-   MPU_GET_RAM
-   MPU_READ_REGISTER
-   MPU_WRITE_REGISTER
-   MPU_READ_MEMORY
-   MPU_WRITE_MEMORY
+   MPU_READ
+   MPU_WRITE
+   MPU_READ_MEM
+   MPU_WRITE_MEM
+   MPU_READ_FIFO
+   MPU_WRITE_FIFO
 */
 struct mpu_read_write {
+       /* Memory address or register address depending on ioctl */
        unsigned short address;
        unsigned short length;
        unsigned char *data;
 };
 
-struct irq_data {
+enum mpuirq_data_type {
+    MPUIRQ_DATA_TYPE_MPU_IRQ,
+    MPUIRQ_DATA_TYPE_SLAVE_IRQ,
+    MPUIRQ_DATA_TYPE_PM_EVENT,
+    MPUIRQ_DATA_TYPE_NUM_TYPES,
+};
+
+/* User space PM event notification */
+#define MPU_PM_EVENT_SUSPEND_PREPARE (3)
+#define MPU_PM_EVENT_POST_SUSPEND    (4)
+
+#define MAX_MPUIRQ_DATA_SIZE (32)
+
+struct mpuirq_data {
        int interruptcount;
        unsigned long long irqtime;
        int data_type;
        int data_size;
        void *data;
 };
+
 enum ext_slave_config_key {
-    MPU_SLAVE_CONFIG_ODR_SUSPEND,
-    MPU_SLAVE_CONFIG_ODR_RESUME,
-    MPU_SLAVE_CONFIG_FSR_SUSPEND,
-    MPU_SLAVE_CONFIG_FSR_RESUME,
-    MPU_SLAVE_CONFIG_MOT_THS,
-    MPU_SLAVE_CONFIG_NMOT_THS,
-    MPU_SLAVE_CONFIG_MOT_DUR,
-    MPU_SLAVE_CONFIG_NMOT_DUR,
-    MPU_SLAVE_CONFIG_NUM_CONFIG_KEYS,
+       MPU_SLAVE_CONFIG_ODR_SUSPEND,
+       MPU_SLAVE_CONFIG_ODR_RESUME,
+       MPU_SLAVE_CONFIG_FSR_SUSPEND,
+       MPU_SLAVE_CONFIG_FSR_RESUME,
+       MPU_SLAVE_CONFIG_MOT_THS,
+       MPU_SLAVE_CONFIG_NMOT_THS,
+       MPU_SLAVE_CONFIG_MOT_DUR,
+       MPU_SLAVE_CONFIG_NMOT_DUR,
+       MPU_SLAVE_CONFIG_IRQ_SUSPEND,
+       MPU_SLAVE_CONFIG_IRQ_RESUME,
+       MPU_SLAVE_WRITE_REGISTERS,
+       MPU_SLAVE_READ_REGISTERS,
+       MPU_SLAVE_CONFIG_NUM_CONFIG_KEYS,
 };
+
+/* For the MPU_SLAVE_CONFIG_IRQ_SUSPEND and MPU_SLAVE_CONFIG_IRQ_RESUME */
+enum ext_slave_config_irq_type {
+       MPU_SLAVE_IRQ_TYPE_NONE,
+       MPU_SLAVE_IRQ_TYPE_MOTION,
+       MPU_SLAVE_IRQ_TYPE_DATA_READY,
+};
+
 /* Structure for the following IOCTS's
  * MPU_CONFIG_ACCEL
  * MPU_CONFIG_COMPASS
  * MPU_CONFIG_PRESSURE
+ * MPU_GET_CONFIG_ACCEL
+ * MPU_GET_CONFIG_COMPASS
+ * MPU_GET_CONFIG_PRESSURE
  */
 struct ext_slave_config {
        int key;
        int len;
+       int apply;
        void *data;
 };
 
@@ -126,22 +158,26 @@ enum ext_slave_id {
 
        ACCEL_ID_LIS331,
        ACCEL_ID_LSM303,
+       ACCEL_ID_LIS3DH,
        ACCEL_ID_KXSD9,
        ACCEL_ID_KXTF9,
        ACCEL_ID_BMA150,
        ACCEL_ID_BMA222,
        ACCEL_ID_ADI346,
        ACCEL_ID_MMA8450,
-       ACCEL_ID_MMA8451,
+       ACCEL_ID_MMA845X,
        ACCEL_ID_MPU6000,
 
        COMPASS_ID_AKM,
        COMPASS_ID_AMI30X,
+       COMPASS_ID_AMI306,
        COMPASS_ID_YAS529,
+       COMPASS_ID_YAS530,
        COMPASS_ID_HMC5883,
        COMPASS_ID_LSM303,
        COMPASS_ID_MMC314X,
-       COMPASS_ID_HSCDTD00XX,
+       COMPASS_ID_HSCDTD002B,
+       COMPASS_ID_HSCDTD004A,
 
        PRESSURE_ID_BMA085,
 };
@@ -205,6 +241,7 @@ struct tFixPntRange {
  *  @init:     function used to preallocate memory used by the driver
  *  @exit:     function used to free memory allocated for the driver
  *  @config:   function used to configure the device
+ *  @get_config:function used to get the device's configuration
  *
  *  @name:     text name of the device
  *  @type:     device type. enum ext_slave_type
@@ -238,6 +275,10 @@ struct ext_slave_descr {
                       struct ext_slave_descr *slave,
                       struct ext_slave_platform_data *pdata,
                       struct ext_slave_config *config);
+       int (*get_config) (void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata,
+                          struct ext_slave_config *config);
 
        char *name;
        unsigned char type;
@@ -278,65 +319,73 @@ struct mpu3050_platform_data {
 */
 #define get_accel_slave_descr NULL
 
-#ifdef CONFIG_SENSORS_ADXL346  /* ADI accelerometer */
+#ifdef CONFIG_MPU_SENSORS_ADXL346      /* ADI accelerometer */
 struct ext_slave_descr *adxl346_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr adxl346_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_BMA150   /* Bosch accelerometer */
+#ifdef CONFIG_MPU_SENSORS_BMA150       /* Bosch accelerometer */
 struct ext_slave_descr *bma150_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr bma150_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_BMA222   /* Bosch 222 accelerometer */
+#ifdef CONFIG_MPU_SENSORS_BMA222       /* Bosch 222 accelerometer */
 struct ext_slave_descr *bma222_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr bma222_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_KXSD9    /* Kionix accelerometer */
+#ifdef CONFIG_MPU_SENSORS_KXSD9        /* Kionix accelerometer */
 struct ext_slave_descr *kxsd9_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr kxsd9_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_KXTF9    /* Kionix accelerometer */
+#ifdef CONFIG_MPU_SENSORS_KXTF9        /* Kionix accelerometer */
 struct ext_slave_descr *kxtf9_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr kxtf9_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_LIS331DLH        /* ST accelerometer */
+#ifdef CONFIG_MPU_SENSORS_LIS331DLH    /* ST accelerometer */
 struct ext_slave_descr *lis331dlh_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr lis331dlh_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_LSM303DLHA       /* ST accelerometer */
+
+#ifdef CONFIG_MPU_SENSORS_LIS3DH       /* ST accelerometer */
+struct ext_slave_descr *lis3dh_get_slave_descr(void);
+#undef get_accel_slave_descr
+#define get_accel_slave_descr lis3dh_get_slave_descr
+#endif
+
+#ifdef CONFIG_MPU_SENSORS_LSM303DLHA   /* ST accelerometer */
 struct ext_slave_descr *lsm303dlha_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr lsm303dlha_get_slave_descr
 #endif
 
 /* MPU6000 Accel */
-#if defined(CONFIG_SENSORS_MPU6000) || defined(CONFIG_SENSORS_MPU6000_MODULE)
+#if defined(CONFIG_MPU_SENSORS_MPU6000) || \
+    defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)
 struct ext_slave_descr *mantis_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr mantis_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_MMA8450  /* Freescale accelerometer */
+#ifdef CONFIG_MPU_SENSORS_MMA8450      /* Freescale accelerometer */
 struct ext_slave_descr *mma8450_get_slave_descr(void);
 #undef get_accel_slave_descr
 #define get_accel_slave_descr mma8450_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_MMA8451  /* Freescale accelerometer */
-struct ext_slave_descr *mma8451_get_slave_descr(void);
+#ifdef CONFIG_MPU_SENSORS_MMA845X      /* Freescale accelerometer */
+struct ext_slave_descr *mma845x_get_slave_descr(void);
 #undef get_accel_slave_descr
-#define get_accel_slave_descr mma8451_get_slave_descr
+#define get_accel_slave_descr mma845x_get_slave_descr
 #endif
 
 
@@ -345,54 +394,71 @@ struct ext_slave_descr *mma8451_get_slave_descr(void);
 */
 #define get_compass_slave_descr NULL
 
-#ifdef CONFIG_SENSORS_AK8975   /* AKM compass */
+#ifdef CONFIG_MPU_SENSORS_AK8975       /* AKM compass */
 struct ext_slave_descr *ak8975_get_slave_descr(void);
 #undef get_compass_slave_descr
 #define get_compass_slave_descr ak8975_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_AMI30X   /* AICHI Steel compass */
+#ifdef CONFIG_MPU_SENSORS_AMI30X       /* AICHI Steel  AMI304/305 compass */
 struct ext_slave_descr *ami30x_get_slave_descr(void);
 #undef get_compass_slave_descr
 #define get_compass_slave_descr ami30x_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_HMC5883  /* Honeywell compass */
+#ifdef CONFIG_MPU_SENSORS_AMI306       /* AICHI Steel AMI306 compass */
+struct ext_slave_descr *ami306_get_slave_descr(void);
+#undef get_compass_slave_descr
+#define get_compass_slave_descr ami306_get_slave_descr
+#endif
+
+#ifdef CONFIG_MPU_SENSORS_HMC5883      /* Honeywell compass */
 struct ext_slave_descr *hmc5883_get_slave_descr(void);
 #undef get_compass_slave_descr
 #define get_compass_slave_descr hmc5883_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_MMC314X  /* MEMSIC compass */
+#ifdef CONFIG_MPU_SENSORS_MMC314X      /* MEMSIC compass */
 struct ext_slave_descr *mmc314x_get_slave_descr(void);
 #undef get_compass_slave_descr
 #define get_compass_slave_descr mmc314x_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_LSM303DLHM       /* ST compass */
+#ifdef CONFIG_MPU_SENSORS_LSM303DLHM   /* ST compass */
 struct ext_slave_descr *lsm303dlhm_get_slave_descr(void);
 #undef get_compass_slave_descr
 #define get_compass_slave_descr lsm303dlhm_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_YAS529   /* Yamaha compass */
+#ifdef CONFIG_MPU_SENSORS_YAS529       /* Yamaha compass */
 struct ext_slave_descr *yas529_get_slave_descr(void);
 #undef get_compass_slave_descr
 #define get_compass_slave_descr yas529_get_slave_descr
 #endif
 
-#ifdef CONFIG_SENSORS_HSCDTD00XX       /* Alps compass */
-struct ext_slave_descr *hscdtd00xx_get_slave_descr(void);
+#ifdef CONFIG_MPU_SENSORS_YAS530       /* Yamaha compass */
+struct ext_slave_descr *yas530_get_slave_descr(void);
 #undef get_compass_slave_descr
-#define get_compass_slave_descr hscdtd00xx_get_slave_descr
+#define get_compass_slave_descr yas530_get_slave_descr
 #endif
 
+#ifdef CONFIG_MPU_SENSORS_HSCDTD002B   /* Alps HSCDTD002B compass */
+struct ext_slave_descr *hscdtd002b_get_slave_descr(void);
+#undef get_compass_slave_descr
+#define get_compass_slave_descr hscdtd002b_get_slave_descr
+#endif
+
+#ifdef CONFIG_MPU_SENSORS_HSCDTD004A   /* Alps HSCDTD004A compass */
+struct ext_slave_descr *hscdtd004a_get_slave_descr(void);
+#undef get_compass_slave_descr
+#define get_compass_slave_descr hscdtd004a_get_slave_descr
+#endif
 /*
     Pressure
 */
 #define get_pressure_slave_descr NULL
 
-#ifdef CONFIG_SENSORS_BMA085   /* BMA pressure */
+#ifdef CONFIG_MPU_SENSORS_BMA085       /* BMA pressure */
 struct ext_slave_descr *bma085_get_slave_descr(void);
 #undef get_pressure_slave_descr
 #define get_pressure_slave_descr bma085_get_slave_descr
old mode 100644 (file)
new mode 100755 (executable)
index e257823..a8dcd5a
@@ -1,7 +1,20 @@
 /*
  $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 __MPU3050_H_
@@ -17,7 +30,7 @@
 
 #define MPU_NAME "mpu3050"
 #define DEFAULT_MPU_SLAVEADDR       0x68
-#include "mpu.h"
+
 /*==== MPU REGISTER SET ====*/
 enum mpu_register {
        MPUREG_WHO_AM_I = 0,    /* 00 0x00 */
old mode 100644 (file)
new mode 100755 (executable)
index c02859a..5a63c8f
@@ -1,7 +1,20 @@
 /*
  $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/>.
+  $
  */
 
 /**
 
 /*==== M_HW REGISTER SET ====*/
 enum {
-       MPUREG_XG_OFFS_TC = 0,
-       MPUREG_YG_OFFS_TC,
-       MPUREG_ZG_OFFS_TC,
-       MPUREG_X_FINE_GAIN,
-       MPUREG_Y_FINE_GAIN,
-       MPUREG_Z_FINE_GAIN,
-       MPUREG_XA_OFFS_H,
-       MPUREG_XA_OFFS_L_TC,
-       MPUREG_YA_OFFS_H,
-       MPUREG_YA_OFFS_L_TC,
-       MPUREG_ZA_OFFS_H,
+       MPUREG_XG_OFFS_TC = 0,                  /* 0x00 */
+       MPUREG_YG_OFFS_TC,                      /* 0x00 */
+       MPUREG_ZG_OFFS_TC,                      /* 0x00 */
+       MPUREG_X_FINE_GAIN,                     /* 0x00 */
+       MPUREG_Y_FINE_GAIN,                     /* 0x00 */
+       MPUREG_Z_FINE_GAIN,                     /* 0x00 */
+       MPUREG_XA_OFFS_H,                       /* 0x00 */
+       MPUREG_XA_OFFS_L_TC,                    /* 0x00 */
+       MPUREG_YA_OFFS_H,                       /* 0x00 */
+       MPUREG_YA_OFFS_L_TC,                    /* 0x00 */
+       MPUREG_ZA_OFFS_H,                       /* 0x00 */
        MPUREG_ZA_OFFS_L_TC,    /* 0xB */
-       MPUREG_0C_RSVD,
-       MPUREG_0D_RSVD,
-       MPUREG_0E_RSVD,
-       MPUREG_0F_RSVD,
-       MPUREG_10_RSVD,
-       MPUREG_11_RSVD,
-       MPUREG_12_RSVD,
-       MPUREG_XG_OFFS_USRH,
-       MPUREG_XG_OFFS_USRL,
-       MPUREG_YG_OFFS_USRH,
-       MPUREG_YG_OFFS_USRL,
-       MPUREG_ZG_OFFS_USRH,
-       MPUREG_ZG_OFFS_USRL,
+       MPUREG_0C_RSVD,                 /* 0x00 */
+       MPUREG_0D_RSVD,                 /* 0x00 */
+       MPUREG_0E_RSVD,                 /* 0x00 */
+       MPUREG_0F_RSVD,                 /* 0x00 */
+       MPUREG_10_RSVD,                 /* 0x00 */
+       MPUREG_11_RSVD,                 /* 0x00 */
+       MPUREG_12_RSVD,                 /* 0x00 */
+       MPUREG_XG_OFFS_USRH,                    /* 0x00 */
+       MPUREG_XG_OFFS_USRL,                    /* 0x00 */
+       MPUREG_YG_OFFS_USRH,                    /* 0x00 */
+       MPUREG_YG_OFFS_USRL,                    /* 0x00 */
+       MPUREG_ZG_OFFS_USRH,                    /* 0x00 */
+       MPUREG_ZG_OFFS_USRL,                    /* 0x00 */
        MPUREG_SMPLRT_DIV,      /* 0x19 */
        MPUREG_CONFIG,          /* 0x1A ==> DLPF_FS_SYNC */
-       MPUREG_GYRO_CONFIG,
-       MPUREG_ACCEL_CONFIG,
-       MPUREG_ACCEL_FF_THR,
-       MPUREG_ACCEL_FF_DUR,
-       MPUREG_ACCEL_MOT_THR,
-       MPUREG_ACCEL_MOT_DUR,
-       MPUREG_ACCEL_ZRMOT_THR,
-       MPUREG_ACCEL_ZRMOT_DUR,
+       MPUREG_GYRO_CONFIG,                     /* 0x00 */
+       MPUREG_ACCEL_CONFIG,                    /* 0x00 */
+       MPUREG_ACCEL_FF_THR,                    /* 0x00 */
+       MPUREG_ACCEL_FF_DUR,                    /* 0x00 */
+       MPUREG_ACCEL_MOT_THR,                   /* 0x00 */
+       MPUREG_ACCEL_MOT_DUR,                   /* 0x00 */
+       MPUREG_ACCEL_ZRMOT_THR,                 /* 0x00 */
+       MPUREG_ACCEL_ZRMOT_DUR,                 /* 0x00 */
        MPUREG_FIFO_EN,         /* 0x23 */
-       MPUREG_I2C_MST_CTRL,
+       MPUREG_I2C_MST_CTRL,                    /* 0x00 */
        MPUREG_I2C_SLV0_ADDR,   /* 0x25 */
-       MPUREG_I2C_SLV0_REG,
-       MPUREG_I2C_SLV0_CTRL,
+       MPUREG_I2C_SLV0_REG,                    /* 0x00 */
+       MPUREG_I2C_SLV0_CTRL,                   /* 0x00 */
        MPUREG_I2C_SLV1_ADDR,   /* 0x28 */
-       MPUREG_I2C_SLV1_REG_PASSWORD,
-       MPUREG_I2C_SLV1_CTRL,
+       MPUREG_I2C_SLV1_REG_PASSWORD,                   /* 0x00 */
+       MPUREG_I2C_SLV1_CTRL,                   /* 0x00 */
        MPUREG_I2C_SLV2_ADDR,   /* 0x2B */
-       MPUREG_I2C_SLV2_REG,
-       MPUREG_I2C_SLV2_CTRL,
+       MPUREG_I2C_SLV2_REG,                    /* 0x00 */
+       MPUREG_I2C_SLV2_CTRL,                   /* 0x00 */
        MPUREG_I2C_SLV3_ADDR,   /* 0x2E */
-       MPUREG_I2C_SLV3_REG,
-       MPUREG_I2C_SLV3_CTRL,
+       MPUREG_I2C_SLV3_REG,                    /* 0x00 */
+       MPUREG_I2C_SLV3_CTRL,                   /* 0x00 */
        MPUREG_I2C_SLV4_ADDR,   /* 0x31 */
-       MPUREG_I2C_SLV4_REG,
-       MPUREG_I2C_SLV4_DO,
-       MPUREG_I2C_SLV4_CTRL,
-       MPUREG_I2C_SLV4_DI,
+       MPUREG_I2C_SLV4_REG,                    /* 0x00 */
+       MPUREG_I2C_SLV4_DO,                     /* 0x00 */
+       MPUREG_I2C_SLV4_CTRL,                   /* 0x00 */
+       MPUREG_I2C_SLV4_DI,                     /* 0x00 */
        MPUREG_I2C_MST_STATUS,  /* 0x36 */
        MPUREG_INT_PIN_CFG,     /* 0x37 ==> -* INT_CFG */
        MPUREG_INT_ENABLE,      /* 0x38 ==> / */
        MPUREG_DMP_INT_STATUS,  /* 0x39 */
        MPUREG_INT_STATUS,      /* 0x3A */
        MPUREG_ACCEL_XOUT_H,    /* 0x3B */
-       MPUREG_ACCEL_XOUT_L,
-       MPUREG_ACCEL_YOUT_H,
-       MPUREG_ACCEL_YOUT_L,
-       MPUREG_ACCEL_ZOUT_H,
-       MPUREG_ACCEL_ZOUT_L,
+       MPUREG_ACCEL_XOUT_L,                    /* 0x00 */
+       MPUREG_ACCEL_YOUT_H,                    /* 0x00 */
+       MPUREG_ACCEL_YOUT_L,                    /* 0x00 */
+       MPUREG_ACCEL_ZOUT_H,                    /* 0x00 */
+       MPUREG_ACCEL_ZOUT_L,                    /* 0x00 */
        MPUREG_TEMP_OUT_H,      /* 0x41 */
-       MPUREG_TEMP_OUT_L,
+       MPUREG_TEMP_OUT_L,                      /* 0x00 */
        MPUREG_GYRO_XOUT_H,     /* 0x43 */
-       MPUREG_GYRO_XOUT_L,
-       MPUREG_GYRO_YOUT_H,
-       MPUREG_GYRO_YOUT_L,
-       MPUREG_GYRO_ZOUT_H,
-       MPUREG_GYRO_ZOUT_L,
+       MPUREG_GYRO_XOUT_L,                     /* 0x00 */
+       MPUREG_GYRO_YOUT_H,                     /* 0x00 */
+       MPUREG_GYRO_YOUT_L,                     /* 0x00 */
+       MPUREG_GYRO_ZOUT_H,                     /* 0x00 */
+       MPUREG_GYRO_ZOUT_L,                     /* 0x00 */
        MPUREG_EXT_SLV_SENS_DATA_00,    /* 0x49 */
-       MPUREG_EXT_SLV_SENS_DATA_01,
-       MPUREG_EXT_SLV_SENS_DATA_02,
-       MPUREG_EXT_SLV_SENS_DATA_03,
-       MPUREG_EXT_SLV_SENS_DATA_04,
-       MPUREG_EXT_SLV_SENS_DATA_05,
+       MPUREG_EXT_SLV_SENS_DATA_01,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_02,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_03,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_04,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_05,                    /* 0x00 */
        MPUREG_EXT_SLV_SENS_DATA_06,    /* 0x4F */
-       MPUREG_EXT_SLV_SENS_DATA_07,
-       MPUREG_EXT_SLV_SENS_DATA_08,
-       MPUREG_EXT_SLV_SENS_DATA_09,
-       MPUREG_EXT_SLV_SENS_DATA_10,
-       MPUREG_EXT_SLV_SENS_DATA_11,
+       MPUREG_EXT_SLV_SENS_DATA_07,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_08,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_09,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_10,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_11,                    /* 0x00 */
        MPUREG_EXT_SLV_SENS_DATA_12,    /* 0x55 */
-       MPUREG_EXT_SLV_SENS_DATA_13,
-       MPUREG_EXT_SLV_SENS_DATA_14,
-       MPUREG_EXT_SLV_SENS_DATA_15,
-       MPUREG_EXT_SLV_SENS_DATA_16,
-       MPUREG_EXT_SLV_SENS_DATA_17,
+       MPUREG_EXT_SLV_SENS_DATA_13,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_14,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_15,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_16,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_17,                    /* 0x00 */
        MPUREG_EXT_SLV_SENS_DATA_18,    /* 0x5B */
-       MPUREG_EXT_SLV_SENS_DATA_19,
-       MPUREG_EXT_SLV_SENS_DATA_20,
-       MPUREG_EXT_SLV_SENS_DATA_21,
-       MPUREG_EXT_SLV_SENS_DATA_22,
-       MPUREG_EXT_SLV_SENS_DATA_23,
+       MPUREG_EXT_SLV_SENS_DATA_19,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_20,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_21,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_22,                    /* 0x00 */
+       MPUREG_EXT_SLV_SENS_DATA_23,                    /* 0x00 */
        ACCEL_INTEL_STATUS,     /* 0x61 */
-       MPUREG_62_RSVD,
-       MPUREG_63_RSVD,
-       MPUREG_64_RSVD,
-       MPUREG_65_RSVD,
-       MPUREG_66_RSVD,
-       MPUREG_67_RSVD,
+       MPUREG_62_RSVD,                 /* 0x00 */
+       MPUREG_63_RSVD,                 /* 0x00 */
+       MPUREG_64_RSVD,                 /* 0x00 */
+       MPUREG_65_RSVD,                 /* 0x00 */
+       MPUREG_66_RSVD,                 /* 0x00 */
+       MPUREG_67_RSVD,                 /* 0x00 */
        SIGNAL_PATH_RESET,      /* 0x68 */
        ACCEL_INTEL_CTRL,       /* 0x69 */
        MPUREG_USER_CTRL,       /* 0x6A */
        MPUREG_PWR_MGMT_1,      /* 0x6B */
-       MPUREG_PWR_MGMT_2,
+       MPUREG_PWR_MGMT_2,                      /* 0x00 */
        MPUREG_BANK_SEL,        /* 0x6D */
        MPUREG_MEM_START_ADDR,  /* 0x6E */
        MPUREG_MEM_R_W,         /* 0x6F */
-       MPUREG_PRGM_STRT_ADDRH,
-       MPUREG_PRGM_STRT_ADDRL,
+       MPUREG_PRGM_STRT_ADDRH,                 /* 0x00 */
+       MPUREG_PRGM_STRT_ADDRL,                 /* 0x00 */
        MPUREG_FIFO_COUNTH,     /* 0x72 */
-       MPUREG_FIFO_COUNTL,
+       MPUREG_FIFO_COUNTL,                     /* 0x00 */
        MPUREG_FIFO_R_W,        /* 0x74 */
        MPUREG_WHOAMI,          /* 0x75,117 */
 
@@ -296,7 +309,12 @@ enum MPU_MEMORY_BANKS {
 #define        BIT_STBY_ZG                             0x01
 
 /* although it has 6, this refers to the gyros */
-#define MPU_NUM_AXES (3)
+#define MPU_NUM_AXES     (3)
+
+#define ACCEL_MOT_THR_LSB (32) /* mg */
+#define ACCEL_MOT_DUR_LSB (1)
+#define ACCEL_ZRMOT_THR_LSB_CONVERSION(mg) ((mg *1000)/255)
+#define ACCEL_ZRMOT_DUR_LSB (64)
 
 /*----------------------------------------------------------------------------*/
 /*---- Alternative names to take care of conflicts with current mpu3050.h ----*/