| Kernel driver mpu |
| ===================== |
| |
| Supported chips: |
| * InvenSense IMU3050 |
| Prefix: 'mpu3050' |
| Datasheet: |
| PS-MPU-3000A-00.2.4b.pdf |
| |
| * InvenSense IMU6000 |
| Prefix: 'mpu6000' |
| Datasheet: |
| MPU-6000A-00 v1.0.pdf |
| |
| Author: InvenSense <http://invensense.com> |
| |
| Description |
| ----------- |
| The mpu is a motion processor unit that controls the mpu3050 gyroscope, a slave |
| accelerometer, a compass and a pressure sensor, or the mpu6000 and slave |
| compass. This document describes how to install the driver into a Linux kernel |
| and a small note about how to set up the file permissions in an android file |
| system. |
| |
| Sysfs entries |
| ------------- |
| /dev/mpu |
| /dev/mpuirq |
| /dev/accelirq |
| /dev/compassirq |
| /dev/pressureirq |
| |
| General Remarks MPU3050 |
| ----------------------- |
| * Valid addresses for the MPU3050 is 0x68. |
| * Accelerometer must be on the secondary I2C bus for MPU3050, the |
| magnetometer must be on the primary bus and pressure sensor must |
| be on the primary bus. |
| |
| General Remarks MPU6000 |
| ----------------------- |
| * Valid addresses for the MPU6000 is 0x68. |
| * Magnetometer must be on the secondary I2C bus for the MPU6000. |
| * Accelerometer slave address must be set to 0x68 |
| * Gyro and Accel orientation matrices should be the same |
| |
| Programming the chip using /dev/mpu |
| ---------------------------------- |
| Programming of MPU3050 or MPU6000 is done by first opening the /dev/mpu file and |
| then performing a series of IOCTLS on the handle returned. The IOCTL codes can |
| be found in mpu.h. Typically this is done by the mllite library in user |
| space. |
| |
| Adding to a Kernel |
| ================== |
| |
| The mpu driver is designed to be inserted in the drivers/misc part of the |
| kernel. Extracting the tarball from the root kernel dir will place the |
| contents of the tarball here: |
| |
| <kernel root dir>/drivers/misc/inv_mpu |
| <kernel root dir>/include/linux/mpu.h |
| <kernel root dir>/include/linux/mpu3050.h |
| <kernel root dir>/include/linux/mpu6000.h |
| |
| After this is done the drivers/misc/Kconfig must be edited to add the line: |
| |
| source "drivers/misc/inv_mpu/Kconfig" |
| |
| Similarly drivers/misc/Makefile must be edited to add the line: |
| |
| obj-y += inv_mpu/ |
| |
| Configuration can then be done as normal. |
| |
| NOTE: This driver depends on a kernel patch to drivers/char/char.c. This patch |
| started to be included in most 2.6.35 based kernels. |
| drivers: misc: pass miscdevice pointer via file private data |
| https://patchwork.kernel.org/patch/96412/ |
| |
| --- |
| drivers/char/misc.c | 1 + |
| 1 files changed, 1 insertions(+), 0 deletions(-) |
| |
| |
| diff --git a/drivers/char/misc.c b/drivers/char/misc.c |
| index 92ab03d..cd650ca 100644 |
| --- a/drivers/char/misc.c |
| +++ b/drivers/char/misc.c |
| @@ -144,6 +144,7 @@ static int misc_open(struct inode * inode, struct file * file) |
| old_fops = file->f_op; |
| file->f_op = new_fops; |
| if (file->f_op->open) { |
| + file->private_data = c; |
| err=file->f_op->open(inode,file); |
| if (err) { |
| fops_put(file->f_op); |
| --- |
| |
| Board and Platform Data |
| ----------------------- |
| |
| In order for the driver to work, board and platform data specific to the device |
| needs to be added to the board file. A mpu_platform_data structure must |
| be created and populated and set in the i2c_board_info_structure. For details |
| of each structure member see mpu.h. All values below are simply an example and |
| should be modified for your platform. |
| |
| #include <linux/mpu.h> |
| |
| #if defined(CONFIG_MPU_SENSORS_MPU3050) |
| |
| static struct mpu_platform_data mpu_data = { |
| .int_config = 0x10, |
| .orientation = { -1, 0, 0, |
| 0, 1, 0, |
| 0, 0, -1 }, |
| /* accel */ |
| .accel = { |
| #ifdef CONFIG_INV_SENSORS_MODULE |
| .get_slave_descr = NULL, |
| #else |
| .get_slave_descr = get_accel_slave_descr, |
| #endif |
| .irq = (IH_GPIO_BASE + 138), |
| .adapt_num = 2, |
| .bus = EXT_SLAVE_BUS_SECONDARY, |
| #ifdef CONFIG_MPU_SENSORS_KXTF9 |
| .address = 0x0F, |
| #elif defined CONFIG_MPU_SENSORS_BMA150 |
| .address = 0x38, |
| #elif defined CONFIG_MPU_SENSORS_LIS331 || defined CONFIG_MPU_SENSORS_LIS303 \ |
| || defined CONFIG_MPU_SENSORS_LIS3DH || defined CONFIG_MPU_SENSORS_KXSD9 |
| .address = 0x18, |
| #elif defined CONFIG_MPU_SENSORS_MMA845X || defined CONFIG_MPU_SENSORS_MMA8450 |
| .address = 0x1C, |
| #elif defined CONFIG_MPU_SENSORS_ADI346 |
| .address = 0x53, |
| #endif |
| .orientation = { -1, 0, 0, |
| 0, 1, 0, |
| 0, 0, -1 }, |
| }, |
| /* compass */ |
| .compass = { |
| #ifdef CONFIG_INV_SENSORS_MODULE |
| .get_slave_descr = NULL, |
| #else |
| .get_slave_descr = get_compass_slave_descr, |
| #endif |
| .irq = (IH_GPIO_BASE + 137), |
| .adapt_num = 2, |
| .bus = EXT_SLAVE_BUS_PRIMARY, |
| #ifdef CONFIG_MPU_SENSORS_AK8975 |
| .address = 0x0E, |
| #elif defined CONFIG_MPU_SENSORS_AMI30x |
| .address = 0x0E, |
| #elif defined CONFIG_MPU_SENSORS_AMI306 |
| .address = 0x0E, |
| #elif defined CONFIG_MPU_SENSORS_YAS529 |
| .address = 0x2E, |
| #elif defined CONFIG_MPU_SENSORS_MMC314X |
| .address = 0x30, |
| #elif defined CONFIG_MPU_SENSORS_HSCDTD00XX |
| .address = 0x0C, |
| #endif |
| .orientation = { 1, 0, 0, |
| 0, 1, 0, |
| 0, 0, 1 }, |
| }, |
| }; |
| #endif |
| |
| #if defined(CONFIG_MPU_SENSORS_MPU6050A2) || \ |
| defined(CONFIG_MPU_SENSORS_MPU6050B1) |
| |
| static struct mpu_platform_data mpu_data = { |
| .int_config = 0x10, |
| .orientation = { -1, 0, 0, |
| 0, 1, 0, |
| 0, 0, -1 }, |
| /* accel */ |
| .accel = { |
| #if defined CONFIG_INV_SENSORS_MODULE |
| .get_slave_descr = NULL, |
| #else |
| .get_slave_descr = get_accel_slave_descr, |
| #endif |
| .irq = (IH_GPIO_BASE + 137), |
| .adapt_num = 2, |
| .bus = EXT_SLAVE_BUS_PRIMARY, |
| .address = 0x68, |
| .orientation = { -1, 0, 0, |
| 0, 1, 0, |
| 0, 0, -1 }, |
| }, |
| /* compass */ |
| .compass = { |
| #if defined CONFIG_INV_SENSORS_MODULE |
| .get_slave_descr = NULL, |
| #else |
| .get_slave_descr = get_compass_slave_descr, |
| #endif |
| .irq = (IH_GPIO_BASE + 138), |
| .adapt_num = 2, |
| .bus = EXT_SLAVE_BUS_SECONDARY, |
| #ifdef CONFIG_MPU_SENSORS_AK8975 |
| .address = 0x0E, |
| #elif defined CONFIG_MPU_SENSORS_AMI30x |
| .address = 0x0E, |
| #elif defined CONFIG_MPU_SENSORS_AMI306 |
| .address = 0x0E, |
| #elif defined CONFIG_MPU_SENSORS_YAS529 |
| .address = 0x2E, |
| #elif defined CONFIG_MPU_SENSORS_MMC314X |
| .address = 0x30, |
| #elif defined CONFIG_MPU_SENSORS_HSCDTD00XX |
| .address = 0x0C, |
| #endif |
| .orientation = { 1, 0, 0, |
| 0, 1, 0, |
| 0, 0, 1 }, |
| }, |
| }; |
| |
| #endif |
| |
| static struct i2c_board_info __initdata beagle_i2c_2_boardinfo[] = { |
| #if defined(CONFIG_MPU_SENSORS_MPU3050) || \ |
| defined(CONFIG_MPU_SENSORS_MPU6050A2) || \ |
| defined(CONFIG_MPU_SENSORS_MPU6050B1) |
| { |
| I2C_BOARD_INFO(MPU_NAME, 0x68), |
| .irq = (IH_GPIO_BASE + MPUIRQ_GPIO), |
| .platform_data = &mpu_data, |
| }, |
| #endif |
| }; |
| |
| Typically the IRQ is a GPIO input pin and needs to be configured properly. If |
| in the above example GPIO 168 corresponds to IRQ 299, the following should be |
| done as well: |
| |
| #define MPU_GPIO_IRQ 168 |
| |
| gpio_request(MPU_GPIO_IRQ,"MPUIRQ"); |
| gpio_direction_input(MPU_GPIO_IRQ) |
| |
| Dynamic Debug |
| ============= |
| |
| The mpu3050 makes use of dynamic debug. For details on how to use this |
| refer to Documentation/dynamic-debug-howto.txt |
| |
| Android File Permissions |
| ======================== |
| |
| To set up the file permissions on an android system, the /dev/mpu and |
| /dev/mpuirq files needs to be added to the system/core/init/devices.c file |
| inside the perms_ structure. |
| |
| static struct perms_ devperms[] = { |
| { "/dev/mpu" ,0660, AID_SYSTEM, AID_SYSTEM, 1 }, |
| }; |
| |
| Sufficient file permissions need to be give to read and write it by the system. |
| |
| For gingerbread and later the system/core/rootdir/ueventd.rc file needs to be |
| modified with the appripriate lines added. |
| |
| # MPU sensors and IRQ |
| /dev/mpu 0660 system system |
| /dev/mpuirq 0660 system system |
| /dev/accelirq 0660 system system |
| /dev/compassirq 0660 system system |
| /dev/pressureirq 0660 system system |