diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/misc/inv_mpu/compass/yas530.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/misc/inv_mpu/compass/yas530.c')
-rw-r--r-- | drivers/misc/inv_mpu/compass/yas530.c | 580 |
1 files changed, 580 insertions, 0 deletions
diff --git a/drivers/misc/inv_mpu/compass/yas530.c b/drivers/misc/inv_mpu/compass/yas530.c new file mode 100644 index 00000000000..fdca05ba8e5 --- /dev/null +++ b/drivers/misc/inv_mpu/compass/yas530.c | |||
@@ -0,0 +1,580 @@ | |||
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 | /** | ||
21 | * @addtogroup COMPASSDL | ||
22 | * | ||
23 | * @{ | ||
24 | * @file yas530.c | ||
25 | * @brief Magnetometer setup and handling methods for Yamaha YAS530 | ||
26 | * compass when used in a user-space solution (no kernel driver). | ||
27 | */ | ||
28 | |||
29 | /* -------------------------------------------------------------------------- */ | ||
30 | |||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/slab.h> | ||
37 | |||
38 | #include <linux/module.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include "mpu-dev.h" | ||
41 | |||
42 | #include "log.h" | ||
43 | #include <linux/mpu.h> | ||
44 | #include "mlsl.h" | ||
45 | #include "mldl_cfg.h" | ||
46 | #undef MPL_LOG_TAG | ||
47 | #define MPL_LOG_TAG "MPL-compass" | ||
48 | |||
49 | /* -------------------------------------------------------------------------- */ | ||
50 | #define YAS530_REGADDR_DEVICE_ID (0x80) | ||
51 | #define YAS530_REGADDR_ACTUATE_INIT_COIL (0x81) | ||
52 | #define YAS530_REGADDR_MEASURE_COMMAND (0x82) | ||
53 | #define YAS530_REGADDR_CONFIG (0x83) | ||
54 | #define YAS530_REGADDR_MEASURE_INTERVAL (0x84) | ||
55 | #define YAS530_REGADDR_OFFSET_X (0x85) | ||
56 | #define YAS530_REGADDR_OFFSET_Y1 (0x86) | ||
57 | #define YAS530_REGADDR_OFFSET_Y2 (0x87) | ||
58 | #define YAS530_REGADDR_TEST1 (0x88) | ||
59 | #define YAS530_REGADDR_TEST2 (0x89) | ||
60 | #define YAS530_REGADDR_CAL (0x90) | ||
61 | #define YAS530_REGADDR_MEASURE_DATA (0xb0) | ||
62 | |||
63 | /* -------------------------------------------------------------------------- */ | ||
64 | static int Cx, Cy1, Cy2; | ||
65 | static int /*a1, */ a2, a3, a4, a5, a6, a7, a8, a9; | ||
66 | static int k; | ||
67 | |||
68 | static unsigned char dx, dy1, dy2; | ||
69 | static unsigned char d2, d3, d4, d5, d6, d7, d8, d9, d0; | ||
70 | static unsigned char dck; | ||
71 | |||
72 | /* -------------------------------------------------------------------------- */ | ||
73 | |||
74 | static int set_hardware_offset(void *mlsl_handle, | ||
75 | struct ext_slave_descr *slave, | ||
76 | struct ext_slave_platform_data *pdata, | ||
77 | char offset_x, char offset_y1, char offset_y2) | ||
78 | { | ||
79 | char data; | ||
80 | int result = INV_SUCCESS; | ||
81 | |||
82 | data = offset_x & 0x3f; | ||
83 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
84 | YAS530_REGADDR_OFFSET_X, data); | ||
85 | if (result) { | ||
86 | LOG_RESULT_LOCATION(result); | ||
87 | return result; | ||
88 | } | ||
89 | |||
90 | data = offset_y1 & 0x3f; | ||
91 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
92 | YAS530_REGADDR_OFFSET_Y1, data); | ||
93 | if (result) { | ||
94 | LOG_RESULT_LOCATION(result); | ||
95 | return result; | ||
96 | } | ||
97 | |||
98 | data = offset_y2 & 0x3f; | ||
99 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
100 | YAS530_REGADDR_OFFSET_Y2, data); | ||
101 | if (result) { | ||
102 | LOG_RESULT_LOCATION(result); | ||
103 | return result; | ||
104 | } | ||
105 | |||
106 | return result; | ||
107 | } | ||
108 | |||
109 | static int set_measure_command(void *mlsl_handle, | ||
110 | struct ext_slave_descr *slave, | ||
111 | struct ext_slave_platform_data *pdata, | ||
112 | int ldtc, int fors, int dlymes) | ||
113 | { | ||
114 | int result = INV_SUCCESS; | ||
115 | |||
116 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
117 | YAS530_REGADDR_MEASURE_COMMAND, 0x01); | ||
118 | if (result) { | ||
119 | LOG_RESULT_LOCATION(result); | ||
120 | return result; | ||
121 | } | ||
122 | |||
123 | return result; | ||
124 | } | ||
125 | |||
126 | static int measure_normal(void *mlsl_handle, | ||
127 | struct ext_slave_descr *slave, | ||
128 | struct ext_slave_platform_data *pdata, | ||
129 | int *busy, unsigned short *t, | ||
130 | unsigned short *x, unsigned short *y1, | ||
131 | unsigned short *y2) | ||
132 | { | ||
133 | unsigned char data[8]; | ||
134 | unsigned short b, to, xo, y1o, y2o; | ||
135 | int result; | ||
136 | ktime_t sleeptime; | ||
137 | result = set_measure_command(mlsl_handle, slave, pdata, 0, 0, 0); | ||
138 | sleeptime = ktime_set(0, 2 * NSEC_PER_MSEC); | ||
139 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
140 | schedule_hrtimeout(&sleeptime, HRTIMER_MODE_REL); | ||
141 | |||
142 | result = inv_serial_read(mlsl_handle, pdata->address, | ||
143 | YAS530_REGADDR_MEASURE_DATA, 8, data); | ||
144 | if (result) { | ||
145 | LOG_RESULT_LOCATION(result); | ||
146 | return result; | ||
147 | } | ||
148 | |||
149 | b = (data[0] >> 7) & 0x01; | ||
150 | to = ((data[0] << 2) & 0x1fc) | ((data[1] >> 6) & 0x03); | ||
151 | xo = ((data[2] << 5) & 0xfe0) | ((data[3] >> 3) & 0x1f); | ||
152 | y1o = ((data[4] << 5) & 0xfe0) | ((data[5] >> 3) & 0x1f); | ||
153 | y2o = ((data[6] << 5) & 0xfe0) | ((data[7] >> 3) & 0x1f); | ||
154 | |||
155 | *busy = b; | ||
156 | *t = to; | ||
157 | *x = xo; | ||
158 | *y1 = y1o; | ||
159 | *y2 = y2o; | ||
160 | |||
161 | return result; | ||
162 | } | ||
163 | |||
164 | static int check_offset(void *mlsl_handle, | ||
165 | struct ext_slave_descr *slave, | ||
166 | struct ext_slave_platform_data *pdata, | ||
167 | char offset_x, char offset_y1, char offset_y2, | ||
168 | int *flag_x, int *flag_y1, int *flag_y2) | ||
169 | { | ||
170 | int result; | ||
171 | int busy; | ||
172 | short t, x, y1, y2; | ||
173 | |||
174 | result = set_hardware_offset(mlsl_handle, slave, pdata, | ||
175 | offset_x, offset_y1, offset_y2); | ||
176 | if (result) { | ||
177 | LOG_RESULT_LOCATION(result); | ||
178 | return result; | ||
179 | } | ||
180 | |||
181 | result = measure_normal(mlsl_handle, slave, pdata, | ||
182 | &busy, &t, &x, &y1, &y2); | ||
183 | if (result) { | ||
184 | LOG_RESULT_LOCATION(result); | ||
185 | return result; | ||
186 | } | ||
187 | |||
188 | *flag_x = 0; | ||
189 | *flag_y1 = 0; | ||
190 | *flag_y2 = 0; | ||
191 | |||
192 | if (x > 2048) | ||
193 | *flag_x = 1; | ||
194 | if (y1 > 2048) | ||
195 | *flag_y1 = 1; | ||
196 | if (y2 > 2048) | ||
197 | *flag_y2 = 1; | ||
198 | if (x < 2048) | ||
199 | *flag_x = -1; | ||
200 | if (y1 < 2048) | ||
201 | *flag_y1 = -1; | ||
202 | if (y2 < 2048) | ||
203 | *flag_y2 = -1; | ||
204 | |||
205 | return result; | ||
206 | } | ||
207 | |||
208 | static int measure_and_set_offset(void *mlsl_handle, | ||
209 | struct ext_slave_descr *slave, | ||
210 | struct ext_slave_platform_data *pdata, | ||
211 | char *offset) | ||
212 | { | ||
213 | int i; | ||
214 | int result = INV_SUCCESS; | ||
215 | char offset_x = 0, offset_y1 = 0, offset_y2 = 0; | ||
216 | int flag_x = 0, flag_y1 = 0, flag_y2 = 0; | ||
217 | static const int correct[5] = { 16, 8, 4, 2, 1 }; | ||
218 | |||
219 | for (i = 0; i < 5; i++) { | ||
220 | result = check_offset(mlsl_handle, slave, pdata, | ||
221 | offset_x, offset_y1, offset_y2, | ||
222 | &flag_x, &flag_y1, &flag_y2); | ||
223 | if (result) { | ||
224 | LOG_RESULT_LOCATION(result); | ||
225 | return result; | ||
226 | } | ||
227 | |||
228 | if (flag_x) | ||
229 | offset_x += flag_x * correct[i]; | ||
230 | if (flag_y1) | ||
231 | offset_y1 += flag_y1 * correct[i]; | ||
232 | if (flag_y2) | ||
233 | offset_y2 += flag_y2 * correct[i]; | ||
234 | } | ||
235 | |||
236 | result = set_hardware_offset(mlsl_handle, slave, pdata, | ||
237 | offset_x, offset_y1, offset_y2); | ||
238 | if (result) { | ||
239 | LOG_RESULT_LOCATION(result); | ||
240 | return result; | ||
241 | } | ||
242 | |||
243 | offset[0] = offset_x; | ||
244 | offset[1] = offset_y1; | ||
245 | offset[2] = offset_y2; | ||
246 | |||
247 | return result; | ||
248 | } | ||
249 | |||
250 | static void coordinate_conversion(short x, short y1, short y2, short t, | ||
251 | int32_t *xo, int32_t *yo, int32_t *zo) | ||
252 | { | ||
253 | int32_t sx, sy1, sy2, sy, sz; | ||
254 | int32_t hx, hy, hz; | ||
255 | |||
256 | sx = x - (Cx * t) / 100; | ||
257 | sy1 = y1 - (Cy1 * t) / 100; | ||
258 | sy2 = y2 - (Cy2 * t) / 100; | ||
259 | |||
260 | sy = sy1 - sy2; | ||
261 | sz = -sy1 - sy2; | ||
262 | |||
263 | hx = k * ((100 * sx + a2 * sy + a3 * sz) / 10); | ||
264 | hy = k * ((a4 * sx + a5 * sy + a6 * sz) / 10); | ||
265 | hz = k * ((a7 * sx + a8 * sy + a9 * sz) / 10); | ||
266 | |||
267 | *xo = hx; | ||
268 | *yo = hy; | ||
269 | *zo = hz; | ||
270 | } | ||
271 | |||
272 | static int yas530_suspend(void *mlsl_handle, | ||
273 | struct ext_slave_descr *slave, | ||
274 | struct ext_slave_platform_data *pdata) | ||
275 | { | ||
276 | int result = INV_SUCCESS; | ||
277 | |||
278 | return result; | ||
279 | } | ||
280 | |||
281 | static int yas530_resume(void *mlsl_handle, | ||
282 | struct ext_slave_descr *slave, | ||
283 | struct ext_slave_platform_data *pdata) | ||
284 | { | ||
285 | int result = INV_SUCCESS; | ||
286 | |||
287 | unsigned char dummyData = 0x00; | ||
288 | char offset[3] = { 0, 0, 0 }; | ||
289 | unsigned char data[16]; | ||
290 | unsigned char read_reg[1]; | ||
291 | |||
292 | /* =============================================== */ | ||
293 | |||
294 | /* Step 1 - Test register initialization */ | ||
295 | dummyData = 0x00; | ||
296 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
297 | YAS530_REGADDR_TEST1, dummyData); | ||
298 | if (result) { | ||
299 | LOG_RESULT_LOCATION(result); | ||
300 | return result; | ||
301 | } | ||
302 | |||
303 | result = | ||
304 | inv_serial_single_write(mlsl_handle, pdata->address, | ||
305 | YAS530_REGADDR_TEST2, dummyData); | ||
306 | if (result) { | ||
307 | LOG_RESULT_LOCATION(result); | ||
308 | return result; | ||
309 | } | ||
310 | |||
311 | /* Device ID read */ | ||
312 | result = inv_serial_read(mlsl_handle, pdata->address, | ||
313 | YAS530_REGADDR_DEVICE_ID, 1, read_reg); | ||
314 | |||
315 | /*Step 2 Read the CAL register */ | ||
316 | /* CAL data read */ | ||
317 | result = inv_serial_read(mlsl_handle, pdata->address, | ||
318 | YAS530_REGADDR_CAL, 16, data); | ||
319 | if (result) { | ||
320 | LOG_RESULT_LOCATION(result); | ||
321 | return result; | ||
322 | } | ||
323 | /* CAL data Second Read */ | ||
324 | result = inv_serial_read(mlsl_handle, pdata->address, | ||
325 | YAS530_REGADDR_CAL, 16, data); | ||
326 | if (result) { | ||
327 | LOG_RESULT_LOCATION(result); | ||
328 | return result; | ||
329 | } | ||
330 | |||
331 | /*Cal data */ | ||
332 | dx = data[0]; | ||
333 | dy1 = data[1]; | ||
334 | dy2 = data[2]; | ||
335 | d2 = (data[3] >> 2) & 0x03f; | ||
336 | d3 = ((data[3] << 2) & 0x0c) | ((data[4] >> 6) & 0x03); | ||
337 | d4 = data[4] & 0x3f; | ||
338 | d5 = (data[5] >> 2) & 0x3f; | ||
339 | d6 = ((data[5] << 4) & 0x30) | ((data[6] >> 4) & 0x0f); | ||
340 | d7 = ((data[6] << 3) & 0x78) | ((data[7] >> 5) & 0x07); | ||
341 | d8 = ((data[7] << 1) & 0x3e) | ((data[8] >> 7) & 0x01); | ||
342 | d9 = ((data[8] << 1) & 0xfe) | ((data[9] >> 7) & 0x01); | ||
343 | d0 = (data[9] >> 2) & 0x1f; | ||
344 | dck = ((data[9] << 1) & 0x06) | ((data[10] >> 7) & 0x01); | ||
345 | |||
346 | /*Correction Data */ | ||
347 | Cx = (int)dx * 6 - 768; | ||
348 | Cy1 = (int)dy1 * 6 - 768; | ||
349 | Cy2 = (int)dy2 * 6 - 768; | ||
350 | a2 = (int)d2 - 32; | ||
351 | a3 = (int)d3 - 8; | ||
352 | a4 = (int)d4 - 32; | ||
353 | a5 = (int)d5 + 38; | ||
354 | a6 = (int)d6 - 32; | ||
355 | a7 = (int)d7 - 64; | ||
356 | a8 = (int)d8 - 32; | ||
357 | a9 = (int)d9; | ||
358 | k = (int)d0 + 10; | ||
359 | |||
360 | /*Obtain the [49:47] bits */ | ||
361 | dck &= 0x07; | ||
362 | |||
363 | /*Step 3 : Storing the CONFIG with the CLK value */ | ||
364 | dummyData = 0x00 | (dck << 2); | ||
365 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
366 | YAS530_REGADDR_CONFIG, dummyData); | ||
367 | if (result) { | ||
368 | LOG_RESULT_LOCATION(result); | ||
369 | return result; | ||
370 | } | ||
371 | |||
372 | /*Step 4 : Set Acquisition Interval Register */ | ||
373 | dummyData = 0x00; | ||
374 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
375 | YAS530_REGADDR_MEASURE_INTERVAL, | ||
376 | dummyData); | ||
377 | if (result) { | ||
378 | LOG_RESULT_LOCATION(result); | ||
379 | return result; | ||
380 | } | ||
381 | |||
382 | /*Step 5 : Reset Coil */ | ||
383 | dummyData = 0x00; | ||
384 | result = inv_serial_single_write(mlsl_handle, pdata->address, | ||
385 | YAS530_REGADDR_ACTUATE_INIT_COIL, | ||
386 | dummyData); | ||
387 | if (result) { | ||
388 | LOG_RESULT_LOCATION(result); | ||
389 | return result; | ||
390 | } | ||
391 | |||
392 | /* Offset Measurement and Set */ | ||
393 | result = measure_and_set_offset(mlsl_handle, slave, pdata, offset); | ||
394 | if (result) { | ||
395 | LOG_RESULT_LOCATION(result); | ||
396 | return result; | ||
397 | } | ||
398 | |||
399 | return result; | ||
400 | } | ||
401 | |||
402 | static int yas530_read(void *mlsl_handle, | ||
403 | struct ext_slave_descr *slave, | ||
404 | struct ext_slave_platform_data *pdata, | ||
405 | unsigned char *data) | ||
406 | { | ||
407 | int result = INV_SUCCESS; | ||
408 | |||
409 | int busy; | ||
410 | short t, x, y1, y2; | ||
411 | int32_t xyz[3]; | ||
412 | short rawfixed[3]; | ||
413 | |||
414 | result = measure_normal(mlsl_handle, slave, pdata, | ||
415 | &busy, &t, &x, &y1, &y2); | ||
416 | if (result) { | ||
417 | LOG_RESULT_LOCATION(result); | ||
418 | return result; | ||
419 | } | ||
420 | |||
421 | coordinate_conversion(x, y1, y2, t, &xyz[0], &xyz[1], &xyz[2]); | ||
422 | |||
423 | rawfixed[0] = (short)(xyz[0] / 100); | ||
424 | rawfixed[1] = (short)(xyz[1] / 100); | ||
425 | rawfixed[2] = (short)(xyz[2] / 100); | ||
426 | |||
427 | data[0] = rawfixed[0] >> 8; | ||
428 | data[1] = rawfixed[0] & 0xFF; | ||
429 | data[2] = rawfixed[1] >> 8; | ||
430 | data[3] = rawfixed[1] & 0xFF; | ||
431 | data[4] = rawfixed[2] >> 8; | ||
432 | data[5] = rawfixed[2] & 0xFF; | ||
433 | |||
434 | if (busy) | ||
435 | return INV_ERROR_COMPASS_DATA_NOT_READY; | ||
436 | return result; | ||
437 | } | ||
438 | |||
439 | static struct ext_slave_descr yas530_descr = { | ||
440 | .init = NULL, | ||
441 | .exit = NULL, | ||
442 | .suspend = yas530_suspend, | ||
443 | .resume = yas530_resume, | ||
444 | .read = yas530_read, | ||
445 | .config = NULL, | ||
446 | .get_config = NULL, | ||
447 | .name = "yas530", | ||
448 | .type = EXT_SLAVE_TYPE_COMPASS, | ||
449 | .id = COMPASS_ID_YAS530, | ||
450 | .read_reg = 0x06, | ||
451 | .read_len = 6, | ||
452 | .endian = EXT_SLAVE_BIG_ENDIAN, | ||
453 | .range = {3276, 8001}, | ||
454 | .trigger = NULL, | ||
455 | }; | ||
456 | |||
457 | static | ||
458 | struct ext_slave_descr *yas530_get_slave_descr(void) | ||
459 | { | ||
460 | return &yas530_descr; | ||
461 | } | ||
462 | |||
463 | /* -------------------------------------------------------------------------- */ | ||
464 | struct yas530_mod_private_data { | ||
465 | struct i2c_client *client; | ||
466 | struct ext_slave_platform_data *pdata; | ||
467 | }; | ||
468 | |||
469 | static unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
470 | |||
471 | static int yas530_mod_probe(struct i2c_client *client, | ||
472 | const struct i2c_device_id *devid) | ||
473 | { | ||
474 | struct ext_slave_platform_data *pdata; | ||
475 | struct yas530_mod_private_data *private_data; | ||
476 | int result = 0; | ||
477 | |||
478 | dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name); | ||
479 | |||
480 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
481 | result = -ENODEV; | ||
482 | goto out_no_free; | ||
483 | } | ||
484 | |||
485 | pdata = client->dev.platform_data; | ||
486 | if (!pdata) { | ||
487 | dev_err(&client->adapter->dev, | ||
488 | "Missing platform data for slave %s\n", devid->name); | ||
489 | result = -EFAULT; | ||
490 | goto out_no_free; | ||
491 | } | ||
492 | |||
493 | private_data = kzalloc(sizeof(*private_data), GFP_KERNEL); | ||
494 | if (!private_data) { | ||
495 | result = -ENOMEM; | ||
496 | goto out_no_free; | ||
497 | } | ||
498 | |||
499 | i2c_set_clientdata(client, private_data); | ||
500 | private_data->client = client; | ||
501 | private_data->pdata = pdata; | ||
502 | |||
503 | result = inv_mpu_register_slave(THIS_MODULE, client, pdata, | ||
504 | yas530_get_slave_descr); | ||
505 | if (result) { | ||
506 | dev_err(&client->adapter->dev, | ||
507 | "Slave registration failed: %s, %d\n", | ||
508 | devid->name, result); | ||
509 | goto out_free_memory; | ||
510 | } | ||
511 | |||
512 | return result; | ||
513 | |||
514 | out_free_memory: | ||
515 | kfree(private_data); | ||
516 | out_no_free: | ||
517 | dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result); | ||
518 | return result; | ||
519 | |||
520 | } | ||
521 | |||
522 | static int yas530_mod_remove(struct i2c_client *client) | ||
523 | { | ||
524 | struct yas530_mod_private_data *private_data = | ||
525 | i2c_get_clientdata(client); | ||
526 | |||
527 | dev_dbg(&client->adapter->dev, "%s\n", __func__); | ||
528 | |||
529 | inv_mpu_unregister_slave(client, private_data->pdata, | ||
530 | yas530_get_slave_descr); | ||
531 | |||
532 | kfree(private_data); | ||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static const struct i2c_device_id yas530_mod_id[] = { | ||
537 | { "yas530", COMPASS_ID_YAS530 }, | ||
538 | {} | ||
539 | }; | ||
540 | |||
541 | MODULE_DEVICE_TABLE(i2c, yas530_mod_id); | ||
542 | |||
543 | static struct i2c_driver yas530_mod_driver = { | ||
544 | .class = I2C_CLASS_HWMON, | ||
545 | .probe = yas530_mod_probe, | ||
546 | .remove = yas530_mod_remove, | ||
547 | .id_table = yas530_mod_id, | ||
548 | .driver = { | ||
549 | .owner = THIS_MODULE, | ||
550 | .name = "yas530_mod", | ||
551 | }, | ||
552 | .address_list = normal_i2c, | ||
553 | }; | ||
554 | |||
555 | static int __init yas530_mod_init(void) | ||
556 | { | ||
557 | int res = i2c_add_driver(&yas530_mod_driver); | ||
558 | pr_info("%s: Probe name %s\n", __func__, "yas530_mod"); | ||
559 | if (res) | ||
560 | pr_err("%s failed\n", __func__); | ||
561 | return res; | ||
562 | } | ||
563 | |||
564 | static void __exit yas530_mod_exit(void) | ||
565 | { | ||
566 | pr_info("%s\n", __func__); | ||
567 | i2c_del_driver(&yas530_mod_driver); | ||
568 | } | ||
569 | |||
570 | module_init(yas530_mod_init); | ||
571 | module_exit(yas530_mod_exit); | ||
572 | |||
573 | MODULE_AUTHOR("Invensense Corporation"); | ||
574 | MODULE_DESCRIPTION("Driver to integrate YAS530 sensor with the MPU"); | ||
575 | MODULE_LICENSE("GPL"); | ||
576 | MODULE_ALIAS("yas530_mod"); | ||
577 | |||
578 | /** | ||
579 | * @} | ||
580 | */ | ||