import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / magnetometer / mmc328x_auto / mmc328x.c
CommitLineData
6fa3eb70
S
1/* mmc328x.c - mmc328x compass driver
2 *
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/interrupt.h>
16#include <linux/i2c.h>
17#include <linux/slab.h>
18#include <linux/irq.h>
19#include <linux/miscdevice.h>
20#include <asm/uaccess.h>
21#include <asm/atomic.h>
22#include <linux/delay.h>
23#include <linux/input.h>
24#include <linux/workqueue.h>
25#include <linux/kobject.h>
26#include <linux/platform_device.h>
27#include <linux/earlysuspend.h>
28#include <linux/time.h>
29#include <linux/hrtimer.h>
30
31#include <mach/mt_typedefs.h>
32#include <mach/mt_gpio.h>
33#include <mach/mt_pm_ldo.h>
34
35
36#include <linux/hwmsensor.h>
37#include <linux/hwmsen_dev.h>
38#include <linux/sensors_io.h>
39
40
41#include <cust_mag.h>
42#include "mmc328x.h"
43#include <linux/hwmsen_helper.h>
44/*----------------------------------------------------------------------------*/
45#define DEBUG 1
46#define MMC328x_DEV_NAME "mmc328x"
47#define DRIVER_VERSION "1.0.0"
48/*----------------------------------------------------------------------------*/
49#define MMC328x_DEBUG 1
50#define MMC328x_DEBUG_MSG 1
51#define MMC328x_DEBUG_FUNC 1
52#define MMC328x_DEBUG_DATA 1
53#define MAX_FAILURE_COUNT 3
54#define MMC328x_RETRY_COUNT 10
55#define MMC328x_DEFAULT_DELAY 100
56#define MMC328x_BUFSIZE 0x20
57#define MMC328X_DELAY_RM 10 /* ms */
58
59
60#if MMC328x_DEBUG_MSG
61#define MMCDBG(format, ...) printk(KERN_INFO "mmc328x " format "\n", ## __VA_ARGS__)
62#else
63#define MMCDBG(format, ...)
64#endif
65
66#if MMC328x_DEBUG_FUNC
67#define MMCFUNC(func) printk(KERN_INFO "mmc328x " func " is called\n")
68#else
69#define MMCFUNC(func)
70#endif
71
72static struct i2c_client *this_client = NULL;
73
74
75// calibration msensor and orientation data
76static int sensor_data[CALIBRATION_DATA_SIZE];
77static struct mutex sensor_data_mutex;
78static struct mutex read_i2c_xyz;
79static DECLARE_WAIT_QUEUE_HEAD(data_ready_wq);
80static DECLARE_WAIT_QUEUE_HEAD(open_wq);
81
82static int mmcd_delay = MMC328x_DEFAULT_DELAY;
83
84static atomic_t open_flag = ATOMIC_INIT(0);
85static atomic_t m_flag = ATOMIC_INIT(0);
86static atomic_t o_flag = ATOMIC_INIT(0);
87
88/*----------------------------------------------------------------------------*/
89/*----------------------------------------------------------------------------*/
90static const struct i2c_device_id mmc328x_i2c_id[] = {{MMC328x_DEV_NAME,0},{}};
91/*the adapter id will be available in customization*/
92static unsigned short mmc328x_force[] = {0x00, MMC328x_I2C_ADDR, I2C_CLIENT_END, I2C_CLIENT_END};
93static const unsigned short *const mmc328x_forces[] = { mmc328x_force, NULL };
94static struct i2c_client_address_data mmc328x_addr_data = { .forces = mmc328x_forces,};
95/*----------------------------------------------------------------------------*/
96static int mmc328x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
97static int mmc328x_i2c_remove(struct i2c_client *client);
98static int mmc328x_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info);
99//static int mmc_probe(struct platform_device *pdev);
100//static int mmc_remove(struct platform_device *pdev);
101static int mmc328x_local_init(void);
102static int mmc328x_remove(void);
103
104static int mmc328x_init_flag =0; // 0<==>OK -1 <==> fail
105
106
107
108/*----------------------------------------------------------------------------*/
109typedef enum {
110 MMC_FUN_DEBUG = 0x01,
111 MMC_DATA_DEBUG = 0X02,
112 MMC_HWM_DEBUG = 0X04,
113 MMC_CTR_DEBUG = 0X08,
114 MMC_I2C_DEBUG = 0x10,
115} MMC_TRC;
116
117#define MMC328x_DELAY_TM 10 /* ms */
118#define MMC328x_DELAY_SET 10 /* ms */
119#define MMC328x_DELAY_RST 10 /* ms */
120#define MMC328x_DELAY_STDN 1 /* ms */
121
122#define MMC328x_RESET_INTV 10
123
124static u32 read_idx = 0;
125
126
127static struct sensor_init_info mmc328x_init_info = {
128 .name = "mmc328x",
129 .init = mmc328x_local_init,
130 .uninit = mmc328x_remove,
131
132};
133
134
135/*----------------------------------------------------------------------------*/
136struct mmc328x_i2c_data {
137 struct i2c_client *client;
138 struct mag_hw *hw;
139 atomic_t layout;
140 atomic_t trace;
141 struct hwmsen_convert cvt;
142#if defined(CONFIG_HAS_EARLYSUSPEND)
143 struct early_suspend early_drv;
144#endif
145};
146/*----------------------------------------------------------------------------*/
147static struct i2c_driver mmc328x_i2c_driver = {
148 .driver = {
149 .owner = THIS_MODULE,
150 .name = MMC328x_DEV_NAME,
151 },
152 .probe = mmc328x_i2c_probe,
153 .remove = mmc328x_i2c_remove,
154 .detect = mmc328x_i2c_detect,
155#if !defined(CONFIG_HAS_EARLYSUSPEND)
156 .suspend = mmc328x_suspend,
157 .resume = mmc328x_resume,
158#endif
159 .id_table = mmc328x_i2c_id,
160 .address_data = &mmc328x_addr_data,
161};
162
163/*----------------------------------------------------------------------------*/
164static atomic_t dev_open_count;
165
166static int mmc328x_SetPowerMode(struct i2c_client *client, bool enable)
167{
168 u8 databuf[2];
169 int res = 0;
170 u8 addr = MMC328x_REG_CTRL;
171 struct mmc328x_i2c_data *obj = i2c_get_clientdata(client);
172
173 if(hwmsen_read_byte(client, addr, databuf))
174 {
175 printk("mmc328x: read power ctl register err and retry!\n");
176 if(hwmsen_read_byte(client, addr, databuf))
177 {
178 printk("mmc328x: read power ctl register retry err!\n");
179 return -1;
180 }
181 }
182
183 databuf[0] &= ~MMC328x_CTRL_TM;
184
185 if(enable == TRUE)
186 {
187 databuf[0] |= MMC328x_CTRL_TM;
188 }
189 else
190 {
191 // do nothing
192 }
193 databuf[1] = databuf[0];
194 databuf[0] = MMC328x_REG_CTRL;
195
196
197 res = i2c_master_send(client, databuf, 0x2);
198
199 if(res <= 0)
200 {
201 printk("mmc328x: set power mode failed!\n");
202 return -1;
203 }
204 else
205 {
206 printk("mmc328x: set power mode ok %x!\n", databuf[1]);
207 }
208
209 return 0;
210}
211/*----------------------------------------------------------------------------*/
212
213/*----------------------------------------------------------------------------*/
214static void mmc328x_power(struct mag_hw *hw, unsigned int on)
215{
216 static unsigned int power_on = 0;
217
218 if(hw->power_id != MT65XX_POWER_NONE)
219 {
220 MMCDBG("power %s\n", on ? "on" : "off");
221 if(power_on == on)
222 {
223 MMCDBG("ignore power control: %d\n", on);
224 }
225 else if(on)
226 {
227 if(!hwPowerOn(hw->power_id, hw->power_vol, "mmc328x"))
228 {
229 printk(KERN_ERR "power on fails!!\n");
230 }
231 }
232 else
233 {
234 if(!hwPowerDown(hw->power_id, "mmc328x"))
235 {
236 printk(KERN_ERR "power off fail!!\n");
237 }
238 }
239 }
240 power_on = on;
241}
242static int I2C_RxData(char *rxData, int length)
243{
244 uint8_t loop_i;
245
246#if DEBUG
247 int i;
248 struct i2c_client *client = this_client;
249 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
250 char addr = rxData[0];
251#endif
252
253
254 /* Caller should check parameter validity.*/
255 if((rxData == NULL) || (length < 1))
256 {
257 return -EINVAL;
258 }
259
260 for(loop_i = 0; loop_i < MMC328x_RETRY_COUNT; loop_i++)
261 {
262 this_client->addr = this_client->addr & I2C_MASK_FLAG | I2C_WR_FLAG;
263 if(i2c_master_send(this_client, (const char*)rxData, ((length<<0X08) | 0X01)))
264 {
265 break;
266 }
267 printk("I2C_RxData delay!\n");
268 mdelay(10);
269 }
270
271 if(loop_i >= MMC328x_RETRY_COUNT)
272 {
273 printk(KERN_ERR "%s retry over %d\n", __func__, MMC328x_RETRY_COUNT);
274 return -EIO;
275 }
276#if DEBUG
277 if(atomic_read(&data->trace) & MMC_I2C_DEBUG)
278 {
279 printk(KERN_INFO "RxData: len=%02x, addr=%02x\n data=", length, addr);
280 for(i = 0; i < length; i++)
281 {
282 printk(KERN_INFO " %02x", rxData[i]);
283 }
284 printk(KERN_INFO "\n");
285 }
286#endif
287 return 0;
288}
289
290static int I2C_TxData(char *txData, int length)
291{
292 uint8_t loop_i;
293
294#if DEBUG
295 int i;
296 struct i2c_client *client = this_client;
297 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
298#endif
299
300 /* Caller should check parameter validity.*/
301 if ((txData == NULL) || (length < 2))
302 {
303 return -EINVAL;
304 }
305
306 this_client->addr = this_client->addr & I2C_MASK_FLAG;
307 for(loop_i = 0; loop_i < MMC328x_RETRY_COUNT; loop_i++)
308 {
309 if(i2c_master_send(this_client, (const char*)txData, length) > 0)
310 {
311 break;
312 }
313 printk("I2C_TxData delay!\n");
314 mdelay(10);
315 }
316
317 if(loop_i >= MMC328x_RETRY_COUNT)
318 {
319 printk(KERN_ERR "%s retry over %d\n", __func__, MMC328x_RETRY_COUNT);
320 return -EIO;
321 }
322#if DEBUG
323 if(atomic_read(&data->trace) & MMC_I2C_DEBUG)
324 {
325 printk(KERN_INFO "TxData: len=%02x, addr=%02x\n data=", length, txData[0]);
326 for(i = 0; i < (length-1); i++)
327 {
328 printk(KERN_INFO " %02x", txData[i + 1]);
329 }
330 printk(KERN_INFO "\n");
331 }
332#endif
333 return 0;
334}
335
336
337// Daemon application save the data
338static int ECS_SaveData(int buf[12])
339{
340#if DEBUG
341 struct i2c_client *client = this_client;
342 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
343#endif
344
345 mutex_lock(&sensor_data_mutex);
346 memcpy(sensor_data, buf, sizeof(sensor_data));
347 mutex_unlock(&sensor_data_mutex);
348
349#if DEBUG
350 if(atomic_read(&data->trace) & MMC_HWM_DEBUG)
351 {
352 MMCDBG("Get daemon data: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d!\n",
353 sensor_data[0],sensor_data[1],sensor_data[2],sensor_data[3],
354 sensor_data[4],sensor_data[5],sensor_data[6],sensor_data[7],
355 sensor_data[8],sensor_data[9],sensor_data[10],sensor_data[11]);
356 }
357#endif
358
359 return 0;
360
361}
362static int ECS_ReadXYZData(int *vec, int size)
363{
364 unsigned char data[6] = {0,0,0,0,0,0};
365 ktime_t expires;
366 int wait_n=0;
367 int MD_times = 0;
368 static int last_data[3];
369 struct timespec time1, time2, time3,time4,delay,aa;
370#if DEBUG
371 struct i2c_client *client = this_client;
372 struct mmc328x_i2c_data *clientdata = i2c_get_clientdata(client);
373#endif
374//set_current_state(TASK_INTERRUPTIBLE);
375time1 = current_kernel_time();
376
377 if(size < 3)
378 {
379 return -1;
380 }
381 mutex_lock(&read_i2c_xyz);
382#if 0
383 /* do RESET/SET every MMC328x_RESET_INTV times read */
384 if (!(read_idx % MMC328x_RESET_INTV))
385 {
386 /* SET */
387 data[0] = MMC328x_REG_CTRL;
388 data[1] = MMC328x_CTRL_SET;
389 /* not check return value here, assume it always OK */
390 I2C_TxData(data, 2);
391 //delay.tv_sec =0;
392 //delay.tv_nsec = MMC328x_DELAY_STDN *1000;
393 //hrtimer_nanosleep(&delay, &aa, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
394 msleep(MMC328x_DELAY_STDN);
395 }
396
397
398 /* wait TM done for coming data read */
399// time2 = current_kernel_time();
400
401 time3 = current_kernel_time();
402 /* read xyz raw data */
403 read_idx++;
404 data[0] = MMC328x_REG_DATA;
405 if(I2C_RxData(data, 6) < 0)
406 {
407 mutex_unlock(&read_i2c_xyz);
408 return -EFAULT;
409 }
410 vec[0] = data[0] << 8 | data[1];
411 vec[1] = data[2] << 8 | data[3];
412 vec[2] = data[4] << 8 | data[5];
413 for(wait_n=0; wait_n<10; wait_n++)
414{
415 if((vec[0]!=0) && (vec[1]!=0)&&(vec[2]!=0))
416 break;
417 data[0] = MMC328x_REG_DATA;
418 if(I2C_RxData(data, 6) < 0)
419 {
420 mutex_unlock(&read_i2c_xyz);
421 return -EFAULT;
422 }
423 vec[0] = data[0] << 8 | data[1];
424 vec[1] = data[2] << 8 | data[3];
425 vec[2] = data[4] << 8 | data[5];
426 }
427 time4 = current_kernel_time();
428// printk("start time %d - %d, sleep %d - %d , stop %d !\r\n", time1.tv_sec, time1.tv_nsec, time2.tv_nsec, time3.tv_nsec, time4.tv_nsec);
429#if DEBUG
430 if(atomic_read(&clientdata->trace) & MMC_DATA_DEBUG)
431 {
432 printk("[X - %04x] [Y - %04x] [Z - %04x]\r\n", vec[0], vec[1], vec[2]);
433 if((vec[0]-last_data[0] > 100) ||(last_data[0]-vec[0] > 100) ||
434 (vec[1]-last_data[1] > 100) ||(last_data[1]-vec[1] > 100) ||
435 (vec[2]-last_data[2] > 100) ||(last_data[2]-vec[2] > 100))
436 {
437 msleep(3000);
438 printk("data error!\r\n");
439 }}
440#endif
441 /* send TM cmd before read */
442 data[0] = MMC328x_REG_CTRL;
443 data[1] = MMC328x_CTRL_TM;
444 /* not check return value here, assume it always OK */
445 I2C_TxData(data, 2);
446#endif
447 time2 = current_kernel_time();
448
449if (!(read_idx % MMC328x_RESET_INTV))
450 {
451 /* RM */
452 data[0] = MMC328x_REG_CTRL;
453 data[1] = MMC328x_CTRL_RM;
454 /* not check return value here, assume it always OK */
455 I2C_TxData(data, 2);
456 /* wait external capacitor charging done for next RM */
457 msleep(MMC328X_DELAY_RM);
458 }
459 time3 = current_kernel_time();
460 /* send TM cmd before read */
461 data[0] = MMC328x_REG_CTRL;
462 data[1] = MMC328x_CTRL_TM;
463 /* not check return value here, assume it always OK */
464 I2C_TxData(data, 2);
465 msleep(MMC328x_DELAY_TM);
466
467 /* Read MD */
468 data[0] = MMC328x_REG_DS;
469 I2C_RxData(data, 1);
470 while (!(data[0] & 0x01)) {
471 msleep(1);
472 /* Read MD again*/
473 data[0] = MMC328x_REG_DS;
474 I2C_RxData(data, 1);
475 if (data[0] & 0x01) break;
476 MD_times++;
477 if (MD_times > 3) {
478 printk("TM not work!!");
479 mutex_unlock(&read_i2c_xyz);
480 return -EFAULT;
481 }
482 }
483 read_idx++;
484 data[0] = MMC328x_REG_DATA;
485 if(I2C_RxData(data, 6) < 0)
486 {
487 mutex_unlock(&read_i2c_xyz);
488 return -EFAULT;
489 }
490 vec[0] = data[1] << 8 | data[0];
491 vec[1] = data[3] << 8 | data[2];
492 vec[2] = data[5] << 8 | data[4];
493#if DEBUG
494 if(atomic_read(&clientdata->trace) & MMC_DATA_DEBUG)
495 {
496 printk("[X - %04x] [Y - %04x] [Z - %04x]\n", vec[0], vec[1], vec[2]);
497 }
498#endif
499 mutex_unlock(&read_i2c_xyz);
500 last_data[0] = vec[0];
501 last_data[1] = vec[1];
502 last_data[2] = vec[2];
503 return 0;
504}
505
506static int ECS_GetRawData(int data[3])
507{
508 int err = 0;
509 err = ECS_ReadXYZData(data, 3);
510 if(err !=0 )
511 {
512 printk(KERN_ERR "MMC328x_IOC_TM failed\n");
513 return -1;
514 }
515
516 // sensitivity 512 count = 1 Guass = 100uT
517 data[0] = (data[0] - MMC328X_OFFSET_X) * 100 / MMC328X_SENSITIVITY_X;
518 data[1] = (data[1] - MMC328X_OFFSET_X) * 100 / MMC328X_SENSITIVITY_X;
519 data[2] = (data[2] - MMC328X_OFFSET_X) * 100 / MMC328X_SENSITIVITY_X;
520
521 return err;
522}
523static int ECS_GetOpenStatus(void)
524{
525 wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
526 return atomic_read(&open_flag);
527}
528
529
530/*----------------------------------------------------------------------------*/
531static int mmc328x_ReadChipInfo(char *buf, int bufsize)
532{
533 if((!buf)||(bufsize <= MMC328x_BUFSIZE -1))
534 {
535 return -1;
536 }
537 if(!this_client)
538 {
539 *buf = 0;
540 return -2;
541 }
542
543 sprintf(buf, "mmc328x Chip");
544 return 0;
545}
546
547/*----------------------------------------------------------------------------*/
548static ssize_t show_chipinfo_value(struct device_driver *ddri, char *buf)
549{
550 char strbuf[MMC328x_BUFSIZE];
551 mmc328x_ReadChipInfo(strbuf, MMC328x_BUFSIZE);
552 return sprintf(buf, "%s\n", strbuf);
553}
554/*----------------------------------------------------------------------------*/
555static ssize_t show_sensordata_value(struct device_driver *ddri, char *buf)
556{
557
558 int sensordata[3];
559 char strbuf[MMC328x_BUFSIZE];
560
561 ECS_GetRawData(sensordata);
562
563
564 sprintf(strbuf, "%d %d %d\n", sensordata[0],sensordata[1],sensordata[2]);
565
566 return sprintf(buf, "%s\n", strbuf);
567}
568/*----------------------------------------------------------------------------*/
569static ssize_t show_posturedata_value(struct device_driver *ddri, char *buf)
570{
571 int tmp[3];
572 char strbuf[MMC328x_BUFSIZE];
573 tmp[0] = sensor_data[0] * CONVERT_O / CONVERT_O_DIV;
574 tmp[1] = sensor_data[1] * CONVERT_O / CONVERT_O_DIV;
575 tmp[2] = sensor_data[2] * CONVERT_O / CONVERT_O_DIV;
576 sprintf(strbuf, "%d, %d, %d\n", tmp[0],tmp[1], tmp[2]);
577
578 return sprintf(buf, "%s\n", strbuf);;
579}
580
581/*----------------------------------------------------------------------------*/
582static ssize_t show_layout_value(struct device_driver *ddri, char *buf)
583{
584 struct i2c_client *client = this_client;
585 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
586
587 return sprintf(buf, "(%d, %d)\n[%+2d %+2d %+2d]\n[%+2d %+2d %+2d]\n",
588 data->hw->direction,atomic_read(&data->layout), data->cvt.sign[0], data->cvt.sign[1],
589 data->cvt.sign[2],data->cvt.map[0], data->cvt.map[1], data->cvt.map[2]);
590}
591/*----------------------------------------------------------------------------*/
592static ssize_t store_layout_value(struct device_driver *ddri, char *buf, size_t count)
593{
594 struct i2c_client *client = this_client;
595 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
596 int layout = 0;
597
598 if(1 == sscanf(buf, "%d", &layout))
599 {
600 atomic_set(&data->layout, layout);
601 if(!hwmsen_get_convert(layout, &data->cvt))
602 {
603 printk(KERN_ERR "HWMSEN_GET_CONVERT function error!\r\n");
604 }
605 else if(!hwmsen_get_convert(data->hw->direction, &data->cvt))
606 {
607 printk(KERN_ERR "invalid layout: %d, restore to %d\n", layout, data->hw->direction);
608 }
609 else
610 {
611 printk(KERN_ERR "invalid layout: (%d, %d)\n", layout, data->hw->direction);
612 hwmsen_get_convert(0, &data->cvt);
613 }
614 }
615 else
616 {
617 printk(KERN_ERR "invalid format = '%s'\n", buf);
618 }
619
620 return count;
621}
622/*----------------------------------------------------------------------------*/
623static ssize_t show_status_value(struct device_driver *ddri, char *buf)
624{
625 struct i2c_client *client = this_client;
626 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
627 ssize_t len = 0;
628
629 if(data->hw)
630 {
631 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: %d %d (%d %d)\n",
632 data->hw->i2c_num, data->hw->direction, data->hw->power_id, data->hw->power_vol);
633 }
634 else
635 {
636 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");
637 }
638
639 len += snprintf(buf+len, PAGE_SIZE-len, "OPEN: %d\n", atomic_read(&dev_open_count));
640 return len;
641}
642/*----------------------------------------------------------------------------*/
643static ssize_t show_trace_value(struct device_driver *ddri, char *buf)
644{
645 ssize_t res;
646 struct mmc328x_i2c_data *obj = i2c_get_clientdata(this_client);
647 if(NULL == obj)
648 {
649 printk(KERN_ERR "mmc328x_i2c_data is null!!\n");
650 return 0;
651 }
652
653 res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&obj->trace));
654 return res;
655}
656/*----------------------------------------------------------------------------*/
657static ssize_t store_trace_value(struct device_driver *ddri, char *buf, size_t count)
658{
659 struct mmc328x_i2c_data *obj = i2c_get_clientdata(this_client);
660 int trace;
661 if(NULL == obj)
662 {
663 printk(KERN_ERR "mmc328x_i2c_data is null!!\n");
664 return 0;
665 }
666
667 if(1 == sscanf(buf, "0x%x", &trace))
668 {
669 atomic_set(&obj->trace, trace);
670 }
671 else
672 {
673 printk(KERN_ERR "invalid content: '%s', length = %d\n", buf, count);
674 }
675
676 return count;
677}
678
679static ssize_t show_daemon_name(struct device_driver *ddri, char *buf)
680{
681 char strbuf[MMC328x_BUFSIZE];
682 sprintf(strbuf, "memsicd");
683 return sprintf(buf, "%s", strbuf);
684}
685
686/*----------------------------------------------------------------------------*/
687static DRIVER_ATTR(daemon, S_IRUGO, show_daemon_name, NULL);
688static DRIVER_ATTR(chipinfo, S_IRUGO, show_chipinfo_value, NULL);
689static DRIVER_ATTR(sensordata, S_IRUGO, show_sensordata_value, NULL);
690static DRIVER_ATTR(posturedata, S_IRUGO, show_posturedata_value, NULL);
691static DRIVER_ATTR(layout, S_IRUGO | S_IWUSR, show_layout_value, store_layout_value);
692static DRIVER_ATTR(status, S_IRUGO, show_status_value, NULL);
693static DRIVER_ATTR(trace, S_IRUGO | S_IWUSR, show_trace_value, store_trace_value);
694/*----------------------------------------------------------------------------*/
695static struct driver_attribute *mmc328x_attr_list[] = {
696 &driver_attr_daemon,
697 &driver_attr_chipinfo,
698 &driver_attr_sensordata,
699 &driver_attr_posturedata,
700 &driver_attr_layout,
701 &driver_attr_status,
702 &driver_attr_trace,
703};
704/*----------------------------------------------------------------------------*/
705static int mmc328x_create_attr(struct device_driver *driver)
706{
707 int idx, err = 0;
708 int num = (int)(sizeof(mmc328x_attr_list)/sizeof(mmc328x_attr_list[0]));
709 if (driver == NULL)
710 {
711 return -EINVAL;
712 }
713
714 for(idx = 0; idx < num; idx++)
715 {
716 if(err = driver_create_file(driver, mmc328x_attr_list[idx]))
717 {
718 printk(KERN_ERR "driver_create_file (%s) = %d\n", mmc328x_attr_list[idx]->attr.name, err);
719 break;
720 }
721 }
722
723 return err;
724}
725/*----------------------------------------------------------------------------*/
726static int mmc328x_delete_attr(struct device_driver *driver)
727{
728 int idx;
729 int num = (int)(sizeof(mmc328x_attr_list)/sizeof(mmc328x_attr_list[0]));
730
731 if(driver == NULL)
732 {
733 return -EINVAL;
734 }
735
736
737 for(idx = 0; idx < num; idx++)
738 {
739 driver_remove_file(driver, mmc328x_attr_list[idx]);
740 }
741
742
743 return 0;
744}
745
746
747/*----------------------------------------------------------------------------*/
748static int mmc328x_open(struct inode *inode, struct file *file)
749{
750 struct mmc328x_i2c_data *obj = i2c_get_clientdata(this_client);
751 int ret = -1;
752
753 if(atomic_read(&obj->trace) & MMC_CTR_DEBUG)
754 {
755 MMCDBG("Open device node:mmc328x\n");
756 }
757 ret = nonseekable_open(inode, file);
758
759 return ret;
760}
761/*----------------------------------------------------------------------------*/
762static int mmc328x_release(struct inode *inode, struct file *file)
763{
764 struct mmc328x_i2c_data *obj = i2c_get_clientdata(this_client);
765 atomic_dec(&dev_open_count);
766 if(atomic_read(&obj->trace) & MMC_CTR_DEBUG)
767 {
768 MMCDBG("Release device node:mmc328x\n");
769 }
770 return 0;
771}
772/*----------------------------------------------------------------------------*/
773static int mmc328x_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
774{
775 void __user *argp = (void __user *)arg;
776
777 /* NOTE: In this function the size of "char" should be 1-byte. */
778 char buff[MMC328x_BUFSIZE]; /* for chip information */
779
780 int value[12]; /* for SET_YPR */
781 int delay; /* for GET_DELAY */
782 int status; /* for OPEN/CLOSE_STATUS */
783 short sensor_status; /* for Orientation and Msensor status */
784 unsigned char data[16] = {0};
785 int vec[3] = {0};
786 struct i2c_client *client = this_client;
787 struct mmc328x_i2c_data *clientdata = i2c_get_clientdata(client);
788 hwm_sensor_data* osensor_data;
789 uint32_t enable;
790
791
792 switch (cmd)
793 {
794 case MMC31XX_IOC_TM:
795 data[0] = MMC328x_REG_CTRL;
796 data[1] = MMC328x_CTRL_TM;
797 if (I2C_TxData(data, 2) < 0)
798 {
799 printk(KERN_ERR "MMC328x_IOC_TM failed\n");
800 return -EFAULT;
801 }
802 /* wait TM done for coming data read */
803 msleep(MMC328x_DELAY_TM);
804 break;
805
806 case MMC31XX_IOC_SET:
807 data[0] = MMC328x_REG_CTRL;
808 data[1] = MMC328x_REG_DS;
809 if(I2C_TxData(data, 2) < 0)
810 {
811 printk(KERN_ERR "MMC328x_IOC_SET failed\n");
812 return -EFAULT;
813 }
814 /* wait external capacitor charging done for next SET/RESET */
815 msleep(MMC328x_DELAY_SET);
816 break;
817
818 case MMC31XX_IOC_RESET:
819 data[0] = MMC328x_REG_CTRL;
820 data[1] = MMC328x_REG_DS;
821 if(I2C_TxData(data, 2) < 0)
822 {
823 printk(KERN_ERR "MMC328x_IOC_RESET failed\n");
824 return -EFAULT;
825 }
826 /* wait external capacitor charging done for next SET/RESET */
827 msleep(MMC328x_DELAY_RST);
828 break;
829
830 case MMC31XX_IOC_READ:
831 data[0] = MMC328x_REG_DATA;
832 if(I2C_RxData(data, 6) < 0)
833 {
834 printk(KERN_ERR "MMC328x_IOC_READ failed\n");
835 return -EFAULT;
836 }
837 vec[0] = data[0] << 8 | data[1];
838 vec[1] = data[2] << 8 | data[3];
839 vec[2] = data[4] << 8 | data[5];
840#if DEBUG
841 if(atomic_read(&clientdata->trace) & MMC_DATA_DEBUG)
842 {
843 printk("[X - %04x] [Y - %04x] [Z - %04x]\n", vec[0], vec[1], vec[2]);
844 }
845#endif
846 if(copy_to_user(argp, vec, sizeof(vec)))
847 {
848 printk(KERN_ERR "MMC328x_IOC_READ: copy to user failed\n");
849 return -EFAULT;
850 }
851 break;
852
853 case MMC31XX_IOC_READXYZ:
854 ECS_ReadXYZData(vec, 3);
855 if(copy_to_user(argp, vec, sizeof(vec)))
856 {
857 printk(KERN_ERR "MMC328x_IOC_READXYZ: copy to user failed\n");
858 return -EFAULT;
859 }
860 break;
861
862 case ECOMPASS_IOC_GET_DELAY:
863 delay = mmcd_delay;
864 if(copy_to_user(argp, &delay, sizeof(delay)))
865 {
866 printk(KERN_ERR "copy_to_user failed.");
867 return -EFAULT;
868 }
869 break;
870
871 case ECOMPASS_IOC_SET_YPR:
872 if(argp == NULL)
873 {
874 MMCDBG("invalid argument.");
875 return -EINVAL;
876 }
877 if(copy_from_user(value, argp, sizeof(value)))
878 {
879 MMCDBG("copy_from_user failed.");
880 return -EFAULT;
881 }
882 ECS_SaveData(value);
883 break;
884
885 case ECOMPASS_IOC_GET_OPEN_STATUS:
886 status = ECS_GetOpenStatus();
887 if(copy_to_user(argp, &status, sizeof(status)))
888 {
889 MMCDBG("copy_to_user failed.");
890 return -EFAULT;
891 }
892 break;
893
894 case ECOMPASS_IOC_GET_MFLAG:
895 sensor_status = atomic_read(&m_flag);
896 if(copy_to_user(argp, &sensor_status, sizeof(sensor_status)))
897 {
898 MMCDBG("copy_to_user failed.");
899 return -EFAULT;
900 }
901 break;
902
903 case ECOMPASS_IOC_GET_OFLAG:
904 sensor_status = atomic_read(&o_flag);
905 if(copy_to_user(argp, &sensor_status, sizeof(sensor_status)))
906 {
907 MMCDBG("copy_to_user failed.");
908 return -EFAULT;
909 }
910 break;
911
912
913 case MSENSOR_IOCTL_READ_CHIPINFO:
914 if(argp == NULL)
915 {
916 printk(KERN_ERR "IO parameter pointer is NULL!\r\n");
917 break;
918 }
919
920 mmc328x_ReadChipInfo(buff, MMC328x_BUFSIZE);
921 if(copy_to_user(argp, buff, strlen(buff)+1))
922 {
923 return -EFAULT;
924 }
925 break;
926
927 case MSENSOR_IOCTL_READ_SENSORDATA:
928 if(argp == NULL)
929 {
930 printk(KERN_ERR "IO parameter pointer is NULL!\r\n");
931 break;
932 }
933 ECS_GetRawData(vec);
934 sprintf(buff, "%x %x %x", vec[0], vec[1], vec[2]);
935 if(copy_to_user(argp, buff, strlen(buff)+1))
936 {
937 return -EFAULT;
938 }
939 break;
940
941 case ECOMPASS_IOC_GET_LAYOUT:
942 status = atomic_read(&clientdata->layout);
943 if(copy_to_user(argp, &status, sizeof(status)))
944 {
945 MMCDBG("copy_to_user failed.");
946 return -EFAULT;
947 }
948 break;
949
950 case MSENSOR_IOCTL_SENSOR_ENABLE:
951
952 if(argp == NULL)
953 {
954 printk(KERN_ERR "IO parameter pointer is NULL!\r\n");
955 break;
956 }
957 if(copy_from_user(&enable, argp, sizeof(enable)))
958 {
959 MMCDBG("copy_from_user failed.");
960 return -EFAULT;
961 }
962 else
963 {
964 printk( "MSENSOR_IOCTL_SENSOR_ENABLE enable=%d!\r\n",enable);
965 if(1 == enable)
966 {
967 atomic_set(&o_flag, 1);
968 atomic_set(&open_flag, 1);
969 }
970 else
971 {
972 atomic_set(&o_flag, 0);
973 if(atomic_read(&m_flag) == 0)
974 {
975 atomic_set(&open_flag, 0);
976 }
977 }
978 wake_up(&open_wq);
979
980 }
981
982 break;
983
984 case MSENSOR_IOCTL_READ_FACTORY_SENSORDATA:
985 if(argp == NULL)
986 {
987 printk(KERN_ERR "IO parameter pointer is NULL!\r\n");
988 break;
989 }
990
991 //AKECS_GetRawData(buff, AKM8975_BUFSIZE);
992 osensor_data = (hwm_sensor_data *)buff;
993 mutex_lock(&sensor_data_mutex);
994
995 osensor_data->values[0] = sensor_data[8] * CONVERT_O;
996 osensor_data->values[1] = sensor_data[9] * CONVERT_O;
997 osensor_data->values[2] = sensor_data[10] * CONVERT_O;
998 osensor_data->status = sensor_data[11];
999 osensor_data->value_divide = CONVERT_O_DIV;
1000
1001 mutex_unlock(&sensor_data_mutex);
1002
1003 sprintf(buff, "%x %x %x %x %x", osensor_data->values[0], osensor_data->values[1],
1004 osensor_data->values[2],osensor_data->status,osensor_data->value_divide);
1005 if(copy_to_user(argp, buff, strlen(buff)+1))
1006 {
1007 return -EFAULT;
1008 }
1009
1010 break;
1011
1012 default:
1013 printk(KERN_ERR "%s not supported = 0x%04x", __FUNCTION__, cmd);
1014 return -ENOIOCTLCMD;
1015 break;
1016 }
1017
1018 return 0;
1019}
1020/*----------------------------------------------------------------------------*/
1021static struct file_operations mmc328x_fops = {
1022 .owner = THIS_MODULE,
1023 .open = mmc328x_open,
1024 .release = mmc328x_release,
1025 .ioctl = mmc328x_ioctl,
1026};
1027/*----------------------------------------------------------------------------*/
1028static struct miscdevice mmc328x_device = {
1029 .minor = MISC_DYNAMIC_MINOR,
1030 .name = "msensor",
1031 .fops = &mmc328x_fops,
1032};
1033/*----------------------------------------------------------------------------*/
1034int mmc328x_operate(void* self, uint32_t command, void* buff_in, int size_in,
1035 void* buff_out, int size_out, int* actualout)
1036{
1037 int err = 0;
1038 int value;
1039 hwm_sensor_data* msensor_data;
1040
1041#if DEBUG
1042 struct i2c_client *client = this_client;
1043 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
1044#endif
1045
1046#if DEBUG
1047 if(atomic_read(&data->trace) & MMC_FUN_DEBUG)
1048 {
1049 MMCFUNC("mmc328x_operate");
1050 }
1051#endif
1052 switch (command)
1053 {
1054 case SENSOR_DELAY:
1055 if((buff_in == NULL) || (size_in < sizeof(int)))
1056 {
1057 printk(KERN_ERR "Set delay parameter error!\n");
1058 err = -EINVAL;
1059 }
1060 else
1061 {
1062 value = *(int *)buff_in;
1063 if(value <= 20)
1064 {
1065 mmcd_delay = 20;
1066 }
1067 mmcd_delay = value;
1068 }
1069 break;
1070
1071 case SENSOR_ENABLE:
1072 if((buff_in == NULL) || (size_in < sizeof(int)))
1073 {
1074 printk(KERN_ERR "Enable sensor parameter error!\n");
1075 err = -EINVAL;
1076 }
1077 else
1078 {
1079 value = *(int *)buff_in;
1080
1081 if(value == 1)
1082 {
1083 atomic_set(&m_flag, 1);
1084 atomic_set(&open_flag, 1);
1085 }
1086 else
1087 {
1088 atomic_set(&m_flag, 0);
1089 if(atomic_read(&o_flag) == 0)
1090 {
1091 atomic_set(&open_flag, 0);
1092 }
1093 }
1094 wake_up(&open_wq);
1095
1096 // TODO: turn device into standby or normal mode
1097 }
1098 break;
1099
1100 case SENSOR_GET_DATA:
1101 if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))
1102 {
1103 printk(KERN_ERR "get sensor data parameter error!\n");
1104 err = -EINVAL;
1105 }
1106 else
1107 {
1108 msensor_data = (hwm_sensor_data *)buff_out;
1109 mutex_lock(&sensor_data_mutex);
1110
1111 msensor_data->values[0] = sensor_data[4] * CONVERT_M;
1112 msensor_data->values[1] = sensor_data[5] * CONVERT_M;
1113 msensor_data->values[2] = sensor_data[6] * CONVERT_M;
1114 msensor_data->status = sensor_data[7];
1115 msensor_data->value_divide = CONVERT_M_DIV;
1116
1117 mutex_unlock(&sensor_data_mutex);
1118#if DEBUG
1119 if(atomic_read(&data->trace) & MMC_HWM_DEBUG)
1120 {
1121 MMCDBG("Hwm get m-sensor data: %d, %d, %d. divide %d, status %d!\n",
1122 msensor_data->values[0],msensor_data->values[1],msensor_data->values[2],
1123 msensor_data->value_divide,msensor_data->status);
1124 }
1125#endif
1126 }
1127 break;
1128 default:
1129 printk(KERN_ERR "msensor operate function no this parameter %d!\n", command);
1130 err = -1;
1131 break;
1132 }
1133
1134 return err;
1135}
1136
1137/*----------------------------------------------------------------------------*/
1138int mmc328x_orientation_operate(void* self, uint32_t command, void* buff_in, int size_in,
1139 void* buff_out, int size_out, int* actualout)
1140{
1141 int err = 0;
1142 int value;
1143 hwm_sensor_data* osensor_data;
1144#if DEBUG
1145 struct i2c_client *client = this_client;
1146 struct mmc328x_i2c_data *data = i2c_get_clientdata(client);
1147#endif
1148
1149#if DEBUG
1150 if(atomic_read(&data->trace) & MMC_FUN_DEBUG)
1151 {
1152 MMCFUNC("mmc328x_orientation_operate");
1153 }
1154#endif
1155
1156 switch (command)
1157 {
1158 case SENSOR_DELAY:
1159 if((buff_in == NULL) || (size_in < sizeof(int)))
1160 {
1161 printk(KERN_ERR "Set delay parameter error!\n");
1162 err = -EINVAL;
1163 }
1164 else
1165 {
1166 value = *(int *)buff_in;
1167 if(value <= 20)
1168 {
1169 mmcd_delay = 20;
1170 }
1171 mmcd_delay = value;
1172 }
1173 break;
1174
1175 case SENSOR_ENABLE:
1176 if((buff_in == NULL) || (size_in < sizeof(int)))
1177 {
1178 printk(KERN_ERR "Enable sensor parameter error!\n");
1179 err = -EINVAL;
1180 }
1181 else
1182 {
1183
1184 value = *(int *)buff_in;
1185
1186 if(value == 1)
1187 {
1188 atomic_set(&o_flag, 1);
1189 atomic_set(&open_flag, 1);
1190 }
1191 else
1192 {
1193 atomic_set(&o_flag, 0);
1194 if(atomic_read(&m_flag) == 0)
1195 {
1196 atomic_set(&open_flag, 0);
1197 }
1198 }
1199 wake_up(&open_wq);
1200 }
1201 break;
1202
1203 case SENSOR_GET_DATA:
1204 if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))
1205 {
1206 printk(KERN_ERR "get sensor data parameter error!\n");
1207 err = -EINVAL;
1208 }
1209 else
1210 {
1211 osensor_data = (hwm_sensor_data *)buff_out;
1212 mutex_lock(&sensor_data_mutex);
1213
1214 osensor_data->values[0] = sensor_data[8] * CONVERT_O;
1215 osensor_data->values[1] = sensor_data[9] * CONVERT_O;
1216 osensor_data->values[2] = sensor_data[10] * CONVERT_O;
1217 osensor_data->status = sensor_data[11];
1218 osensor_data->value_divide = CONVERT_O_DIV;
1219
1220 mutex_unlock(&sensor_data_mutex);
1221#if DEBUG
1222 if(atomic_read(&data->trace) & MMC_HWM_DEBUG)
1223 {
1224 MMCDBG("Hwm get o-sensor data: %d, %d, %d. divide %d, status %d!\n",
1225 osensor_data->values[0],osensor_data->values[1],osensor_data->values[2],
1226 osensor_data->value_divide,osensor_data->status);
1227 }
1228#endif
1229 }
1230 break;
1231 default:
1232 printk(KERN_ERR "gsensor operate function no this parameter %d!\n", command);
1233 err = -1;
1234 break;
1235 }
1236
1237 return err;
1238}
1239
1240/*----------------------------------------------------------------------------*/
1241#ifndef CONFIG_HAS_EARLYSUSPEND
1242/*----------------------------------------------------------------------------*/
1243static int mmc328x_suspend(struct i2c_client *client, pm_message_t msg)
1244{
1245 struct mmc328x_i2c_data *obj = i2c_get_clientdata(client)
1246
1247
1248 if(msg.event == PM_EVENT_SUSPEND)
1249 {
1250 mmc328x_power(obj->hw, 0);
1251 }
1252 return 0;
1253}
1254/*----------------------------------------------------------------------------*/
1255static int mmc328x_resume(struct i2c_client *client)
1256{
1257 struct mmc328x_i2c_data *obj = i2c_get_clientdata(client)
1258
1259
1260 mmc328x_power(obj->hw, 1);
1261
1262
1263 return 0;
1264}
1265/*----------------------------------------------------------------------------*/
1266#else /*CONFIG_HAS_EARLY_SUSPEND is defined*/
1267/*----------------------------------------------------------------------------*/
1268static void mmc328x_early_suspend(struct early_suspend *h)
1269{
1270 struct mmc328x_i2c_data *obj = container_of(h, struct mmc328x_i2c_data, early_drv);
1271 printk("mmc328x early_suspend!!\n");
1272 //mmc328x_power(obj->hw, 0);
1273
1274 if(NULL == obj)
1275 {
1276 printk(KERN_ERR "null pointer!!\n");
1277 return;
1278 }
1279 if(mmc328x_SetPowerMode(obj->client, false))
1280 {
1281 printk("mmc328x: write power control fail!!\n");
1282 return;
1283 }
1284
1285}
1286/*----------------------------------------------------------------------------*/
1287static void mmc328x_late_resume(struct early_suspend *h)
1288{
1289 struct mmc328x_i2c_data *obj = container_of(h, struct mmc328x_i2c_data, early_drv);
1290
1291
1292 if(NULL == obj)
1293 {
1294 printk(KERN_ERR "null pointer!!\n");
1295 return;
1296 }
1297 //mmc328x_power(obj->hw, 1);
1298
1299}
1300/*----------------------------------------------------------------------------*/
1301#endif /*CONFIG_HAS_EARLYSUSPEND*/
1302/*----------------------------------------------------------------------------*/
1303static int mmc328x_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
1304{
1305 strcpy(info->type, MMC328x_DEV_NAME);
1306 return 0;
1307}
1308
1309/*----------------------------------------------------------------------------*/
1310static int mmc328x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
1311{
1312 struct i2c_client *new_client;
1313 struct mmc328x_i2c_data *data;
1314 char tmp[2];
1315 int err = 0;
1316 struct hwmsen_object sobj_m, sobj_o;
1317
1318 MMCDBG("%s: ++++\n", __func__);
1319 if(!(data = kmalloc(sizeof(struct mmc328x_i2c_data), GFP_KERNEL)))
1320 {
1321 err = -ENOMEM;
1322 goto exit;
1323 }
1324 memset(data, 0, sizeof(struct mmc328x_i2c_data));
1325
1326 data->hw = mmc328x_get_cust_mag_hw();
1327
1328 atomic_set(&data->layout, data->hw->direction);
1329 atomic_set(&data->trace, 0);
1330
1331
1332 mutex_init(&sensor_data_mutex);
1333 mutex_init(&read_i2c_xyz);
1334
1335 init_waitqueue_head(&data_ready_wq);
1336 init_waitqueue_head(&open_wq);
1337
1338 data->client = client;
1339 new_client = data->client;
1340 i2c_set_clientdata(new_client, data);
1341
1342 this_client = new_client;
1343 //this_client->timing=400;
1344
1345
1346 /* send ST cmd to mag sensor first of all */
1347 tmp[0] = MMC328x_REG_CTRL;
1348 tmp[1] = MMC328x_CTRL_RM;
1349 if(I2C_TxData(tmp, 2) < 0)
1350 {
1351 printk(KERN_ERR "mmc328x_device set ST cmd failed\n");
1352 goto exit_kfree;
1353 }
1354
1355
1356 /* Register sysfs attribute */
1357 if(err = mmc328x_create_attr(&(mmc328x_init_info.platform_diver_addr->driver)))
1358 {
1359 printk(KERN_ERR "create attribute err = %d\n", err);
1360 goto exit_sysfs_create_group_failed;
1361 }
1362
1363
1364 if(err = misc_register(&mmc328x_device))
1365 {
1366 printk(KERN_ERR "mmc328x_device register failed\n");
1367 goto exit_misc_device_register_failed; }
1368
1369 sobj_m.self = data;
1370 sobj_m.polling = 1;
1371 sobj_m.sensor_operate = mmc328x_operate;
1372 if(err = hwmsen_attach(ID_MAGNETIC, &sobj_m))
1373 {
1374 printk(KERN_ERR "attach fail = %d\n", err);
1375 goto exit_kfree;
1376 }
1377
1378 sobj_o.self = data;
1379 sobj_o.polling = 1;
1380 sobj_o.sensor_operate = mmc328x_orientation_operate;
1381 if(err = hwmsen_attach(ID_ORIENTATION, &sobj_o))
1382 {
1383 printk(KERN_ERR "attach fail = %d\n", err);
1384 goto exit_kfree;
1385 }
1386
1387#if CONFIG_HAS_EARLYSUSPEND
1388 data->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 2,
1389 data->early_drv.suspend = mmc328x_early_suspend,
1390 data->early_drv.resume = mmc328x_late_resume,
1391 register_early_suspend(&data->early_drv);
1392#endif
1393
1394 MMCDBG("%s: OK\n", __func__);
1395 mmc328x_init_flag = 0;
1396
1397 return 0;
1398
1399 exit_sysfs_create_group_failed:
1400 exit_misc_device_register_failed:
1401 exit_kfree:
1402 kfree(data);
1403 exit:
1404 printk(KERN_ERR "%s: err = %d\n", __func__, err);
1405 mmc328x_init_flag = -1;
1406 return err;
1407}
1408/*----------------------------------------------------------------------------*/
1409static int mmc328x_i2c_remove(struct i2c_client *client)
1410{
1411 int err;
1412
1413 if(err = mmc328x_delete_attr(&(mmc328x_init_info.platform_diver_addr->driver)))
1414 {
1415 printk(KERN_ERR "mmc328x_delete_attr fail: %d\n", err);
1416 }
1417
1418 this_client = NULL;
1419 i2c_unregister_device(client);
1420 kfree(i2c_get_clientdata(client));
1421 misc_deregister(&mmc328x_device);
1422 return 0;
1423}
1424/*----------------------------------------------------------------------------*/
1425static int mmc328x_local_init(void)
1426{
1427 struct mag_hw *hw = mmc328x_get_cust_mag_hw();
1428 MMCFUNC("mmc328x_local_init");
1429
1430 mmc328x_power(hw, 1);
1431 atomic_set(&dev_open_count, 0);
1432 mmc328x_force[0] = hw->i2c_num;
1433
1434 if(i2c_add_driver(&mmc328x_i2c_driver))
1435 {
1436 printk(KERN_ERR "add driver error\n");
1437 return -1;
1438 }
1439 if(-1 == mmc328x_init_flag)
1440 {
1441 return -1;
1442 }
1443 return 0;
1444}
1445
1446/*----------------------------------------------------------------------------*/
1447static int mmc328x_remove()
1448{
1449 struct mag_hw *hw = mmc328x_get_cust_mag_hw();
1450 mmc328x_power(hw, 0);
1451 atomic_set(&dev_open_count, 0);
1452 i2c_del_driver(&mmc328x_i2c_driver);
1453 return 0;
1454}
1455/*----------------------------------------------------------------------------*/
1456
1457static int __init mmc328x_init(void)
1458{
1459 MMCFUNC("mmc328x_init");
1460 hwmsen_msensor_add(&mmc328x_init_info);
1461 return 0;
1462}
1463/*----------------------------------------------------------------------------*/
1464static void __exit mmc328x_exit(void)
1465{
1466 MMCFUNC("mmc328x_exit");
1467}
1468/*----------------------------------------------------------------------------*/
1469module_init(mmc328x_init);
1470module_exit(mmc328x_exit);
1471
1472MODULE_AUTHOR("weiqi fu");
1473MODULE_DESCRIPTION("mmc328x compass driver");
1474MODULE_LICENSE("GPL");
1475MODULE_VERSION(DRIVER_VERSION);
1476