Merge branch 'develop' of 10.10.10.29:/home/rockchip/kernel into develop
[firefly-linux-kernel-4.4.55.git] / drivers / misc / mtk23d.c
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/i2c.h>
4 #include <linux/irq.h>
5 #include <linux/gpio.h>
6 #include <linux/input.h>
7 #include <linux/platform_device.h>
8 #include <linux/fs.h>
9 #include <linux/uaccess.h>
10 #include <linux/miscdevice.h>
11 #include <linux/circ_buf.h>
12 #include <linux/interrupt.h>
13 #include <linux/miscdevice.h>
14 #include <mach/iomux.h>
15 #include <mach/gpio.h>
16 //#include <mach/spi_fpga.h>
17 #include <linux/delay.h>
18 #include <linux/poll.h>
19 #include <linux/wait.h>
20 //#include <linux/android_power.h>
21 //#include <asm/arch/gpio_extend.h>
22 #include <linux/workqueue.h>
23 #include <linux/mtk23d.h>
24 #include <linux/wakelock.h>
25 #include "../mtd/rknand/api_flash.h"
26
27 MODULE_LICENSE("GPL");
28
29 #define DEBUG
30 #ifdef DEBUG
31 #define MODEMDBG(x...) printk(x)
32 #else
33 #define MODEMDBG(fmt,argss...)
34 #endif
35 #define MTK23D_POWEROFF 0X00
36 #define MTK23D_RESET 0x01
37 #define MTK23D_POWERON  0x02
38 #define MTK23D_POWER_HIGH 0x03
39 #define MTK23D_IMEI_READ  0x04
40 //#define BP_POW_EN     TCA6424_P02
41 //#define BP_STATUS    RK2818_PIN_PH7    //input  high bp sleep
42 //#define AP_STATUS    RK2818_PIN_PA4    //output high ap sleep
43
44 //#define BP_RESET      TCA6424_P11     //Ryan
45
46 //#define AP_BP_WAKEUP  RK2818_PIN_PF5   //output AP wake up BP used rising edge
47 //#define BP_AP_WAKEUP  RK2818_PIN_PE0  //input BP wake up AP
48
49 static bool bpstatus_irq_enable = false;
50 static bool wakelock_inited;
51 static struct wake_lock mtk23d_wakelock;
52
53 #define SLEEP 1
54 #define READY 0
55
56 //struct modem_dev *mt6223d_data = NULL;
57 struct rk2818_23d_data *gpdata = NULL;
58
59 static int rk29_uart_to_gpio(int uart_id)
60 {
61         if(uart_id == 3) {
62                 rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_GPIO2B3);                       
63                 rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_GPIO2B2);                
64
65                 gpio_request(RK29_PIN2_PB3, NULL);
66                 gpio_request(RK29_PIN2_PB2, NULL);
67
68                 gpio_direction_output(RK29_PIN2_PB3, GPIO_LOW);
69                 gpio_direction_output(RK29_PIN2_PB2, GPIO_LOW);
70         }
71         else if(uart_id == 2) {
72                 rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_GPIO2B1);                       
73                 rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_GPIO2B0);                
74
75                 gpio_request(RK29_PIN2_PB1, NULL);
76                 gpio_request(RK29_PIN2_PB0, NULL);
77
78                 gpio_direction_output(RK29_PIN2_PB1, GPIO_LOW);
79                 gpio_direction_output(RK29_PIN2_PB0, GPIO_LOW);
80         }
81         else if(uart_id == 1) {
82                 rk29_mux_api_set(GPIO2A5_UART1SOUT_NAME, GPIO2L_GPIO2A5);                       
83                 rk29_mux_api_set(GPIO2A4_UART1SIN_NAME, GPIO2L_GPIO2A4);                
84
85                 gpio_request(RK29_PIN2_PA5, NULL);
86                 gpio_request(RK29_PIN2_PA4, NULL);
87
88                 gpio_direction_output(RK29_PIN2_PA5, GPIO_LOW);
89                 gpio_direction_output(RK29_PIN2_PA4, GPIO_LOW);
90         }
91         else if(uart_id == 0){
92                 rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_GPIO1B7);                       
93                 gpio_request(RK29_PIN1_PB7, NULL);
94                 gpio_direction_output(RK29_PIN1_PB7,GPIO_LOW);
95                 gpio_pull_updown(RK29_PIN1_PB7, PullDisable);  // ÏÂÀ­½ûÖ¹
96
97                 rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_GPIO1B6);                
98                 gpio_request(RK29_PIN1_PB6, NULL);
99                 gpio_direction_output(RK29_PIN1_PB6,GPIO_LOW);  
100                 gpio_pull_updown(RK29_PIN1_PB6, PullDisable);  // ÏÂÀ­½ûÖ¹
101
102                 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);                        
103                 gpio_request(RK29_PIN1_PC1, NULL);
104                 gpio_direction_output(RK29_PIN1_PC1,GPIO_LOW);
105
106                 rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_GPIO1C0);                 
107                 gpio_request(RK29_PIN1_PC0, NULL);
108                 //gpio_direction_input(RK29_PIN1_PC0);          
109                 gpio_direction_output(RK29_PIN1_PC0,GPIO_LOW);
110         }
111
112         return 0;
113 }
114
115 static int rk29_gpio_to_uart(int uart_id)
116 {
117         if(uart_id == 3) {
118                 rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_UART3_SOUT);
119                 rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_UART3_SIN); 
120
121                 gpio_request(RK29_PIN2_PB3, NULL);
122                 gpio_request(RK29_PIN2_PB2, NULL);
123
124                 gpio_direction_output(RK29_PIN2_PB3, GPIO_HIGH);
125                 gpio_direction_output(RK29_PIN2_PB2, GPIO_HIGH);
126         }
127         else if(uart_id == 2) {
128                 rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT);                    
129                 rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN);              
130
131                 gpio_request(RK29_PIN2_PB1, NULL);
132                 gpio_request(RK29_PIN2_PB0, NULL);
133
134                 gpio_direction_output(RK29_PIN2_PB1, GPIO_HIGH);
135                 gpio_direction_output(RK29_PIN2_PB0, GPIO_HIGH);
136         }
137         else if(uart_id == 1) {
138                 rk29_mux_api_set(GPIO2A5_UART1SOUT_NAME, GPIO2L_UART1_SOUT);                    
139                 rk29_mux_api_set(GPIO2A4_UART1SIN_NAME, GPIO2L_UART1_SIN);              
140
141                 gpio_request(RK29_PIN2_PA5, NULL);
142                 gpio_request(RK29_PIN2_PA4, NULL);
143
144                 gpio_direction_output(RK29_PIN2_PA5, GPIO_HIGH);
145                 gpio_direction_output(RK29_PIN2_PA4, GPIO_HIGH);
146         }
147         else if(uart_id == 0){
148                 rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT);
149                 rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN); 
150                 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
151                 rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N);     
152         }
153
154         return 0;
155
156 }
157
158 static int  get_bp_statue(struct platform_device *pdev)
159 {
160         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
161         
162         if(gpio_get_value(pdata->bp_statue))
163                 return SLEEP;
164         else
165                 return READY;
166 }
167 static void ap_sleep(struct platform_device *pdev)
168 {
169         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
170         
171         MODEMDBG("ap sleep!\n");
172         gpio_set_value(pdata->ap_statue,GPIO_HIGH);
173 }
174 static void ap_wakeup(struct platform_device *pdev)
175 {
176         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
177         
178         MODEMDBG("ap wakeup!\n");
179         gpio_set_value(pdata->ap_statue,GPIO_LOW);
180 }
181 /* */
182 static void ap_wakeup_bp(struct platform_device *pdev, int wake)//low to wakeup bp
183 {
184         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
185         struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
186         MODEMDBG("ap_wakeup_bp\n");
187
188         gpio_set_value(pdata->ap_bp_wakeup, wake);  // phc
189         //gpio_set_value(RK2818_PIN_PF5, wake);
190 }
191
192 static void bpwakeup_work_func_work(struct work_struct *work)
193 {
194         struct modem_dev *bdata = container_of(work, struct modem_dev, work);
195         
196         MODEMDBG("%s\n", __FUNCTION__);
197         
198 }
199 /*  */
200 static irqreturn_t  bpwakeup_work_func(int irq, void *data)
201 {
202         struct modem_dev *mt6223d_data = (struct modem_dev *)data;
203         
204         MODEMDBG("bpwakeup_work_func\n");
205         schedule_work(&mt6223d_data->work);
206         return IRQ_HANDLED;
207 }
208 static irqreturn_t  bp_apwakeup_work_func(int irq, void *data)
209 {
210         //struct modem_dev *dev = &mtk23d_misc;
211         
212         MODEMDBG("bp_apwakeup_work_func\n");
213         //wake_up_interruptible(&dev->wakeup);
214         return IRQ_HANDLED;
215 }
216
217 static irqreturn_t BBwakeup_isr(int irq, void *dev_id)
218 {
219         struct rk2818_23d_data *pdata = dev_id;
220         
221         MODEMDBG("%s \n", __FUNCTION__);
222         //if(irq != gpio_to_irq(RK29_PIN1_PC0))
223         //{
224         //              printk("irq != gpio_to_irq(RK29_PIN1_PC0) \n");
225         //              return IRQ_NONE;
226         //}
227         
228 //      disable_irq_wake(irq);
229         
230         if(bpstatus_irq_enable == true)
231         {
232                 MODEMDBG("mtk23d_wakelock 3s \n");
233                 wake_lock_timeout(&mtk23d_wakelock, 3 * HZ);
234         }
235                 
236
237         return IRQ_HANDLED;
238 }
239
240 int modem_poweron_off(int on_off)
241 {
242         struct rk2818_23d_data *pdata = gpdata;
243         int result, error = 0, irq = 0; 
244         
245   if(on_off)
246         {
247                 printk("modem_poweron\n");
248
249                 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);  // power on enable
250                 mdelay(300);
251                 gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);  // release reset
252                 msleep(3000);
253                 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);  // power on relase
254
255                 rk29_gpio_to_uart(0);
256                 
257                 gpio_direction_input(pdata->bp_statue);
258                 if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
259                 gpio_direction_input(pdata->bp_ap_wakeup);
260
261                 /* ³õʼ»¯BP»½ÐÑAPµÄ¹¦ÄÜ */
262                 wakelock_inited = false;
263                 irq = gpio_to_irq(pdata->bp_statue);
264                 if (irq < 0) {
265                         printk("can't get pdata->bp_statue irq \n");
266                 }
267                 else
268                 {
269                         error = request_irq(irq, BBwakeup_isr,IRQF_TRIGGER_FALLING, NULL, pdata);
270                         if (error) {
271                                 printk("mtk23d_probe bp_statue request_irq error!!! \n");
272                         }
273                 }
274                 if (!wakelock_inited) {
275                         wake_lock_init(&mtk23d_wakelock, WAKE_LOCK_SUSPEND, "23d_resume");
276                         wakelock_inited = true;
277                 }
278         }
279   else
280   {
281                         printk("modem_poweroff\n");
282                         rk29_uart_to_gpio(0);
283                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
284                         msleep(2500);
285                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
286                         msleep(500);
287                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH); 
288   }
289 }
290 static int power_on =1;
291 static int mtk23d_open(struct inode *inode, struct file *file)
292 {
293         struct rk2818_23d_data *pdata = gpdata;
294         //struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
295         struct platform_data *pdev = container_of(pdata, struct device, platform_data);
296
297         MODEMDBG("modem_open\n");
298
299         int ret = 0;
300         if(power_on)
301         {
302                 power_on = 0;
303                 modem_poweron_off(1);
304         }
305         device_init_wakeup(&pdev, 1);
306
307         return 0;
308 }
309
310 static int mtk23d_release(struct inode *inode, struct file *file)
311 {
312         MODEMDBG("mtk23d_release\n");
313
314         //gpio_free(pdata->bp_power);
315         return 0;
316 }
317
318 //extern char imei_value[16]; // phc, no find 'imei_value' in rk29 project
319 //char imei_value[16] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5};
320
321 static int mtk23d_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg)
322 {
323         struct rk2818_23d_data *pdata = gpdata;
324         int i,ret;
325         void __user *argp = (void __user *)arg;
326         
327         char SectorBuffer[512];
328         
329         printk("mtk23d_ioctl\n");
330         ret = down_interruptible(&pdata->power_sem);
331         if (ret < 0) {
332                 printk("%s: down power_sem error ret = %d\n", __func__, ret);
333                 return ret;
334         }
335         
336         switch(cmd)
337         {
338
339                 case MTK23D_POWEROFF:
340                         printk("MTK23D_POWEROFF\n");
341                         rk29_uart_to_gpio(0);
342                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
343                         msleep(2500);
344                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
345                         msleep(500);
346                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
347                         break;
348
349                 case MTK23D_RESET:              
350                         printk("MTK23D_RESET\n");
351                         /****power off 23d and uart to gpio***/
352                         rk29_uart_to_gpio(0);
353                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
354                         msleep(2500);
355                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
356                         msleep(500);
357                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
358                         
359                         /****power on 23d***/
360                         msleep(100);
361                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
362                         rk29_gpio_to_uart(0);
363                         msleep(300);
364                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
365                         msleep(2500);
366                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
367                         break;
368
369                 case MTK23D_POWERON:            
370                         /****power on 23d***/
371                         printk("MTK23D_POWERON\n");
372                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
373                         msleep(100);
374                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
375                         rk29_gpio_to_uart(0);
376                         msleep(300);
377                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
378                         msleep(2500);
379                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
380                         break;
381                         
382                 case MTK23D_IMEI_READ:
383                         printk("MTK23D_IMEI_READ\n");
384                         
385                         GetSNSectorInfo(SectorBuffer); // phc,20110624
386                         
387                         if(copy_to_user(argp, &(SectorBuffer[451]), 16))  // IMEIºó´Ó451Æ«ÒÆ¿ªÊ¼µÄ16bytes£¬µÚÒ»¸öbyteΪ³¤¶È¹Ì¶¨Îª15
388                         {
389                                 printk("ERROR: copy_to_user---%s\n", __FUNCTION__);
390                                 up(&pdata->power_sem);
391                                 return -EFAULT;
392                         }
393                         //printk("IMEI:%d %d %d %d\n", SectorBuffer[451], SectorBuffer[452], SectorBuffer[453], SectorBuffer[454]);
394                         break;
395                 default:
396                         break;
397         }
398
399         up(&pdata->power_sem);
400         
401         return 0;
402 }
403
404 static struct file_operations mtk23d_fops = {
405         .owner = THIS_MODULE,
406         .open = mtk23d_open,
407         .release = mtk23d_release,
408         .ioctl = mtk23d_ioctl
409 };
410
411 static struct miscdevice mtk23d_misc = {
412         .minor = MISC_DYNAMIC_MINOR,
413         .name = MODEM_NAME,
414         .fops = &mtk23d_fops
415 };
416
417 static int mtk23d_probe(struct platform_device *pdev)
418 {
419         struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
420         struct modem_dev *mt6223d_data = NULL;
421         int result, error = 0, irq = 0; 
422         
423         MODEMDBG("mtk23d_probe\n");
424
425         //pdata->io_init();
426
427         mt6223d_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
428         if(NULL == mt6223d_data)
429         {
430                 printk("failed to request mt6223d_data\n");
431                 goto err6;
432         }
433         platform_set_drvdata(pdev, mt6223d_data);
434
435         result = gpio_request(pdata->bp_statue, "mtk23d");
436         if (result) {
437                 printk("failed to request BP_STATUS gpio\n");
438                 goto err5;
439         }
440         
441         result = gpio_request(pdata->ap_statue, "mtk23d");
442         if (result) {
443                 printk("failed to request AP_STATUS gpio\n");
444                 goto err4;
445         }       
446         
447         result = gpio_request(pdata->ap_bp_wakeup, "mtk23d");
448         if (result) {
449                 printk("failed to request AP_BP_WAKEUP gpio\n");
450                 goto err3;
451         }       
452         result = gpio_request(pdata->bp_reset, "mtk23d");
453         if (result) {
454                 printk("failed to request BP_RESET gpio\n");
455                 goto err2;
456         }               
457         result = gpio_request(pdata->bp_power, "mtk23d");
458         if (result) {
459                 printk("failed to request BP_POW_EN gpio\n");
460                 goto err1;
461         }
462         
463         if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
464         {
465                 result = gpio_request(pdata->bp_ap_wakeup, "mtk23d");
466                 if (result) {
467                         printk("failed to request BP_AP_WAKEUP gpio\n");
468                         goto err0;
469                 }               
470         }
471         
472 #if 1 // GPIO³õʼ»¯£¬²¢ÇÒ·Àֹ©µç
473         rk29_uart_to_gpio(0);
474
475         /***power off 23d***/
476         gpio_direction_output(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
477         
478         gpio_direction_output(pdata->ap_statue, GPIO_LOW);
479         gpio_direction_output(pdata->ap_bp_wakeup, GPIO_LOW);   
480         //gpio_direction_output(pdata->bp_statue,GPIO_LOW);
481         gpio_direction_input(pdata->bp_statue);
482         if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
483         {
484                 //gpio_direction_output(pdata->bp_ap_wakeup,GPIO_LOW);
485                 gpio_direction_input(pdata->bp_ap_wakeup);
486         }
487
488         /*¸´Î»BP*/
489         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
490         //mdelay(200);
491         //gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
492 #endif  
493
494         INIT_WORK(&mt6223d_data->work, bpwakeup_work_func_work);
495         init_MUTEX(&pdata->power_sem);
496         power_on = 1;
497         result = misc_register(&mtk23d_misc);
498         if(result)
499         {
500                 MODEMDBG("misc_register err\n");
501         }
502         MODEMDBG("mtk23d_probe ok\n");
503         
504         return result;
505 err0:
506         cancel_work_sync(&mt6223d_data->work);
507         gpio_free(pdata->bp_ap_wakeup);
508 err1:
509         gpio_free(pdata->bp_power);
510 err2:
511         gpio_free(pdata->bp_reset);
512 err3:
513         gpio_free(pdata->ap_bp_wakeup);
514 err4:
515         gpio_free(pdata->ap_statue);
516 err5:
517         gpio_free(pdata->bp_statue);
518 err6:
519         kfree(mt6223d_data);
520 ret:
521         return result;
522 }
523
524 int mtk23d_suspend(struct platform_device *pdev)
525 {
526         int irq, error;
527         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
528         
529         MODEMDBG("%s \n", __FUNCTION__);
530         
531         //enable_irq_wake(irq);
532         ap_sleep(pdev);
533         ap_wakeup_bp(pdev, 0);
534
535         irq = gpio_to_irq(pdata->bp_statue);
536         if (irq < 0) {
537                 printk("can't get pdata->bp_statue irq \n");
538         }
539         else
540         {
541                 printk("enable pdata->bp_statue irq_wake!! \n");
542                 bpstatus_irq_enable = true;
543                 enable_irq_wake(irq);
544         }
545         
546         return 0;
547 }
548
549 int mtk23d_resume(struct platform_device *pdev)
550 {
551         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
552         int irq = 0;
553         
554         MODEMDBG("%s \n", __FUNCTION__);
555         
556         irq = gpio_to_irq(pdata->bp_statue);
557         if(irq)
558         {
559                 printk("disable pdata->bp_statue irq_wake!! \n");
560                 bpstatus_irq_enable = false;
561                 disable_irq_wake(irq);
562         }
563         
564         ap_wakeup(pdev);
565         ap_wakeup_bp(pdev, 1);
566         
567         return 0;
568 }
569
570 void mtk23d_shutdown(struct platform_device *pdev, pm_message_t state)
571 {
572         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
573         struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
574         
575         MODEMDBG("%s \n", __FUNCTION__);
576
577         modem_poweron_off(0);  // power down
578
579         cancel_work_sync(&mt6223d_data->work);
580         gpio_free(pdata->bp_ap_wakeup);
581         gpio_free(pdata->bp_power);
582         gpio_free(pdata->bp_reset);
583         gpio_free(pdata->ap_bp_wakeup);
584         gpio_free(pdata->ap_statue);
585         gpio_free(pdata->bp_statue);
586         kfree(mt6223d_data);
587 }
588
589 static struct platform_driver mtk23d_driver = {
590         .probe  = mtk23d_probe,
591         .shutdown       = mtk23d_shutdown,
592         .suspend        = mtk23d_suspend,
593         .resume         = mtk23d_resume,
594         .driver = {
595                 .name   = "mtk23d",
596                 .owner  = THIS_MODULE,
597         },
598 };
599
600 static int __init mtk23d_init(void)
601 {
602         MODEMDBG("mtk23d_init ret=%d\n");
603         return platform_driver_register(&mtk23d_driver);
604 }
605
606 static void __exit mtk23d_exit(void)
607 {
608         MODEMDBG("mtk23d_exit\n");
609         platform_driver_unregister(&mtk23d_driver);
610 }
611
612 module_init(mtk23d_init);
613 //late_initcall_sync(mtk23d_init);
614 module_exit(mtk23d_exit);