aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/inv_mpu/mpu6050/mlsl-kernel.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/misc/inv_mpu/mpu6050/mlsl-kernel.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/misc/inv_mpu/mpu6050/mlsl-kernel.c')
-rw-r--r--drivers/misc/inv_mpu/mpu6050/mlsl-kernel.c420
1 files changed, 420 insertions, 0 deletions
diff --git a/drivers/misc/inv_mpu/mpu6050/mlsl-kernel.c b/drivers/misc/inv_mpu/mpu6050/mlsl-kernel.c
new file mode 100644
index 00000000000..f1c228f48fe
--- /dev/null
+++ b/drivers/misc/inv_mpu/mpu6050/mlsl-kernel.c
@@ -0,0 +1,420 @@
1/*
2 $License:
3 Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 $
18 */
19
20#include "mlsl.h"
21#include <linux/i2c.h>
22#include "log.h"
23#include "mpu6050b1.h"
24
25static int inv_i2c_write(struct i2c_adapter *i2c_adap,
26 unsigned char address,
27 unsigned int len, unsigned char const *data)
28{
29 struct i2c_msg msgs[1];
30 int res;
31
32 if (!data || !i2c_adap) {
33 LOG_RESULT_LOCATION(-EINVAL);
34 return -EINVAL;
35 }
36
37 msgs[0].addr = address;
38 msgs[0].flags = 0; /* write */
39 msgs[0].buf = (unsigned char *)data;
40 msgs[0].len = len;
41
42 res = i2c_transfer(i2c_adap, msgs, 1);
43 if (res < 1) {
44 if (res == 0)
45 res = -EIO;
46 LOG_RESULT_LOCATION(res);
47 return res;
48 } else
49 return 0;
50}
51
52static int inv_i2c_write_register(struct i2c_adapter *i2c_adap,
53 unsigned char address,
54 unsigned char reg, unsigned char value)
55{
56 unsigned char data[2];
57
58 data[0] = reg;
59 data[1] = value;
60 return inv_i2c_write(i2c_adap, address, 2, data);
61}
62
63static int inv_i2c_read(struct i2c_adapter *i2c_adap,
64 unsigned char address, unsigned char reg,
65 unsigned int len, unsigned char *data)
66{
67 struct i2c_msg msgs[2];
68 int res;
69
70 if (!data || !i2c_adap) {
71 LOG_RESULT_LOCATION(-EINVAL);
72 return -EINVAL;
73 }
74
75 msgs[0].addr = address;
76 msgs[0].flags = 0; /* write */
77 msgs[0].buf = &reg;
78 msgs[0].len = 1;
79
80 msgs[1].addr = address;
81 msgs[1].flags = I2C_M_RD;
82 msgs[1].buf = data;
83 msgs[1].len = len;
84
85 res = i2c_transfer(i2c_adap, msgs, 2);
86 if (res < 2) {
87 if (res >= 0)
88 res = -EIO;
89 LOG_RESULT_LOCATION(res);
90 return res;
91 } else
92 return 0;
93}
94
95static int mpu_memory_read(struct i2c_adapter *i2c_adap,
96 unsigned char mpu_addr,
97 unsigned short mem_addr,
98 unsigned int len, unsigned char *data)
99{
100 unsigned char bank[2];
101 unsigned char addr[2];
102 unsigned char buf;
103
104 struct i2c_msg msgs[4];
105 int res;
106
107 if (!data || !i2c_adap) {
108 LOG_RESULT_LOCATION(-EINVAL);
109 return -EINVAL;
110 }
111
112 bank[0] = MPUREG_BANK_SEL;
113 bank[1] = mem_addr >> 8;
114
115 addr[0] = MPUREG_MEM_START_ADDR;
116 addr[1] = mem_addr & 0xFF;
117
118 buf = MPUREG_MEM_R_W;
119
120 /* write message */
121 msgs[0].addr = mpu_addr;
122 msgs[0].flags = 0;
123 msgs[0].buf = bank;
124 msgs[0].len = sizeof(bank);
125
126 msgs[1].addr = mpu_addr;
127 msgs[1].flags = 0;
128 msgs[1].buf = addr;
129 msgs[1].len = sizeof(addr);
130
131 msgs[2].addr = mpu_addr;
132 msgs[2].flags = 0;
133 msgs[2].buf = &buf;
134 msgs[2].len = 1;
135
136 msgs[3].addr = mpu_addr;
137 msgs[3].flags = I2C_M_RD;
138 msgs[3].buf = data;
139 msgs[3].len = len;
140
141 res = i2c_transfer(i2c_adap, msgs, 4);
142 if (res != 4) {
143 if (res >= 0)
144 res = -EIO;
145 LOG_RESULT_LOCATION(res);
146 return res;
147 } else
148 return 0;
149}
150
151static int mpu_memory_write(struct i2c_adapter *i2c_adap,
152 unsigned char mpu_addr,
153 unsigned short mem_addr,
154 unsigned int len, unsigned char const *data)
155{
156 unsigned char bank[2];
157 unsigned char addr[2];
158 unsigned char buf[513];
159
160 struct i2c_msg msgs[3];
161 int res;
162
163 if (!data || !i2c_adap) {
164 LOG_RESULT_LOCATION(-EINVAL);
165 return -EINVAL;
166 }
167 if (len >= (sizeof(buf) - 1)) {
168 LOG_RESULT_LOCATION(-ENOMEM);
169 return -ENOMEM;
170 }
171
172 bank[0] = MPUREG_BANK_SEL;
173 bank[1] = mem_addr >> 8;
174
175 addr[0] = MPUREG_MEM_START_ADDR;
176 addr[1] = mem_addr & 0xFF;
177
178 buf[0] = MPUREG_MEM_R_W;
179 memcpy(buf + 1, data, len);
180
181 /* write message */
182 msgs[0].addr = mpu_addr;
183 msgs[0].flags = 0;
184 msgs[0].buf = bank;
185 msgs[0].len = sizeof(bank);
186
187 msgs[1].addr = mpu_addr;
188 msgs[1].flags = 0;
189 msgs[1].buf = addr;
190 msgs[1].len = sizeof(addr);
191
192 msgs[2].addr = mpu_addr;
193 msgs[2].flags = 0;
194 msgs[2].buf = (unsigned char *)buf;
195 msgs[2].len = len + 1;
196
197 res = i2c_transfer(i2c_adap, msgs, 3);
198 if (res != 3) {
199 if (res >= 0)
200 res = -EIO;
201 LOG_RESULT_LOCATION(res);
202 return res;
203 } else
204 return 0;
205}
206
207int inv_serial_single_write(
208 void *sl_handle,
209 unsigned char slave_addr,
210 unsigned char register_addr,
211 unsigned char data)
212{
213 return inv_i2c_write_register((struct i2c_adapter *)sl_handle,
214 slave_addr, register_addr, data);
215}
216EXPORT_SYMBOL(inv_serial_single_write);
217
218int inv_serial_write(
219 void *sl_handle,
220 unsigned char slave_addr,
221 unsigned short length,
222 unsigned char const *data)
223{
224 int result;
225 const unsigned short data_length = length - 1;
226 const unsigned char start_reg_addr = data[0];
227 unsigned char i2c_write[SERIAL_MAX_TRANSFER_SIZE + 1];
228 unsigned short bytes_written = 0;
229
230 while (bytes_written < data_length) {
231 unsigned short this_len = min(SERIAL_MAX_TRANSFER_SIZE,
232 data_length - bytes_written);
233 if (bytes_written == 0) {
234 result = inv_i2c_write((struct i2c_adapter *)
235 sl_handle, slave_addr,
236 1 + this_len, data);
237 } else {
238 /* manually increment register addr between chunks */
239 i2c_write[0] = start_reg_addr + bytes_written;
240 memcpy(&i2c_write[1], &data[1 + bytes_written],
241 this_len);
242 result = inv_i2c_write((struct i2c_adapter *)
243 sl_handle, slave_addr,
244 1 + this_len, i2c_write);
245 }
246 if (result) {
247 LOG_RESULT_LOCATION(result);
248 return result;
249 }
250 bytes_written += this_len;
251 }
252 return 0;
253}
254EXPORT_SYMBOL(inv_serial_write);
255
256int inv_serial_read(
257 void *sl_handle,
258 unsigned char slave_addr,
259 unsigned char register_addr,
260 unsigned short length,
261 unsigned char *data)
262{
263 int result;
264 unsigned short bytes_read = 0;
265
266 if ((slave_addr & 0x7E) == DEFAULT_MPU_SLAVEADDR
267 && (register_addr == MPUREG_FIFO_R_W ||
268 register_addr == MPUREG_MEM_R_W)) {
269 LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
270 return INV_ERROR_INVALID_PARAMETER;
271 }
272
273 while (bytes_read < length) {
274 unsigned short this_len =
275 min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
276 result = inv_i2c_read((struct i2c_adapter *)sl_handle,
277 slave_addr, register_addr + bytes_read,
278 this_len, &data[bytes_read]);
279 if (result) {
280 LOG_RESULT_LOCATION(result);
281 return result;
282 }
283 bytes_read += this_len;
284 }
285 return 0;
286}
287EXPORT_SYMBOL(inv_serial_read);
288
289int inv_serial_write_mem(
290 void *sl_handle,
291 unsigned char slave_addr,
292 unsigned short mem_addr,
293 unsigned short length,
294 unsigned char const *data)
295{
296 int result;
297 unsigned short bytes_written = 0;
298
299 if ((mem_addr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
300 pr_err("memory read length (%d B) extends beyond its"
301 " limits (%d) if started at location %d\n", length,
302 MPU_MEM_BANK_SIZE, mem_addr & 0xFF);
303 return INV_ERROR_INVALID_PARAMETER;
304 }
305 while (bytes_written < length) {
306 unsigned short this_len =
307 min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_written);
308 result = mpu_memory_write((struct i2c_adapter *)sl_handle,
309 slave_addr, mem_addr + bytes_written,
310 this_len, &data[bytes_written]);
311 if (result) {
312 LOG_RESULT_LOCATION(result);
313 return result;
314 }
315 bytes_written += this_len;
316 }
317 return 0;
318}
319EXPORT_SYMBOL(inv_serial_write_mem);
320
321int inv_serial_read_mem(
322 void *sl_handle,
323 unsigned char slave_addr,
324 unsigned short mem_addr,
325 unsigned short length,
326 unsigned char *data)
327{
328 int result;
329 unsigned short bytes_read = 0;
330
331 if ((mem_addr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
332 printk
333 ("memory read length (%d B) extends beyond its limits (%d) "
334 "if started at location %d\n", length,
335 MPU_MEM_BANK_SIZE, mem_addr & 0xFF);
336 return INV_ERROR_INVALID_PARAMETER;
337 }
338 while (bytes_read < length) {
339 unsigned short this_len =
340 min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
341 result =
342 mpu_memory_read((struct i2c_adapter *)sl_handle,
343 slave_addr, mem_addr + bytes_read,
344 this_len, &data[bytes_read]);
345 if (result) {
346 LOG_RESULT_LOCATION(result);
347 return result;
348 }
349 bytes_read += this_len;
350 }
351 return 0;
352}
353EXPORT_SYMBOL(inv_serial_read_mem);
354
355int inv_serial_write_fifo(
356 void *sl_handle,
357 unsigned char slave_addr,
358 unsigned short length,
359 unsigned char const *data)
360{
361 int result;
362 unsigned char i2c_write[SERIAL_MAX_TRANSFER_SIZE + 1];
363 unsigned short bytes_written = 0;
364
365 if (length > FIFO_HW_SIZE) {
366 printk(KERN_ERR
367 "maximum fifo write length is %d\n", FIFO_HW_SIZE);
368 return INV_ERROR_INVALID_PARAMETER;
369 }
370 while (bytes_written < length) {
371 unsigned short this_len =
372 min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_written);
373 i2c_write[0] = MPUREG_FIFO_R_W;
374 memcpy(&i2c_write[1], &data[bytes_written], this_len);
375 result = inv_i2c_write((struct i2c_adapter *)sl_handle,
376 slave_addr, this_len + 1, i2c_write);
377 if (result) {
378 LOG_RESULT_LOCATION(result);
379 return result;
380 }
381 bytes_written += this_len;
382 }
383 return 0;
384}
385EXPORT_SYMBOL(inv_serial_write_fifo);
386
387int inv_serial_read_fifo(
388 void *sl_handle,
389 unsigned char slave_addr,
390 unsigned short length,
391 unsigned char *data)
392{
393 int result;
394 unsigned short bytes_read = 0;
395
396 if (length > FIFO_HW_SIZE) {
397 printk(KERN_ERR
398 "maximum fifo read length is %d\n", FIFO_HW_SIZE);
399 return INV_ERROR_INVALID_PARAMETER;
400 }
401 while (bytes_read < length) {
402 unsigned short this_len =
403 min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
404 result = inv_i2c_read((struct i2c_adapter *)sl_handle,
405 slave_addr, MPUREG_FIFO_R_W, this_len,
406 &data[bytes_read]);
407 if (result) {
408 LOG_RESULT_LOCATION(result);
409 return result;
410 }
411 bytes_read += this_len;
412 }
413
414 return 0;
415}
416EXPORT_SYMBOL(inv_serial_read_fifo);
417
418/**
419 * @}
420 */