Merge remote-tracking branch 'stable/linux-3.0.y' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / misc / 3g_module / sc6610.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/sc6610.h>
23
24 #include <linux/slab.h>
25 #include <linux/earlysuspend.h>
26
27 MODULE_LICENSE("GPL");
28
29 #define DEBUG 1
30 #ifdef DEBUG
31 #define MODEMDBG(x...) printk(x)
32 #else
33 #define MODEMDBG(fmt,argss...)
34 #endif
35 #define MODEM_RESET 2   
36 #define MODEM_ON 1
37 #define MODEM_OFF 0
38 struct rk29_sc6610_data *s_gpdata = NULL;
39
40 struct class *modem_class = NULL; 
41 static int do_wakeup_irq = 0;
42 static struct wake_lock modem_wakelock;
43 //#define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_FALLING
44 #define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_RISING
45 int modem_poweron_off(int on_off)
46 {
47         struct rk29_sc6610_data *pdata = s_gpdata;              
48         if(on_off){     
49                 gpio_set_value(pdata->bp_power, GPIO_HIGH);             
50                 
51         }else{
52                 gpio_set_value(pdata->bp_power, GPIO_LOW);              
53         }
54         return 0;
55 }
56
57 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
58 {
59     if(do_wakeup_irq)
60     {
61         do_wakeup_irq = 0;
62         
63         wake_lock_timeout(&modem_wakelock, 10 * HZ);
64     }
65     return IRQ_HANDLED;
66 }
67 static int sc6610_open(struct inode *inode, struct file *file)
68 {
69         return 0;
70 }
71
72 static int sc6610_release(struct inode *inode, struct file *file)
73 {
74         return 0;
75 }
76
77 static long sc6610_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
78 {
79         struct rk29_sc6610_data *pdata = s_gpdata;
80         switch(cmd)
81         {
82                 case MODEM_RESET:                                       
83                         gpio_set_value(pdata->bp_reset, GPIO_LOW);
84                         msleep(2000);
85                         gpio_set_value(pdata->bp_reset, GPIO_HIGH);                     
86                         break;
87                 case MODEM_ON:  
88                         modem_poweron_off(MODEM_ON);
89                         break;
90                 case MODEM_OFF: 
91                         modem_poweron_off(MODEM_OFF);
92                         break;
93                 default:
94                         break;
95         }
96         return 0;
97 }
98
99 static struct file_operations sc6610_fops = {
100         .owner = THIS_MODULE,
101         .open = sc6610_open,
102         .release = sc6610_release,
103         .unlocked_ioctl = sc6610_ioctl
104 };
105
106 static struct miscdevice sc6610_misc = {
107         .minor = MISC_DYNAMIC_MINOR,
108         .name = MODEM_NAME,
109         .fops = &sc6610_fops
110 };
111
112 static int sc6610_probe(struct platform_device *pdev)
113 {
114         struct rk29_sc6610_data *pdata = s_gpdata = pdev->dev.platform_data;
115         struct modem_dev *sc6610_data = NULL;
116         int result;     
117         int irq;
118         pdata->dev = &pdev->dev;
119
120         if(pdata->io_init)
121                 pdata->io_init();       
122         result = gpio_request(pdata->ap_wakeup_bp, "ap_wakeup_bp");
123         if (result) {
124                 printk("failed to request ap_wakeup_bp gpio\n");
125                 goto err0;
126         }
127         result = gpio_request(pdata->bp_power, "bp_power");
128         if (result) {
129                 printk("failed to request bp_power gpio\n");
130                 goto err1;
131         }       
132         result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
133         if (result) {
134                 printk("failed to request bp_wakeup_ap gpio\n");
135                 goto err2;
136         }
137                 
138         gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
139         
140         irq = gpio_to_irq(pdata->bp_wakeup_ap);
141         
142         result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
143         if (result < 0) {
144                 printk("%s: request_irq(%d) failed\n", __func__, irq);
145                 goto err2;
146         }
147         enable_irq_wake(irq); 
148         wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
149         sc6610_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
150         if(sc6610_data == NULL)
151         {
152                 printk("failed to request sc6610_data\n");
153                 goto err3;
154         }
155         platform_set_drvdata(pdev, sc6610_data);                
156         result = misc_register(&sc6610_misc);
157         if(result)
158         {
159                 printk("misc_register err\n");
160         }
161         modem_poweron_off(MODEM_ON);
162         return result;
163
164 err0:
165         gpio_free(pdata->ap_wakeup_bp);
166 err1:
167         gpio_free(pdata->bp_power);
168 err2:
169         gpio_free(pdata->bp_wakeup_ap);
170 err3:
171         kfree(sc6610_data);
172         return 0;
173 }
174
175 int c6610_suspend(struct platform_device *pdev, pm_message_t state)
176 {
177         struct rk29_sc6610_data *pdata = s_gpdata = pdev->dev.platform_data;
178         pdata->dev = &pdev->dev;
179         do_wakeup_irq = 1;
180         gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
181         return 0;
182 }
183
184 int c6610_resume(struct platform_device *pdev)
185 {
186         struct rk29_sc6610_data *pdata = s_gpdata = pdev->dev.platform_data;
187         pdata->dev = &pdev->dev;
188         gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
189         return 0;
190 }
191
192 void c6610_shutdown(struct platform_device *pdev)
193 {
194         struct rk29_sc6610_data *pdata = pdev->dev.platform_data;
195         struct modem_dev *sc6610_data = platform_get_drvdata(pdev);
196         modem_poweron_off(MODEM_OFF);
197         if(pdata->io_deinit)
198                 pdata->io_deinit();
199         cancel_work_sync(&sc6610_data->work);   
200         gpio_free(pdata->bp_power);
201         gpio_free(pdata->ap_wakeup_bp);
202         gpio_free(pdata->bp_wakeup_ap);
203         kfree(sc6610_data);
204 }
205
206 static struct platform_driver sc6610_driver = {
207         .probe  = sc6610_probe,
208         .shutdown       = c6610_shutdown,
209         .suspend        = c6610_suspend,
210         .resume         = c6610_resume,
211         .driver = {
212                 .name   = "SC6610",
213                 .owner  = THIS_MODULE,
214         },
215 };
216
217 static int __init sc6610_init(void)
218 {
219         
220         return platform_driver_register(&sc6610_driver);
221 }
222
223 static void __exit sc6610_exit(void)
224 {
225         platform_driver_unregister(&sc6610_driver);
226         
227 }
228
229 module_init(sc6610_init);
230
231 module_exit(sc6610_exit);