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 and compass, 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

General Remarks MPU3050
-----------------------
* Valid addresses for the MPU3050 is 0x68.
* Accelerometer must be on the secondary I2C bus for MPU3050 and the 
  magnetometer 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/mpu3050
    <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/mpu3050/Kconfig"

Similarly drivers/misc/Makefile must be edited to add the line:

    obj-y += mpu3050/

Configuration can then be done as normal.

Board and Platform Data
-----------------------

In order for the driver to work, board and platform data specific to the device
needs to be added to the board file.  A mpu3050_platform_data structure must
be created and 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_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 },
	 },
};
#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 },
	 },
};
#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.

