import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / ttab / eeprom / dummy_eeprom.c
1 /*
2 * Driver for EEPROM
3 *
4 *
5 */
6
7 #include <linux/i2c.h>
8 #include <linux/platform_device.h>
9 #include <linux/delay.h>
10 #include <linux/cdev.h>
11 #include <linux/uaccess.h>
12 #include <linux/slab.h>
13 #include <linux/fs.h>
14 #include "kd_camera_hw.h"
15 #include "eeprom.h"
16 #include "eeprom_define.h"
17
18 #include "dummy_eeprom.h"
19 #include <asm/system.h> // for SMP
20
21 //#define EEPROMGETDLT_DEBUG //test
22 //#define EEPROM_DEBUG //test
23 #ifdef EEPROM_DEBUG
24 #define EEPROMDB printk
25 #else
26 #define EEPROMDB(x,...)
27 #endif
28
29
30 static DEFINE_SPINLOCK(g_EEPROMLock); // for SMP
31
32 #define EEPROM_I2C_BUSNUM 1
33 static struct i2c_board_info __initdata kd_eeprom_dev={ I2C_BOARD_INFO("dummy_eeprom", 0xA0>>1)};
34
35 /*******************************************************************************
36 *
37 ********************************************************************************/
38 #define EEPROM_ICS_REVISION 1 //seanlin111208
39 /*******************************************************************************
40 *
41 ********************************************************************************/
42 #define EEPROM_DRVNAME "dummy_eeprom"
43 #define EEPROM_I2C_GROUP_ID 0
44 /*******************************************************************************
45 *
46 ********************************************************************************/
47 /* fix warning MSG
48 static unsigned short g_pu2Normal_i2c[] = {S24CS64A_DEVICE_ID , I2C_CLIENT_END};
49 static unsigned short g_u2Ignore = I2C_CLIENT_END;
50 static struct i2c_client_address_data g_stEEPROM_Addr_data = {
51 .normal_i2c = g_pu2Normal_i2c,
52 .probe = &g_u2Ignore,
53 .ignore = &g_u2Ignore
54 }; */
55 static struct i2c_client * g_pstI2Cclient = NULL;
56
57 //81 is used for V4L driver
58 static dev_t g_EEPROMdevno = MKDEV(EEPROM_DEV_MAJOR_NUMBER,0);
59 static struct cdev * g_pEEPROM_CharDrv = NULL;
60 //static spinlock_t g_EEPROMLock;
61 static struct class *EEPROM_class = NULL;
62 static atomic_t g_EEPROMatomic;
63 /*******************************************************************************
64 *
65 ********************************************************************************/
66 // maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes
67 int iWriteEEPROM(u16 a_u2Addr , u32 a_u4Bytes, u8 * puDataInBytes)
68 {
69 int i4RetValue = 0;
70 u32 u4Index = 0;
71 char puSendCmd[8] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF) ,
72 0, 0, 0, 0, 0, 0};
73 if(a_u4Bytes + 2 > 8)
74 {
75 EEPROMDB("[EEPROM] exceed I2c-mt65xx.c 8 bytes limitation (include address 2 Byte)\n");
76 return -1;
77 }
78
79 for(u4Index = 0 ; u4Index < a_u4Bytes ; u4Index += 1 )
80 {
81 puSendCmd[(u4Index + 2)] = puDataInBytes[u4Index];
82 }
83
84 i4RetValue = i2c_master_send(g_pstI2Cclient, puSendCmd, (a_u4Bytes + 2));
85 if (i4RetValue != (a_u4Bytes + 2))
86 {
87 EEPROMDB("[EEPROM] I2C write failed!! \n");
88 return -1;
89 }
90 mdelay(10); //for tWR singnal --> write data form buffer to memory.
91
92 //EEPROMDB("[EEPROM] iWriteEEPROM done!! \n");
93 return 0;
94 }
95
96
97 // maximun read length is limited at "I2C_FIFO_SIZE" in I2c-mt65xx.c which is 8 bytes
98 int iReadEEPROM(u16 a_u2Addr, u32 ui4_length, u8 * a_puBuff)
99 {
100 int i4RetValue = 0;
101 char puReadCmd[2] = {(char)(a_u2Addr >> 8) , (char)(a_u2Addr & 0xFF)};
102
103 //EEPROMDB("[EEPROM] iReadEEPROM!! \n");
104
105 if(ui4_length > 8)
106 {
107 EEPROMDB("[EEPROM] exceed I2c-mt65xx.c 8 bytes limitation\n");
108 return -1;
109 }
110 spin_lock(&g_EEPROMLock); //for SMP
111 g_pstI2Cclient->addr = g_pstI2Cclient->addr & (I2C_MASK_FLAG | I2C_WR_FLAG);
112 spin_unlock(&g_EEPROMLock); // for SMP
113
114 //EEPROMDB("[EERPOM] i2c_master_send \n");
115 i4RetValue = i2c_master_send(g_pstI2Cclient, puReadCmd, 2);
116 if (i4RetValue != 2)
117 {
118 EEPROMDB("[EEPROM] I2C send read address failed!! \n");
119 return -1;
120 }
121
122 //EEPROMDB("[EERPOM] i2c_master_recv \n");
123 i4RetValue = i2c_master_recv(g_pstI2Cclient, (char *)a_puBuff, ui4_length);
124 if (i4RetValue != ui4_length)
125 {
126 EEPROMDB("[EEPROM] I2C read data failed!! \n");
127 return -1;
128 }
129 spin_lock(&g_EEPROMLock); //for SMP
130 g_pstI2Cclient->addr = g_pstI2Cclient->addr & I2C_MASK_FLAG;
131 spin_unlock(&g_EEPROMLock); // for SMP
132
133 //EEPROMDB("[EEPROM] iReadEEPROM done!! \n");
134 return 0;
135 }
136
137
138 static int iWriteData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char * pinputdata)
139 {
140 int i4RetValue = 0;
141 int i4ResidueDataLength;
142 u32 u4IncOffset = 0;
143 u32 u4CurrentOffset;
144 u8 * pBuff;
145
146 EEPROMDB("[EEPROM] iWriteData\n" );
147
148
149 if (ui4_offset + ui4_length >= 0x2000)
150 {
151 EEPROMDB("[EEPROM] Write Error!! S-24CS64A not supprt address >= 0x2000!! \n" );
152 return -1;
153 }
154
155 i4ResidueDataLength = (int)ui4_length;
156 u4CurrentOffset = ui4_offset;
157 pBuff = pinputdata;
158 EEPROMDB("[EEPROM] iWriteData u4CurrentOffset is %d \n",u4CurrentOffset);
159 do
160 {
161 if(i4ResidueDataLength >= 6)
162 {
163 i4RetValue = iWriteEEPROM((u16)u4CurrentOffset, 6, pBuff);
164 if (i4RetValue != 0)
165 {
166 EEPROMDB("[EEPROM] I2C iWriteData failed!! \n");
167 return -1;
168 }
169 u4IncOffset += 6;
170 i4ResidueDataLength -= 6;
171 u4CurrentOffset = ui4_offset + u4IncOffset;
172 pBuff = pinputdata + u4IncOffset;
173 }
174 else
175 {
176 i4RetValue = iWriteEEPROM((u16)u4CurrentOffset, i4ResidueDataLength, pBuff);
177 if (i4RetValue != 0)
178 {
179 EEPROMDB("[EEPROM] I2C iWriteData failed!! \n");
180 return -1;
181 }
182 u4IncOffset += 6;
183 i4ResidueDataLength -= 6;
184 u4CurrentOffset = ui4_offset + u4IncOffset;
185 pBuff = pinputdata + u4IncOffset;
186 //break;
187 }
188 }while (i4ResidueDataLength > 0);
189 EEPROMDB("[EEPROM] iWriteData done\n" );
190
191 return 0;
192 }
193
194 //int iReadData(stEEPROM_INFO_STRUCT * st_pOutputBuffer)
195 static int iReadData(unsigned int ui4_offset, unsigned int ui4_length, unsigned char * pinputdata)
196 {
197 int i4RetValue = 0;
198 int i4ResidueDataLength;
199 u32 u4IncOffset = 0;
200 u32 u4CurrentOffset;
201 u8 * pBuff;
202 EEPROMDB("[EEPROM] iReadData \n" );
203
204 if (ui4_offset + ui4_length >= 0x2000)
205 {
206 EEPROMDB("[EEPROM] Read Error!! S-24CS64A not supprt address >= 0x2000!! \n" );
207 return -1;
208 }
209
210 i4ResidueDataLength = (int)ui4_length;
211 u4CurrentOffset = ui4_offset;
212 pBuff = pinputdata;
213 do
214 {
215 if(i4ResidueDataLength >= 8)
216 {
217 i4RetValue = iReadEEPROM((u16)u4CurrentOffset, 8, pBuff);
218 if (i4RetValue != 0)
219 {
220 EEPROMDB("[EEPROM] I2C iReadData failed!! \n");
221 return -1;
222 }
223 u4IncOffset += 8;
224 i4ResidueDataLength -= 8;
225 u4CurrentOffset = ui4_offset + u4IncOffset;
226 pBuff = pinputdata + u4IncOffset;
227 }
228 else
229 {
230 i4RetValue = iReadEEPROM((u16)u4CurrentOffset, i4ResidueDataLength, pBuff);
231 if (i4RetValue != 0)
232 {
233 EEPROMDB("[EEPROM] I2C iReadData failed!! \n");
234 return -1;
235 }
236 u4IncOffset += 8;
237 i4ResidueDataLength -= 8;
238 u4CurrentOffset = ui4_offset + u4IncOffset;
239 pBuff = pinputdata + u4IncOffset;
240 //break;
241 }
242 }while (i4ResidueDataLength > 0);
243 //fix warning MSG EEPROMDB("[EEPROM] iReadData finial address is %d length is %d buffer address is 0x%x\n",u4CurrentOffset, i4ResidueDataLength, pBuff);
244 EEPROMDB("[EEPROM] iReadData done\n" );
245 return 0;
246 }
247
248
249 /*******************************************************************************
250 *
251 ********************************************************************************/
252 #define NEW_UNLOCK_IOCTL
253 #ifndef NEW_UNLOCK_IOCTL
254 static int EEPROM_Ioctl(struct inode * a_pstInode,
255 struct file * a_pstFile,
256 unsigned int a_u4Command,
257 unsigned long a_u4Param)
258 #else
259 static long EEPROM_Ioctl(
260 struct file *file,
261 unsigned int a_u4Command,
262 unsigned long a_u4Param
263 )
264 #endif
265 {
266 int i4RetValue = 0;
267 u8 * pBuff = NULL;
268 u8 * pWorkingBuff = NULL;
269 stEEPROM_INFO_STRUCT *ptempbuf;
270
271 #ifdef EEPROMGETDLT_DEBUG
272 struct timeval ktv1, ktv2;
273 unsigned long TimeIntervalUS;
274 #endif
275
276 if(_IOC_NONE == _IOC_DIR(a_u4Command))
277 {
278 }
279 else
280 {
281 pBuff = (u8 *)kmalloc(sizeof(stEEPROM_INFO_STRUCT),GFP_KERNEL);
282
283 if(NULL == pBuff)
284 {
285 EEPROMDB("[EEPROM] ioctl allocate mem failed\n");
286 return -ENOMEM;
287 }
288
289 if(_IOC_WRITE & _IOC_DIR(a_u4Command))
290 {
291 if(copy_from_user((u8 *) pBuff , (u8 *) a_u4Param, sizeof(stEEPROM_INFO_STRUCT)))
292 { //get input structure address
293 kfree(pBuff);
294 EEPROMDB("[EEPROM] ioctl copy from user failed\n");
295 return -EFAULT;
296 }
297 }
298 }
299
300 ptempbuf = (stEEPROM_INFO_STRUCT *)pBuff;
301 pWorkingBuff = (u8*)kmalloc(ptempbuf->u4Length,GFP_KERNEL);
302 if(NULL == pWorkingBuff)
303 {
304 kfree(pBuff);
305 EEPROMDB("[EEPROM] ioctl allocate mem failed\n");
306 return -ENOMEM;
307 }
308 //fix warning MSG EEPROMDB("[EEPROM] init Working buffer address 0x%x command is 0x%08x\n", pWorkingBuff, a_u4Command);
309
310
311 if(copy_from_user((u8*)pWorkingBuff , (u8*)ptempbuf->pu1Params, ptempbuf->u4Length))
312 {
313 kfree(pBuff);
314 kfree(pWorkingBuff);
315 EEPROMDB("[EEPROM] ioctl copy from user failed\n");
316 return -EFAULT;
317 }
318
319 switch(a_u4Command)
320 {
321 case EEPROMIOC_S_WRITE:
322 EEPROMDB("[EEPROM] Write CMD \n");
323 #ifdef EEPROMGETDLT_DEBUG
324 do_gettimeofday(&ktv1);
325 #endif
326 i4RetValue = iWriteData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff);
327 #ifdef EEPROMGETDLT_DEBUG
328 do_gettimeofday(&ktv2);
329 if(ktv2.tv_sec > ktv1.tv_sec)
330 {
331 TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec;
332 }
333 else
334 {
335 TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec;
336 }
337 printk("Write data %d bytes take %lu us\n",ptempbuf->u4Length, TimeIntervalUS);
338 #endif
339 break;
340 case EEPROMIOC_G_READ:
341 EEPROMDB("[EEPROM] Read CMD \n");
342 #ifdef EEPROMGETDLT_DEBUG
343 do_gettimeofday(&ktv1);
344 #endif
345 EEPROMDB("[EEPROM] offset %d \n", ptempbuf->u4Offset);
346 EEPROMDB("[EEPROM] length %d \n", ptempbuf->u4Length);
347 //fix warning MSG EEPROMDB("[EEPROM] Before read Working buffer address 0x%x \n", pWorkingBuff);
348
349 i4RetValue = iReadData((u16)ptempbuf->u4Offset, ptempbuf->u4Length, pWorkingBuff);
350 //fix warning MSG EEPROMDB("[EEPROM] After read Working buffer address 0x%x \n", pWorkingBuff);
351
352
353 #ifdef EEPROMGETDLT_DEBUG
354 do_gettimeofday(&ktv2);
355 if(ktv2.tv_sec > ktv1.tv_sec)
356 {
357 TimeIntervalUS = ktv1.tv_usec + 1000000 - ktv2.tv_usec;
358 }
359 else
360 {
361 TimeIntervalUS = ktv2.tv_usec - ktv1.tv_usec;
362 }
363 printk("Read data %d bytes take %lu us\n",ptempbuf->u4Length, TimeIntervalUS);
364 #endif
365
366 break;
367 default :
368 EEPROMDB("[EEPROM] No CMD \n");
369 i4RetValue = -EPERM;
370 break;
371 }
372
373 if(_IOC_READ & _IOC_DIR(a_u4Command))
374 {
375 //copy data to user space buffer, keep other input paremeter unchange.
376 EEPROMDB("[EEPROM] to user length %d \n", ptempbuf->u4Length);
377 //fix warning MSG EEPROMDB("[EEPROM] to user Working buffer address 0x%x \n", pWorkingBuff);
378 if(copy_to_user((u8 __user *) ptempbuf->pu1Params , (u8 *)pWorkingBuff , ptempbuf->u4Length))
379 {
380 kfree(pBuff);
381 kfree(pWorkingBuff);
382 EEPROMDB("[EEPROM] ioctl copy to user failed\n");
383 return -EFAULT;
384 }
385 }
386
387 kfree(pBuff);
388 kfree(pWorkingBuff);
389 return i4RetValue;
390 }
391
392
393 static u32 g_u4Opened = 0;
394 //#define
395 //Main jobs:
396 // 1.check for device-specified errors, device not ready.
397 // 2.Initialize the device if it is opened for the first time.
398 static int EEPROM_Open(struct inode * a_pstInode, struct file * a_pstFile)
399 {
400 EEPROMDB("[S24EEPROM] EEPROM_Open\n");
401 spin_lock(&g_EEPROMLock);
402 if(g_u4Opened)
403 {
404 spin_unlock(&g_EEPROMLock);
405 return -EBUSY;
406 }
407 else
408 {
409 g_u4Opened = 1;
410 atomic_set(&g_EEPROMatomic,0);
411 }
412 spin_unlock(&g_EEPROMLock);
413
414 //if(TRUE != hwPowerOn(MT65XX_POWER_LDO_VCAMA, VOL_2800, "S24CS64A"))
415 //{
416 // EEPROMDB("[EEPROM] Fail to enable analog gain\n");
417 // return -EIO;
418 //}
419
420 return 0;
421 }
422
423 //Main jobs:
424 // 1.Deallocate anything that "open" allocated in private_data.
425 // 2.Shut down the device on last close.
426 // 3.Only called once on last time.
427 // Q1 : Try release multiple times.
428 static int EEPROM_Release(struct inode * a_pstInode, struct file * a_pstFile)
429 {
430 spin_lock(&g_EEPROMLock);
431
432 g_u4Opened = 0;
433
434 atomic_set(&g_EEPROMatomic,0);
435
436 spin_unlock(&g_EEPROMLock);
437
438 return 0;
439 }
440
441 static const struct file_operations g_stEEPROM_fops =
442 {
443 .owner = THIS_MODULE,
444 .open = EEPROM_Open,
445 .release = EEPROM_Release,
446 //.ioctl = EEPROM_Ioctl
447 .unlocked_ioctl = EEPROM_Ioctl
448 };
449
450 #define EEPROM_DYNAMIC_ALLOCATE_DEVNO 1
451 inline static int RegisterEEPROMCharDrv(void)
452 {
453 struct device* EEPROM_device = NULL;
454
455 #if EEPROM_DYNAMIC_ALLOCATE_DEVNO
456 if( alloc_chrdev_region(&g_EEPROMdevno, 0, 1,EEPROM_DRVNAME) )
457 {
458 EEPROMDB("[EEPROM] Allocate device no failed\n");
459
460 return -EAGAIN;
461 }
462 #else
463 if( register_chrdev_region( g_EEPROMdevno , 1 , EEPROM_DRVNAME) )
464 {
465 EEPROMDB("[EEPROM] Register device no failed\n");
466
467 return -EAGAIN;
468 }
469 #endif
470
471 //Allocate driver
472 g_pEEPROM_CharDrv = cdev_alloc();
473
474 if(NULL == g_pEEPROM_CharDrv)
475 {
476 unregister_chrdev_region(g_EEPROMdevno, 1);
477
478 EEPROMDB("[EEPROM] Allocate mem for kobject failed\n");
479
480 return -ENOMEM;
481 }
482
483 //Attatch file operation.
484 cdev_init(g_pEEPROM_CharDrv, &g_stEEPROM_fops);
485
486 g_pEEPROM_CharDrv->owner = THIS_MODULE;
487
488 //Add to system
489 if(cdev_add(g_pEEPROM_CharDrv, g_EEPROMdevno, 1))
490 {
491 EEPROMDB("[EEPROM] Attatch file operation failed\n");
492
493 unregister_chrdev_region(g_EEPROMdevno, 1);
494
495 return -EAGAIN;
496 }
497
498 EEPROM_class = class_create(THIS_MODULE, "EEPROMdrv");
499 if (IS_ERR(EEPROM_class)) {
500 int ret = PTR_ERR(EEPROM_class);
501 EEPROMDB("Unable to create class, err = %d\n", ret);
502 return ret;
503 }
504 EEPROM_device = device_create(EEPROM_class, NULL, g_EEPROMdevno, NULL, EEPROM_DRVNAME);
505
506 return 0;
507 }
508
509 inline static void UnregisterEEPROMCharDrv(void)
510 {
511 //Release char driver
512 cdev_del(g_pEEPROM_CharDrv);
513
514 unregister_chrdev_region(g_EEPROMdevno, 1);
515
516 device_destroy(EEPROM_class, g_EEPROMdevno);
517 class_destroy(EEPROM_class);
518 }
519
520
521 //////////////////////////////////////////////////////////////////////
522 #ifndef EEPROM_ICS_REVISION
523 static int EEPROM_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info);
524 #elif 0
525 static int EEPROM_i2c_detect(struct i2c_client *client, struct i2c_board_info *info);
526 #else
527 #endif
528 static int EEPROM_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
529 static int EEPROM_i2c_remove(struct i2c_client *);
530
531 static const struct i2c_device_id EEPROM_i2c_id[] = {{EEPROM_DRVNAME,0},{}};
532 #if 0 //test110314 Please use the same I2C Group ID as Sensor
533 static unsigned short force[] = {EEPROM_I2C_GROUP_ID, S24CS64A_DEVICE_ID, I2C_CLIENT_END, I2C_CLIENT_END};
534 #else
535 //static unsigned short force[] = {EEPROM_I2C_GROUP_ID, S24CS64A_DEVICE_ID, I2C_CLIENT_END, I2C_CLIENT_END};
536 #endif
537 //static const unsigned short * const forces[] = { force, NULL };
538 //static struct i2c_client_address_data addr_data = { .forces = forces,};
539
540
541 static struct i2c_driver EEPROM_i2c_driver = {
542 .probe = EEPROM_i2c_probe,
543 .remove = EEPROM_i2c_remove,
544 // .detect = EEPROM_i2c_detect,
545 .driver.name = EEPROM_DRVNAME,
546 .id_table = EEPROM_i2c_id,
547 };
548
549 #ifndef EEPROM_ICS_REVISION
550 static int EEPROM_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) {
551 strcpy(info->type, EEPROM_DRVNAME);
552 return 0;
553 }
554 #endif
555 static int EEPROM_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) {
556 int i4RetValue = 0;
557 EEPROMDB("[EEPROM] Attach I2C \n");
558 // spin_lock_init(&g_EEPROMLock);
559
560 //get sensor i2c client
561 spin_lock(&g_EEPROMLock); //for SMP
562 g_pstI2Cclient = client;
563 g_pstI2Cclient->addr = S24CS64A_DEVICE_ID>>1;
564 spin_unlock(&g_EEPROMLock); // for SMP
565
566 EEPROMDB("[EEPROM] g_pstI2Cclient->addr = 0x%8x \n",g_pstI2Cclient->addr);
567 //Register char driver
568 i4RetValue = RegisterEEPROMCharDrv();
569
570 if(i4RetValue){
571 EEPROMDB("[EEPROM] register char device failed!\n");
572 return i4RetValue;
573 }
574
575
576 EEPROMDB("[EEPROM] Attached!! \n");
577 return 0;
578 }
579
580 static int EEPROM_i2c_remove(struct i2c_client *client)
581 {
582 return 0;
583 }
584
585 static int EEPROM_probe(struct platform_device *pdev)
586 {
587 return i2c_add_driver(&EEPROM_i2c_driver);
588 }
589
590 static int EEPROM_remove(struct platform_device *pdev)
591 {
592 i2c_del_driver(&EEPROM_i2c_driver);
593 return 0;
594 }
595
596 // platform structure
597 static struct platform_driver g_stEEPROM_Driver = {
598 .probe = EEPROM_probe,
599 .remove = EEPROM_remove,
600 .driver = {
601 .name = EEPROM_DRVNAME,
602 .owner = THIS_MODULE,
603 }
604 };
605
606
607 static struct platform_device g_stEEPROM_Device = {
608 .name = EEPROM_DRVNAME,
609 .id = 0,
610 .dev = {
611 }
612 };
613
614 static int __init EEPROM_i2C_init(void)
615 {
616 i2c_register_board_info(EEPROM_I2C_BUSNUM, &kd_eeprom_dev, 1);
617 if(platform_driver_register(&g_stEEPROM_Driver)){
618 EEPROMDB("failed to register EEPROM driver\n");
619 return -ENODEV;
620 }
621
622 if (platform_device_register(&g_stEEPROM_Device))
623 {
624 EEPROMDB("failed to register EEPROM driver\n");
625 return -ENODEV;
626 }
627
628 return 0;
629 }
630
631 static void __exit EEPROM_i2C_exit(void)
632 {
633 platform_driver_unregister(&g_stEEPROM_Driver);
634 }
635
636 module_init(EEPROM_i2C_init);
637 module_exit(EEPROM_i2C_exit);
638
639 MODULE_DESCRIPTION("EEPROM driver");
640 MODULE_AUTHOR("Sean Lin <Sean.Lin@Mediatek.com>");
641 MODULE_LICENSE("GPL");
642
643