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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
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
|