RK29SmartPhone:mtk23d reset&control changed
[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
26 MODULE_LICENSE("GPL");
27
28 #define DEBUG
29 #ifdef DEBUG
30 #define MODEMDBG(x...) printk(x)
31 #else
32 #define MODEMDBG(fmt,argss...)
33 #endif
34
35 #define MTK23D_RESET 0x01
36 #define MTK23D_POWERON  0x02
37 #define MTK23D_POWER_HIGH 0x03
38 #define MTK23D_IMEI_READ  0x04
39 //#define BP_POW_EN     TCA6424_P02
40 //#define BP_STATUS    RK2818_PIN_PH7    //input  high bp sleep
41 //#define AP_STATUS    RK2818_PIN_PA4    //output high ap sleep
42
43 //#define BP_RESET      TCA6424_P11     //Ryan
44
45 //#define AP_BP_WAKEUP  RK2818_PIN_PF5   //output AP wake up BP used rising edge
46 //#define BP_AP_WAKEUP  RK2818_PIN_PE0  //input BP wake up AP
47
48 static bool bpstatus_irq_enable = false;
49 static bool wakelock_inited;
50 static struct wake_lock mtk23d_wakelock;
51
52 #define SLEEP 1
53 #define READY 0
54
55 //struct modem_dev *mt6223d_data = NULL;
56 struct rk2818_23d_data *gpdata = NULL;
57
58 static int  get_bp_statue(struct platform_device *pdev)
59 {
60         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
61         
62         if(gpio_get_value(pdata->bp_statue))
63                 return SLEEP;
64         else
65                 return READY;
66 }
67 static void ap_sleep(struct platform_device *pdev)
68 {
69         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
70         
71         MODEMDBG("ap sleep!\n");
72         gpio_set_value(pdata->ap_statue,GPIO_HIGH);
73 }
74 static void ap_wakeup(struct platform_device *pdev)
75 {
76         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
77         
78         MODEMDBG("ap wakeup!\n");
79         gpio_set_value(pdata->ap_statue,GPIO_LOW);
80 }
81 /* */
82 static void ap_wakeup_bp(struct platform_device *pdev, int wake)//low to wakeup bp
83 {
84         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
85         struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
86         MODEMDBG("ap_wakeup_bp\n");
87
88         gpio_set_value(pdata->ap_bp_wakeup, wake);  // phc
89         //gpio_set_value(RK2818_PIN_PF5, wake);
90 }
91
92 static void bpwakeup_work_func_work(struct work_struct *work)
93 {
94         struct modem_dev *bdata = container_of(work, struct modem_dev, work);
95         
96         MODEMDBG("%s\n", __FUNCTION__);
97         
98 }
99 /*  */
100 static irqreturn_t  bpwakeup_work_func(int irq, void *data)
101 {
102         struct modem_dev *mt6223d_data = (struct modem_dev *)data;
103         
104         MODEMDBG("bpwakeup_work_func\n");
105         schedule_work(&mt6223d_data->work);
106         return IRQ_HANDLED;
107 }
108 static irqreturn_t  bp_apwakeup_work_func(int irq, void *data)
109 {
110         //struct modem_dev *dev = &mtk23d_misc;
111         
112         MODEMDBG("bp_apwakeup_work_func\n");
113         //wake_up_interruptible(&dev->wakeup);
114         return IRQ_HANDLED;
115 }
116
117 static irqreturn_t BBwakeup_isr(int irq, void *dev_id)
118 {
119         struct rk2818_23d_data *pdata = dev_id;
120         
121         MODEMDBG("%s \n", __FUNCTION__);
122         //if(irq != gpio_to_irq(RK29_PIN1_PC0))
123         //{
124         //              printk("irq != gpio_to_irq(RK29_PIN1_PC0) \n");
125         //              return IRQ_NONE;
126         //}
127         
128 //      disable_irq_wake(irq);
129         
130         if(bpstatus_irq_enable == true)
131         {
132                 MODEMDBG("mtk23d_wakelock 3s \n");
133                 wake_lock_timeout(&mtk23d_wakelock, 3 * HZ);
134         }
135                 
136
137         return IRQ_HANDLED;
138 }
139
140 int modem_poweron_off(int on_off)
141 {
142         struct rk2818_23d_data *pdata = gpdata;
143         int result, error = 0, irq = 0; 
144         
145   if(on_off)
146   {
147                         printk("modem_poweron\n");
148                         
149                   gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);  // power on enable
150                   mdelay(300);
151                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);  // release reset
152                         msleep(3000);
153                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);  // power on relase
154                                 
155                         #if 1 // phc
156                         rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT);
157                         rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN); 
158                         rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
159                         rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N);     
160                         #endif
161                         
162                   gpio_direction_input(pdata->bp_statue);
163                   gpio_direction_input(pdata->bp_ap_wakeup);
164                         
165                         /* ³õʼ»¯BP»½ÐÑAPµÄ¹¦ÄÜ */
166                         wakelock_inited = false;
167                         irq = gpio_to_irq(pdata->bp_statue);
168                         if (irq < 0) {
169                                 printk("can't get pdata->bp_statue irq \n");
170                         }
171                         else
172                         {
173                                 error = request_irq(irq, BBwakeup_isr,
174                                                     IRQF_TRIGGER_FALLING,
175                                                     NULL,
176                                                     pdata);
177                                 if (error) {
178                                         printk("mtk23d_probe bp_statue request_irq error!!! \n");
179                                 }
180                         }
181                         if (!wakelock_inited) {
182                                 wake_lock_init(&mtk23d_wakelock, WAKE_LOCK_SUSPEND, "23d_resume");
183                                 wakelock_inited = true;
184                         }
185   }
186   else
187   {
188                         printk("modem_poweroff\n");
189                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
190                         mdelay(100);
191                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
192   }
193 }
194 static int power_on =1;
195 static int mtk23d_open(struct inode *inode, struct file *file)
196 {
197         struct rk2818_23d_data *pdata = gpdata;
198         //struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
199         struct platform_data *pdev = container_of(pdata, struct device, platform_data);
200
201         MODEMDBG("modem_open\n");
202
203         int ret = 0;
204         if(power_on)
205         {
206                 power_on = 0;
207                 modem_poweron_off(1);
208         }
209         device_init_wakeup(&pdev, 1);
210
211         return 0;
212 }
213
214 static int mtk23d_release(struct inode *inode, struct file *file)
215 {
216         MODEMDBG("mtk23d_release\n");
217
218         //gpio_free(pdata->bp_power);
219         return 0;
220 }
221
222 //extern char imei_value[16]; // phc, no find 'imei_value' in rk29 project
223 char imei_value[16] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5};
224
225 static int mtk23d_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg)
226 {
227         struct rk2818_23d_data *pdata = gpdata;
228         int i;
229         void __user *argp = (void __user *)arg;
230         printk("mtk23d_ioctl\n");
231         switch(cmd)
232         {
233                 case MTK23D_RESET:              
234                         printk("MTK23D_RESET\n");
235                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
236                         mdelay(100);
237                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
238                         mdelay(300);
239                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
240                         msleep(3000);
241                         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
242                         break;
243                 case MTK23D_IMEI_READ:
244                         printk("MTK23D_IMEI_READ\n");
245                         if(copy_to_user(argp, &(imei_value[0]), 16))
246                         {
247                                 printk("ERROR: copy_to_user---%s\n", __FUNCTION__);
248                                 return -EFAULT;
249                         }
250                         break;
251                 default:
252                         break;
253         }
254         return 0;
255 }
256
257 static struct file_operations mtk23d_fops = {
258         .owner = THIS_MODULE,
259         .open = mtk23d_open,
260         .release = mtk23d_release,
261         .ioctl = mtk23d_ioctl
262 };
263
264 static struct miscdevice mtk23d_misc = {
265         .minor = MISC_DYNAMIC_MINOR,
266         .name = MODEM_NAME,
267         .fops = &mtk23d_fops
268 };
269
270 static int mtk23d_probe(struct platform_device *pdev)
271 {
272         struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
273         struct modem_dev *mt6223d_data = NULL;
274         int result, error = 0, irq = 0; 
275         
276         MODEMDBG("mtk23d_probe\n");
277
278         //pdata->io_init();
279
280         mt6223d_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
281         if(NULL == mt6223d_data)
282         {
283                 printk("failed to request mt6223d_data\n");
284                 goto err6;
285         }
286         platform_set_drvdata(pdev, mt6223d_data);
287
288         result = gpio_request(pdata->bp_statue, "mtk23d");
289         if (result) {
290                 printk("failed to request BP_STATUS gpio\n");
291                 goto err5;
292         }
293         
294         result = gpio_request(pdata->ap_statue, "mtk23d");
295         if (result) {
296                 printk("failed to request AP_STATUS gpio\n");
297                 goto err4;
298         }       
299         
300         result = gpio_request(pdata->ap_bp_wakeup, "mtk23d");
301         if (result) {
302                 printk("failed to request AP_BP_WAKEUP gpio\n");
303                 goto err3;
304         }       
305         result = gpio_request(pdata->bp_reset, "mtk23d");
306         if (result) {
307                 printk("failed to request BP_RESET gpio\n");
308                 goto err2;
309         }               
310         result = gpio_request(pdata->bp_power, "mtk23d");
311         if (result) {
312                 printk("failed to request BP_POW_EN gpio\n");
313                 goto err1;
314         }
315         
316         if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
317         {
318                 result = gpio_request(pdata->bp_ap_wakeup, "mtk23d");
319                 if (result) {
320                         printk("failed to request BP_AP_WAKEUP gpio\n");
321                         goto err0;
322                 }               
323         }
324         
325 #if 1 // GPIO³õʼ»¯£¬²¢ÇÒ·Àֹ©µç
326         rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_GPIO1B7);                       
327         gpio_request(RK29_PIN1_PB7, NULL);
328         gpio_direction_output(RK29_PIN1_PB7,GPIO_LOW);
329         gpio_pull_updown(RK29_PIN1_PB7, PullDisable);  // ÏÂÀ­½ûÖ¹
330         
331         rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_GPIO1B6);                
332         gpio_request(RK29_PIN1_PB6, NULL);
333         gpio_direction_output(RK29_PIN1_PB6,GPIO_LOW);  
334         gpio_pull_updown(RK29_PIN1_PB6, PullDisable);  // ÏÂÀ­½ûÖ¹
335         
336         rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);                        
337         gpio_request(RK29_PIN1_PC1, NULL);
338         gpio_direction_output(RK29_PIN1_PC1,GPIO_LOW);
339         
340         rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_GPIO1C0);                 
341         gpio_request(RK29_PIN1_PC0, NULL);
342         //gpio_direction_input(RK29_PIN1_PC0);          
343         gpio_direction_output(RK29_PIN1_PC0,GPIO_LOW);
344
345
346   gpio_direction_output(pdata->bp_power, GPIO_LOW);
347         gpio_direction_output(pdata->ap_statue, GPIO_LOW);
348         gpio_direction_output(pdata->ap_bp_wakeup, GPIO_LOW);   
349         gpio_direction_output(pdata->bp_reset, GPIO_LOW);
350         //gpio_direction_output(pdata->bp_statue,GPIO_LOW);
351         gpio_direction_input(pdata->bp_statue);
352         if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
353         {
354                 //gpio_direction_output(pdata->bp_ap_wakeup,GPIO_LOW);
355                 gpio_direction_input(pdata->bp_ap_wakeup);
356         }
357         
358         /*¸´Î»BP*/
359         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
360         //mdelay(200);
361         //gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
362 #endif  
363
364         INIT_WORK(&mt6223d_data->work, bpwakeup_work_func_work);
365   power_on = 1;
366         result = misc_register(&mtk23d_misc);
367         if(result)
368         {
369                 MODEMDBG("misc_register err\n");
370         }
371         MODEMDBG("mtk23d_probe ok\n");
372         
373         return result;
374 err0:
375         cancel_work_sync(&mt6223d_data->work);
376         gpio_free(pdata->bp_ap_wakeup);
377 err1:
378         gpio_free(pdata->bp_power);
379 err2:
380         gpio_free(pdata->bp_reset);
381 err3:
382         gpio_free(pdata->ap_bp_wakeup);
383 err4:
384         gpio_free(pdata->ap_statue);
385 err5:
386         gpio_free(pdata->bp_statue);
387 err6:
388         kfree(mt6223d_data);
389 ret:
390         return result;
391 }
392
393 int mtk23d_suspend(struct platform_device *pdev)
394 {
395         int irq, error;
396         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
397         
398         MODEMDBG("%s \n", __FUNCTION__);
399         
400         //enable_irq_wake(irq);
401         ap_sleep(pdev);
402         ap_wakeup_bp(pdev, 0);
403
404         irq = gpio_to_irq(pdata->bp_statue);
405         if (irq < 0) {
406                 printk("can't get pdata->bp_statue irq \n");
407         }
408         else
409         {
410                 printk("enable pdata->bp_statue irq_wake!! \n");
411                 bpstatus_irq_enable = true;
412                 enable_irq_wake(irq);
413         }
414         
415         return 0;
416 }
417
418 int mtk23d_resume(struct platform_device *pdev)
419 {
420         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
421         int irq = 0;
422         
423         MODEMDBG("%s \n", __FUNCTION__);
424         
425         irq = gpio_to_irq(pdata->bp_statue);
426         if(irq)
427         {
428                 printk("disable pdata->bp_statue irq_wake!! \n");
429                 bpstatus_irq_enable = false;
430                 disable_irq_wake(irq);
431         }
432         
433         ap_wakeup(pdev);
434         ap_wakeup_bp(pdev, 1);
435         
436         return 0;
437 }
438
439 void mtk23d_shutdown(struct platform_device *pdev, pm_message_t state)
440 {
441         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
442         struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
443         
444         MODEMDBG("%s \n", __FUNCTION__);
445
446         modem_poweron_off(0);  // power down
447
448         cancel_work_sync(&mt6223d_data->work);
449         gpio_free(pdata->bp_ap_wakeup);
450         gpio_free(pdata->bp_power);
451         gpio_free(pdata->bp_reset);
452         gpio_free(pdata->ap_bp_wakeup);
453         gpio_free(pdata->ap_statue);
454         gpio_free(pdata->bp_statue);
455         kfree(mt6223d_data);
456 }
457
458 static struct platform_driver mtk23d_driver = {
459         .probe  = mtk23d_probe,
460         .shutdown       = mtk23d_shutdown,
461         .suspend        = mtk23d_suspend,
462         .resume         = mtk23d_resume,
463         .driver = {
464                 .name   = "mtk23d",
465                 .owner  = THIS_MODULE,
466         },
467 };
468
469 static int __init mtk23d_init(void)
470 {
471         MODEMDBG("mtk23d_init ret=%d\n");
472         return platform_driver_register(&mtk23d_driver);
473 }
474
475 static void __exit mtk23d_exit(void)
476 {
477         MODEMDBG("mtk23d_exit\n");
478         platform_driver_unregister(&mtk23d_driver);
479 }
480
481 module_init(mtk23d_init);
482 //late_initcall_sync(mtk23d_init);
483 module_exit(mtk23d_exit);