};
#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
.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
};
#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
.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
-\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
+
-\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
+
\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
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
},\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
},\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
};\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
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
},\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
},\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
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
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
/*
$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/>.
+ $
*/
/**
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 = {
/*.resume = */ adxl346_resume,
/*.read = */ adxl346_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "adx1346",
/*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER,
/*.id = */ ACCEL_ID_ADI346,
/*
$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/>.
+ $
*/
/**
result =
MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0a, 0x02);
ERROR_CHECK(result);
- MLOSSleep(10);
+ MLOSSleep(3);
result =
MLSLSerialRead(mlsl_handle, pdata->address, 0x14, 1, ®);
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 = {
/*.resume = */ bma150_resume,
/*.read = */ bma150_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "bma150",
/*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER,
/*.id = */ ACCEL_ID_BMA150,
/*
$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/>.
+ $
*/
/*
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 = {
/*.resume = */ bma222_resume,
/*.read = */ bma222_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "bma222",
/*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER,
/*.id = */ ACCEL_ID_BMA222,
/*
$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/>.
+ $
*/
/**
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 = {
/*
$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/>.
+ $
*/
/**
struct ext_slave_platform_data *pdata)
{
int result;
- (void *) slave;
/* CTRL_REGB: low-power standby mode */
result =
MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0d, 0x0);
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 = {
/*.resume = */ kxsd9_resume,
/*.read = */ kxsd9_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "kxsd9",
/*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER,
/*.id = */ ACCEL_ID_KXSD9,
/*
$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. - */
/* ------------------ */
+#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;
}
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;
}
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, ®);
+ 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,
/*
$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. - */
/* ------------------ */
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 1
+
#ifdef __KERNEL__
#include <linux/module.h>
#endif
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 {
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;
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;
}
/**
* @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;
}
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,
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, ®);
+ LIS331_HP_FILTER_RESET, 1, ®1);
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,
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, ®);
+ LIS331_HP_FILTER_RESET, 1, ®1);
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,
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;
}
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;
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,
--- /dev/null
+/*
+ $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, ®1);
+
+ 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, ®1);
+ 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);
+
+/*
+ * @}
+*/
/*
$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/>.
+ $
*/
/**
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 = {
/*.resume = */ lsm303dlha_resume,
/*.read = */ lsm303dlha_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "lsm303dlha",
/*.type = */ EXT_SLAVE_TYPE_ACCELEROMETER,
/*.id = */ ACCEL_ID_LSM303,
/*
$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)
*
* @{
* @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, ®);
+ 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 &= ~(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;
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;
}
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,
/*
$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
/* 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 =
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 = {
/*.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},
};
--- /dev/null
+/*
+ $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, ®);
+ 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, ®);
+ 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);
+
+/**
+ * @}
+ */
/*
$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/>.
+ $
*/
/**
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,
--- /dev/null
+/*
+ $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, ®);
+ 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);
+
+/**
+ * @}
+ */
/*
$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/>.
+ $
*/
/**
/*.resume = */ ami30x_resume,
/*.read = */ ami30x_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "ami30x",
/*.type = */ EXT_SLAVE_TYPE_COMPASS,
/*.id = */ COMPASS_ID_AMI30X,
/*
$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/>.
+ $
*/
/**
/*.resume = */ hmc5883_resume,
/*.read = */ hmc5883_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "hmc5883",
/*.type = */ EXT_SLAVE_TYPE_COMPASS,
/*.id = */ COMPASS_ID_HMC5883,
--- /dev/null
+/*
+ $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);
+
+/**
+ * @}
+**/
--- /dev/null
+/*
+ $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);
+
+/**
+ * @}
+**/
/*
$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/>.
+ $
*/
/**
/*.resume = */ lsm303dlhm_resume,
/*.read = */ lsm303dlhm_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "lsm303dlhm",
/*.type = */ EXT_SLAVE_TYPE_COMPASS,
/*.id = */ COMPASS_ID_LSM303,
/*
$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/>.
+ $
*/
/**
/*.resume = */ mmc314x_resume,
/*.read = */ mmc314x_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "mmc314x",
/*.type = */ EXT_SLAVE_TYPE_COMPASS,
/*.id = */ COMPASS_ID_MMC314X,
/*
$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)
/*.resume = */ yas529_resume,
/*.read = */ yas529_read,
/*.config = */ NULL,
+ /*.get_config = */ NULL,
/*.name = */ "yas529",
/*.type = */ EXT_SLAVE_TYPE_COMPASS,
/*.id = */ COMPASS_ID_YAS529,
--- /dev/null
+/*
+ $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
+
+ /**
+ * @}
+ **/
--- /dev/null
+/*
+ $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);
+
+/**
+ * @}
+**/
#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
*/
#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
#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
* 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
* 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
* 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
* 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
* 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__)
/* --------------------------------------------------------------------- */
* 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
/*
*/
#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
#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)
/*
$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
result = MLSLSerialReadMem(mlsl_handle, pdata->addr,
memAddr, 1, &index);
- ERROR_CHECK(result)
+ ERROR_CHECK(result);
if (result)
return result;
index >>= 2;
result =
MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
MPUREG_BANK_SEL, 0);
- ERROR_CHECK(result)
+ ERROR_CHECK(result);
if (result)
return result;
}
/**
- * @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)
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;
/* 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);
{
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;
/**
* @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
* 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
{
int result = ML_SUCCESS;
-#ifdef CONFIG_SENSORS_MPU_DEBUG
+#ifdef CONFIG_MPU_SENSORS_DEBUG
mpu_print_cfg(mldl_cfg);
#endif
&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) {
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) {
&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);
return result;
}
-
/**
* @brief suspend the MPU3050 device and all the other sensor
* devices into their low power state.
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);
}
/**
* @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.
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;
}
/**
* @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.
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;
}
/**
* @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.
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;
}
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;
+}
+
/**
*@}
/*
$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/>.
+ $
*/
/**
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;
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__ */
/*
$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
/*
$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
/*
$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"
*/
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;
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) {
/*
$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__
/*
$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;
/* - 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; }
#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)
/*
- 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
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>
#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
#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;
if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
-
+ mutex_unlock(&mpu->mutex);
return 0;
}
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
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)
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;
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;
}
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)
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,
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);
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__);
}
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);
"%s: Already suspended %d\n", __func__,
mesg.event);
}
+ mutex_unlock(&mpu->mutex);
return 0;
}
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,
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;
}
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
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;
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 {
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);
}
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);
}
/*
$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/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)
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)
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,
msgs[0].flags = 0; /* write */
msgs[0].buf = ®
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)
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)
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;
/*
$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
/*
$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/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>
};
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);
"%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;
}
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,
/* 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;
}
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) {
/*
$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__
/*
$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/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;
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);
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 =
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;
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,
goto out_misc_register;
}
- init_waitqueue_head(&data->slaveirq_wait);
return res;
out_misc_register:
/*
$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__
--- /dev/null
+/*
+ $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");
--- /dev/null
+/*
+ $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
/*
$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_
#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;
};
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,
};
* @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
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;
*/
#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
*/
#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
/*
$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_
#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 */
/*
$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 */
#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 ----*/