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 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: /drivers/misc/mpu3050 /include/linux/mpu.h /include/linux/mpu3050.h /include/linux/mpu6000.h After this is done the drivers/misc/Kconfig must be edited to add the line: source "drivers/misc/mpu3050/Kconfig" Similarly drivers/misc/Makefile must be edited to add the line: obj-y += mpu3050/ Configuration can then be done as normal. 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 mpu3050_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 #if defined(CONFIG_SENSORS_MPU3050) || defined(CONFIG_SENSORS_MPU3050_MODULE) #define SENSOR_MPU_NAME "mpu3050" static struct mpu3050_platform_data mpu_data = { .int_config = 0x10, .orientation = { -1, 0, 0, 0, 1, 0, 0, 0, -1 }, /* accel */ .accel = { #ifdef CONFIG_SENSORS_MPU3050_MODULE .get_slave_descr = NULL, #else .get_slave_descr = get_accel_slave_descr, #endif .adapt_num = 2, .bus = EXT_SLAVE_BUS_SECONDARY, .address = 0x0F, .orientation = { -1, 0, 0, 0, 1, 0, 0, 0, -1 }, }, /* compass */ .compass = { #ifdef CONFIG_SENSORS_MPU3050_MODULE .get_slave_descr = NULL, #else .get_slave_descr = get_compass_slave_descr, #endif .adapt_num = 2, .bus = EXT_SLAVE_BUS_PRIMARY, .address = 0x0E, .orientation = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }, }, /* pressure */ .pressure = { #ifdef CONFIG_SENSORS_MPU3050_MODULE .get_slave_descr = NULL, #else .get_slave_descr = get_pressure_slave_descr, #endif .adapt_num = 2, .bus = EXT_SLAVE_BUS_PRIMARY, .address = 0x77, .orientation = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }, }, }; #endif #if defined(CONFIG_SENSORS_MPU6000) || defined(CONFIG_SENSORS_MPU6000_MODULE) #define SENSOR_MPU_NAME "mpu6000" static struct mpu3050_platform_data mpu_data = { .int_config = 0x10, .orientation = { -1, 0, 0, 0, 1, 0, 0, 0, -1 }, /* accel */ .accel = { #ifdef CONFIG_SENSORS_MPU6000_MODULE .get_slave_descr = NULL, #else .get_slave_descr = get_accel_slave_descr, #endif .adapt_num = 2, .bus = EXT_SLAVE_BUS_PRIMARY, .address = 0x68, .orientation = { -1, 0, 0, 0, 1, 0, 0, 0, -1 }, }, /* compass */ .compass = { #ifdef CONFIG_SENSORS_MPU6000_MODULE .get_slave_descr = NULL, #else .get_slave_descr = get_compass_slave_descr, #endif .adapt_num = 2, .bus = EXT_SLAVE_BUS_SECONDARY, .address = 0x0E, .orientation = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }, }, /* pressure */ .pressure = { #ifdef CONFIG_SENSORS_MPU6000_MODULE .get_slave_descr = NULL, #else .get_slave_descr = get_pressure_slave_descr, #endif .adapt_num = 2, .bus = EXT_SLAVE_BUS_PRIMARY, .address = 0x77, .orientation = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }, }, }; #endif static struct i2c_board_info __initdata beagle_i2c_2_boardinfo[] = { { I2C_BOARD_INFO(SENSOR_MPU_NAME, 0x68), .irq = (IH_GPIO_BASE + MPU_GPIO_IRQ), .platform_data = &mpu_data, }, }; 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) 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" ,0640, AID_SYSTEM, AID_SYSTEM, 1 }, }; Sufficient file permissions need to be give to read and write it by the system.