aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mpu3050/README
blob: 2734dc14163edaf68cad2b9ae950b9d1c18d371e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
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_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.