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