123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- 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/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.
- 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 <linux/mpu.h>
- #if defined(CONFIG_MPU_SENSORS_MPU3050) || defined(CONFIG_MPU_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_MPU_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_MPU_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_MPU_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_MPU_SENSORS_MPU6000) || defined(CONFIG_MPU_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_MPU_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_MPU_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_MPU_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)
- NOTE:
- =====
- In previous releases, the sensors were defined using CONFIG_SENSORS_SENSORNAME convention.
- From this release onwards this convention will be changed to CONFIG_MPU_SENSORS_SENSORNAME.
- Please make note of this change.
- 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
|