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