rk3188 ds1006h: wakeup system by OTG BVALID interrupt when USB OTG conneted
[firefly-linux-kernel-4.4.55.git] / drivers / misc / 3g_module / mi700.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 <linux/delay.h>
17 #include <linux/poll.h>
18 #include <linux/wait.h>
19 #include <linux/wakelock.h>
20 #include <linux/workqueue.h>
21 #include <linux/mi700.h>
22 #include <mach/iomux.h>
23 #include<linux/ioctl.h>
24 #include <linux/slab.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         MW100IO 0XA1
36 #define MW_IOCTL_RESET  _IO(MW100IO,0X01)
37
38 #define SLEEP 1
39 #define READY 0
40 #define MI700_RESET 0x01
41 static struct wake_lock modem_wakelock;
42 #define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_RISING
43 struct rk29_mi700_data *gpdata = NULL;
44 static int  bp_wakeup_ap_irq = 0;
45 struct class *modem_class = NULL; 
46 static int do_wakeup_irq = 1;
47 static int modem_status;
48 static int online = 0;
49
50 static void ap_wakeup_bp(struct platform_device *pdev, int wake)
51 {
52         struct rk29_mi700_data *pdata = pdev->dev.platform_data;
53         MODEMDBG("ap_wakeup_bp\n");
54
55         gpio_set_value(pdata->ap_wakeup_bp, wake);  
56
57 }
58 extern void rk28_send_wakeup_key(void);
59
60 static void do_wakeup(struct work_struct *work)
61 {
62     MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
63     //rk28_send_wakeup_key();
64 }
65
66 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
67 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
68 {
69     if(do_wakeup_irq)
70     {
71         do_wakeup_irq = 0;
72         printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
73         wake_lock_timeout(&modem_wakelock, 10 * HZ);
74         schedule_delayed_work(&wakeup_work, HZ / 10);
75     } else
76         printk("%s: already wakeup\n", __FUNCTION__);
77
78     return IRQ_HANDLED;
79 }
80 int modem_poweron_off(int on_off)
81 {
82         struct rk29_mi700_data *pdata = gpdata; 
83         
84         mutex_lock(&pdata->bp_mutex);
85         if(on_off)
86         {
87                 MODEMDBG("------------modem_poweron\n");
88                 gpio_set_value(pdata->bp_reset, GPIO_LOW);
89                 msleep(100);
90                 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
91                 gpio_set_value(pdata->bp_power, GPIO_HIGH);
92                 msleep(1000);
93                 gpio_set_value(pdata->bp_power, GPIO_LOW);
94                 msleep(700);
95                 gpio_set_value(pdata->bp_power, GPIO_HIGH);
96         }
97         else
98         {
99                 MODEMDBG("------------modem_poweroff\n");
100                 gpio_set_value(pdata->bp_power, GPIO_LOW);
101                 gpio_set_value(pdata->bp_power, GPIO_HIGH);
102                 msleep(2500);
103                 gpio_set_value(pdata->bp_power, GPIO_LOW);
104         }
105         mutex_unlock(&pdata->bp_mutex);
106         return 0;
107 }
108 static int mi700_open(struct inode *inode, struct file *file)
109 {
110         //MODEMDBG("-------------%s\n",__FUNCTION__);
111         struct rk29_mi700_data *pdata = gpdata;
112 //      struct platform_data *pdev = container_of(pdata, struct device, platform_data);
113         device_init_wakeup(pdata->dev, 1);
114         return 0;
115 }
116
117 static int mi700_release(struct inode *inode, struct file *file)
118 {
119         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
120         //modem_poweron_off(0);
121         return 0;
122 }
123
124 static long mi700_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
125 {
126         struct rk29_mi700_data *pdata = gpdata;
127         switch(cmd)
128         {
129                 case MI700_RESET:                                       
130                         gpio_set_value(pdata->bp_reset, GPIO_LOW);
131                         msleep(100);
132                         gpio_set_value(pdata->bp_reset, GPIO_HIGH);
133                         msleep(100);
134                         gpio_set_value(pdata->bp_power, GPIO_HIGH);
135                         msleep(1000);
136                         gpio_set_value(pdata->bp_power, GPIO_LOW);
137                         msleep(700);
138                         gpio_set_value(pdata->bp_power, GPIO_HIGH);
139                         break;
140                 default:
141                         break;
142         }
143         return 0;
144 }
145
146 static struct file_operations mi700_fops = {
147         .owner = THIS_MODULE,
148         .open = mi700_open,
149         .release = mi700_release,
150         .unlocked_ioctl = mi700_ioctl
151 };
152
153 static struct miscdevice mi700_misc = {
154         .minor = MISC_DYNAMIC_MINOR,
155         .name = "mi700",
156         .fops = &mi700_fops
157 };
158 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
159 static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
160 #else
161 static ssize_t modem_status_read(struct class *cls, char *_buf)
162 #endif
163 {
164
165         return sprintf(_buf, "%d\n", modem_status);
166         
167 }
168 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
169 static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
170 #else
171 static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
172 #endif
173 {
174       int new_state = simple_strtoul(_buf, NULL, 16);
175       if(new_state == modem_status) 
176             return _count;
177    
178       if (new_state == 1){
179               printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);
180               modem_poweron_off(1);
181       }else if(new_state == 0){
182               printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);
183               modem_poweron_off(0);
184       }else{
185               printk("%s, invalid parameter \n", __FUNCTION__);
186       }
187         
188       modem_status = new_state;
189       return _count; 
190 }
191 static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
192 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
193 static ssize_t online_read(struct class *cls, struct class_attribute *attr, char *_buf)
194 #else
195 static ssize_t online_read(struct class *cls, char *_buf)
196 #endif
197 {
198         return sprintf(_buf, "%d\n", online);
199         
200 }
201 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
202 static ssize_t online_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
203 #else
204 static ssize_t online_write(struct class *cls, const char *_buf, size_t _count)
205 #endif
206 {
207    int new_value = simple_strtoul(_buf, NULL, 16);
208    if(new_value == online) return _count;
209         online = new_value;
210     return _count; 
211 }
212 static CLASS_ATTR(online, 0777, online_read, online_write);
213 static int mi700_probe(struct platform_device *pdev)
214 {
215         struct rk29_mi700_data *pdata = gpdata = pdev->dev.platform_data;
216         struct modem_dev *mi700_data = NULL;
217         int result, irq = 0;    
218         MODEMDBG("-------------%s\n",__FUNCTION__);
219         
220         pdata->dev = &pdev->dev;
221         if(pdata->io_init)
222                 pdata->io_init();
223         
224         mi700_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
225         if(mi700_data == NULL)
226         {
227                 printk("failed to request mi700_data\n");
228                 goto err2;
229         }
230         platform_set_drvdata(pdev, mi700_data);
231         #if 0
232         result = gpio_request(pdata->ap_wakeup_bp, "mi700");
233         if (result) {
234                 printk("failed to request AP_BP_WAKEUP gpio\n");
235                 goto err1;
236         }
237         #endif
238         irq     = gpio_to_irq(pdata->bp_wakeup_ap);
239         enable_irq_wake(irq);
240         if(irq < 0)
241         {
242                 gpio_free(pdata->bp_wakeup_ap);
243                 printk("failed to request bp_wakeup_ap\n");
244         }
245         result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
246         if (result < 0) {
247                 printk("%s: gpio_request(%d) failed\n", __func__, pdata->bp_wakeup_ap);
248         }
249         wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
250         gpio_direction_input(pdata->bp_wakeup_ap);
251         gpio_pull_updown(pdata->bp_wakeup_ap, 1);       
252         result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
253         if (result < 0) {
254                 printk("%s: request_irq(%d) failed\n", __func__, irq);
255                 gpio_free(pdata->bp_wakeup_ap);
256                 goto err0;
257         }
258         enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap)); 
259         
260         mutex_init(&pdata->bp_mutex);
261
262         modem_poweron_off(1);
263         modem_status = 1;
264                 
265         result = misc_register(&mi700_misc);
266         if(result)
267         {
268                 printk("misc_register err\n");
269         }       
270         return result;
271 err0:
272         cancel_work_sync(&mi700_data->work);
273         gpio_free(pdata->bp_wakeup_ap);
274 err1:
275         //gpio_free(pdata->ap_wakeup_bp);
276 err2:
277         kfree(mi700_data);
278         return 0;
279 }
280
281 int mi700_suspend(struct platform_device *pdev)
282 {
283         
284         struct rk29_mi700_data *pdata = pdev->dev.platform_data;
285         do_wakeup_irq = 1;
286         MODEMDBG("%s::%d--\n",__func__,__LINE__);
287         //gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
288         return 0;
289 }
290
291 int mi700_resume(struct platform_device *pdev)
292 {
293         MODEMDBG("-------------%s\n",__FUNCTION__);
294         //ap_wakeup_bp(pdev, 0);
295         //rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
296         return 0;
297 }
298
299 void mi700_shutdown(struct platform_device *pdev, pm_message_t state)
300 {
301         struct rk29_mi700_data *pdata = pdev->dev.platform_data;
302         struct modem_dev *mi700_data = platform_get_drvdata(pdev);
303         
304         MODEMDBG("-------------%s\n",__FUNCTION__);
305         modem_poweron_off(0);
306
307         if(pdata->io_deinit)
308                 pdata->io_deinit();
309         cancel_work_sync(&mi700_data->work);
310         //gpio_free(pdata->bp_power);
311         //gpio_free(pdata->bp_reset);
312         //gpio_free(pdata->ap_wakeup_bp);
313         gpio_free(pdata->bp_wakeup_ap);
314         kfree(mi700_data);
315 }
316
317 static struct platform_driver mi700_driver = {
318         .probe          = mi700_probe,
319         .shutdown       = mi700_shutdown,
320         .suspend        = mi700_suspend,
321         .resume         = mi700_resume,
322         .driver = {
323                 .name   = "MW100",
324                 .owner  = THIS_MODULE,
325         },
326 };
327
328 static int __init mi700_init(void)
329 {
330         MODEMDBG("-------------%s\n",__FUNCTION__);
331         int ret ;
332         
333         modem_class = class_create(THIS_MODULE, "rk291x_modem");
334         ret =  class_create_file(modem_class, &class_attr_modem_status);
335         ret =  class_create_file(modem_class, &class_attr_online);
336         if (ret)
337         {
338                 printk("Fail to class rk291x_modem.\n");
339         }
340         return platform_driver_register(&mi700_driver);
341 }
342
343 static void __exit mi700_exit(void)
344 {
345         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
346         platform_driver_unregister(&mi700_driver);
347         class_remove_file(modem_class, &class_attr_modem_status);
348         class_remove_file(modem_class, &class_attr_online);
349 }
350
351 module_init(mi700_init);
352 module_exit(mi700_exit);