RK29MobileSDK:update mtk23d_ioctl of mtk23d.c
[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
25 MODULE_LICENSE("GPL");
26
27 #define DEBUG
28 #ifdef DEBUG
29 #define MODEMDBG(x...) printk(x)
30 #else
31 #define MODEMDBG(fmt,argss...)
32 #endif
33
34 #define MTK23D_RESET 0x01
35 #define MTK23D_POWERON  0x02
36 #define MTK23D_POWER_HIGH 0x03
37 #define MTK23D_IMEI_READ  0x04
38 //#define BP_POW_EN     TCA6424_P02
39 //#define BP_STATUS    RK2818_PIN_PH7    //input  high bp sleep
40 //#define AP_STATUS    RK2818_PIN_PA4    //output high ap sleep
41
42 //#define BP_RESET      TCA6424_P11     //Ryan
43
44 //#define AP_BP_WAKEUP  RK2818_PIN_PF5   //output AP wake up BP used rising edge
45 //#define BP_AP_WAKEUP  RK2818_PIN_PE0  //input BP wake up AP
46
47 #define SLEEP 1
48 #define READY 0
49
50 //struct modem_dev *mt6223d_data = NULL;
51 struct rk2818_23d_data *gpdata = NULL;
52
53 static int  get_bp_statue(struct platform_device *pdev)
54 {
55         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
56         
57         if(gpio_get_value(pdata->bp_statue))
58                 return SLEEP;
59         else
60                 return READY;
61 }
62 static void ap_sleep(struct platform_device *pdev)
63 {
64         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
65         
66         MODEMDBG("ap sleep!\n");
67         gpio_set_value(pdata->ap_statue,GPIO_HIGH);
68 }
69 static void ap_wakeup(struct platform_device *pdev)
70 {
71         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
72         
73         MODEMDBG("ap wakeup!\n");
74         gpio_set_value(pdata->ap_statue,GPIO_LOW);
75 }
76 /* */
77 static void ap_wakeup_bp(struct platform_device *pdev, int wake)//low to wakeup bp
78 {
79         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
80         struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
81         MODEMDBG("ap_wakeup_bp\n");
82
83         gpio_set_value(pdata->ap_bp_wakeup, wake);  // phc
84         //gpio_set_value(RK2818_PIN_PF5, wake);
85 }
86
87 static void bpwakeup_work_func_work(struct work_struct *work)
88 {
89         struct modem_dev *bdata = container_of(work, struct modem_dev, work);
90         
91         MODEMDBG("%s\n", __FUNCTION__);
92         
93 }
94 /*  */
95 static irqreturn_t  bpwakeup_work_func(int irq, void *data)
96 {
97         struct modem_dev *mt6223d_data = (struct modem_dev *)data;
98         
99         MODEMDBG("bpwakeup_work_func\n");
100         schedule_work(&mt6223d_data->work);
101         return IRQ_HANDLED;
102 }
103 static irqreturn_t  bp_apwakeup_work_func(int irq, void *data)
104 {
105         //struct modem_dev *dev = &mtk23d_misc;
106         
107         MODEMDBG("bp_apwakeup_work_func\n");
108         //wake_up_interruptible(&dev->wakeup);
109         return IRQ_HANDLED;
110 }
111 int modem_poweron_off(int on_off)
112 {
113         struct rk2818_23d_data *pdata = gpdata;
114         
115   if(on_off)
116   {
117          printk("modem_poweron\n");
118          gpio_set_value(gpdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
119          msleep(4000);
120          gpio_set_value(gpdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
121   }
122   else
123   {
124          printk("modem_poweroff\n");
125          gpio_set_value(gpdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
126          mdelay(100);
127          gpio_set_value(gpdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
128   }
129 }
130 static int power_on =1;
131 static int mtk23d_open(struct inode *inode, struct file *file)
132 {
133         struct rk2818_23d_data *pdata = gpdata;
134         //struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
135         struct platform_data *pdev = container_of(pdata, struct device, platform_data);
136
137         MODEMDBG("modem_open\n");
138
139         int ret = 0;
140         if(power_on)
141         {
142                 power_on = 0;
143                 modem_poweron_off(1);
144         }
145         device_init_wakeup(&pdev, 1);
146
147         return 0;
148 }
149
150 static int mtk23d_release(struct inode *inode, struct file *file)
151 {
152         MODEMDBG("mtk23d_release\n");
153
154         //gpio_free(pdata->bp_power);
155         return 0;
156 }
157
158 //extern char imei_value[16]; // phc, no find 'imei_value' in rk29 project
159 char imei_value[16] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5};
160
161 static int mtk23d_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg)
162 {
163         struct rk2818_23d_data *pdata = gpdata;
164         int i;
165         void __user *argp = (void __user *)arg;
166         printk("mtk23d_ioctl\n");
167         switch(cmd)
168         {
169                 case MTK23D_RESET:
170                         gpio_set_value(gpdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
171                         mdelay(100);
172                         gpio_direction_output(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
173                         mdelay(100);
174                         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
175                         msleep(4000);
176                         gpio_set_value(gpdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
177                         break;
178                 case MTK23D_IMEI_READ:
179                         if(copy_to_user(argp, &(imei_value[0]), 16))
180                         {
181                                 printk("ERROR: copy_to_user---%s\n", __FUNCTION__);
182                                 return -EFAULT;
183                         }
184                         break;
185                 default:
186                         break;
187         }
188         return 0;
189 }
190
191 static struct file_operations mtk23d_fops = {
192         .owner = THIS_MODULE,
193         .open = mtk23d_open,
194         .release = mtk23d_release,
195         .ioctl = mtk23d_ioctl
196 };
197
198 static struct miscdevice mtk23d_misc = {
199         .minor = MISC_DYNAMIC_MINOR,
200         .name = MODEM_NAME,
201         .fops = &mtk23d_fops
202 };
203
204 static int mtk23d_probe(struct platform_device *pdev)
205 {
206         struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
207         struct modem_dev *mt6223d_data = NULL;
208         int result, irq = 0;    
209         
210         MODEMDBG("mtk23d_probe\n");
211
212 #if 1   
213         rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_GPIO1B7);                       
214         gpio_request(RK29_PIN1_PB7, NULL);
215         gpio_direction_output(RK29_PIN1_PB7,GPIO_LOW);
216         gpio_pull_updown(RK29_PIN1_PB7, PullDisable);  // ÏÂÀ­½ûÖ¹
217         
218         rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_GPIO1B6);                
219         gpio_request(RK29_PIN1_PB6, NULL);
220         gpio_direction_output(RK29_PIN1_PB6,GPIO_LOW);  
221         gpio_pull_updown(RK29_PIN1_PB6, PullDisable);  // ÏÂÀ­½ûÖ¹
222         
223         rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);                        
224         gpio_request(RK29_PIN1_PC1, NULL);
225         gpio_direction_output(RK29_PIN1_PC1,GPIO_LOW);
226         
227         rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_GPIO1C0);                 
228         gpio_request(RK29_PIN1_PC0, NULL);
229         gpio_direction_output(RK29_PIN1_PC0,GPIO_LOW);          
230 #endif
231
232         pdata->io_init();
233
234         mt6223d_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
235         if(NULL == mt6223d_data)
236         {
237                 printk("failed to request mt6223d_data\n");
238                 goto err6;
239         }
240         platform_set_drvdata(pdev, mt6223d_data);
241
242         result = gpio_request(pdata->bp_statue, "mtk23d");
243         if (result) {
244                 printk("failed to request BP_STATUS gpio\n");
245                 goto err5;
246         }
247         
248         result = gpio_request(pdata->ap_statue, "mtk23d");
249         if (result) {
250                 printk("failed to request AP_STATUS gpio\n");
251                 goto err4;
252         }       
253         
254         result = gpio_request(pdata->ap_bp_wakeup, "mtk23d");
255         if (result) {
256                 printk("failed to request AP_BP_WAKEUP gpio\n");
257                 goto err3;
258         }       
259         result = gpio_request(pdata->bp_reset, "mtk23d");
260         if (result) {
261                 printk("failed to request BP_RESET gpio\n");
262                 goto err2;
263         }               
264         result = gpio_request(pdata->bp_power, "mtk23d");
265         if (result) {
266                 printk("failed to request BP_POW_EN gpio\n");
267                 goto err1;
268         }
269         
270 #if 1 // phc
271         gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
272         gpio_direction_output(pdata->ap_statue, GPIO_LOW);
273         gpio_direction_output(pdata->ap_bp_wakeup, GPIO_LOW);
274         mdelay(100);
275         gpio_direction_output(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
276         mdelay(100);
277         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
278 #endif  
279         
280 #if 0 
281         gpio_direction_input(pdata->bp_statue);
282         
283         //rk2818_mux_api_set(CXGPIO_HSADC_SEL_NAME, 0);
284         gpio_direction_output(pdata->ap_statue, GPIO_LOW);
285         
286         //rk2818_mux_api_set(GPIOF5_APWM3_DPWM3_NAME,0);
287         gpio_direction_output(pdata->ap_bp_wakeup, GPIO_LOW);
288         mdelay(100);
289         //rk2818_mux_api_set(GPIOE_SPI1_FLASH_SEL_NAME, IOMUXA_GPIO1_A3B7);
290         gpio_direction_output(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
291         mdelay(100);
292         gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
293         gpio_set_value(pdata->ap_bp_wakeup, GPIO_HIGH);
294 #endif
295
296         INIT_WORK(&mt6223d_data->work, bpwakeup_work_func_work);
297         power_on = 1;
298         result = misc_register(&mtk23d_misc);
299         if(result)
300         {
301                 MODEMDBG("misc_register err\n");
302         }
303         MODEMDBG("mtk23d_probe ok\n");
304         return result;
305 err0:
306         cancel_work_sync(&mt6223d_data->work);
307         gpio_free(pdata->bp_ap_wakeup);
308 err1:
309         gpio_free(pdata->bp_power);
310 err2:
311         gpio_free(pdata->bp_reset);
312 err3:
313         gpio_free(pdata->ap_bp_wakeup);
314 err4:
315         gpio_free(pdata->ap_statue);
316 err5:
317         gpio_free(pdata->bp_statue);
318 err6:
319         kfree(mt6223d_data);
320 ret:
321         return result;
322 }
323
324 int mtk23d_suspend(struct platform_device *pdev)
325 {
326         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
327         //int irq = gpio_to_irq(pdata->bp_ap_wakeup);
328         
329         MODEMDBG("%s \n", __FUNCTION__);
330         //enable_irq_wake(irq);
331         ap_sleep(pdev);
332         ap_wakeup_bp(pdev, 0);
333         return 0;
334 }
335
336 int mtk23d_resume(struct platform_device *pdev)
337 {
338         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
339         //int irq = gpio_to_irq(pdata->bp_ap_wakeup);
340         
341         MODEMDBG("%s \n", __FUNCTION__);
342         //disable_irq_wake(irq);
343         ap_wakeup(pdev);
344         ap_wakeup_bp(pdev, 1);
345         return 0;
346 }
347
348 void mtk23d_shutdown(struct platform_device *pdev, pm_message_t state)
349 {
350         struct rk2818_23d_data *pdata = pdev->dev.platform_data;
351         struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
352         
353         MODEMDBG("%s \n", __FUNCTION__);
354         
355         modem_poweron_off(0);  // power down
356
357         cancel_work_sync(&mt6223d_data->work);
358         gpio_free(pdata->bp_ap_wakeup);
359         gpio_free(pdata->bp_power);
360         gpio_free(pdata->bp_reset);
361         gpio_free(pdata->ap_bp_wakeup);
362         gpio_free(pdata->ap_statue);
363         gpio_free(pdata->bp_statue);
364         kfree(mt6223d_data);
365 }
366
367 static struct platform_driver mtk23d_driver = {
368         .probe  = mtk23d_probe,
369         .shutdown       = mtk23d_shutdown,
370         .suspend        = mtk23d_suspend,
371         .resume         = mtk23d_resume,
372         .driver = {
373                 .name   = "mtk23d",
374                 .owner  = THIS_MODULE,
375         },
376 };
377
378 static int __init mtk23d_init(void)
379 {
380         MODEMDBG("mtk23d_init ret=%d\n");
381         return platform_driver_register(&mtk23d_driver);
382 }
383
384 static void __exit mtk23d_exit(void)
385 {
386         MODEMDBG("mtk23d_exit\n");
387         platform_driver_unregister(&mtk23d_driver);
388 }
389
390 module_init(mtk23d_init);
391 //late_initcall_sync(mtk23d_init);
392 module_exit(mtk23d_exit);