mmc: host: rk_sdmmc:
[firefly-linux-kernel-4.4.55.git] / drivers / misc / 3g_module / sew868.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/sew868.h>
22 #include<linux/ioctl.h>
23 #include<linux/slab.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 #define SLEEP 1
34 #define READY 0
35 #define SEW868_RESET 0x01
36 #define SEW868_POWON 0x02
37 #define SEW868_POWOFF 0x03
38 static struct wake_lock modem_wakelock;
39 #define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_FALLING
40 //#define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_RISING
41 struct rk30_sew868_data *gpdata = NULL;
42 static int do_wakeup_irq = 0;
43
44 extern void rk28_send_wakeup_key(void);
45
46 static void do_wakeup(struct work_struct *work)
47 {
48     rk28_send_wakeup_key();
49 }
50
51 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
52 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
53 {
54     printk("%s\n", __FUNCTION__);
55     if(do_wakeup_irq)
56     {
57         do_wakeup_irq = 0;
58         wake_lock_timeout(&modem_wakelock, 10 * HZ);
59         schedule_delayed_work(&wakeup_work, HZ / 10);
60     }
61     return IRQ_HANDLED;
62 }
63 static int modem_poweron_off(int on_off)
64 {
65         struct rk30_sew868_data *pdata = gpdata;                
66   if(on_off)
67   {
68                 gpio_direction_output(pdata->bp_sys, GPIO_HIGH);
69                 gpio_set_value(pdata->bp_power, GPIO_LOW);
70                 msleep(200);//for charge
71                 gpio_set_value(pdata->bp_power, GPIO_HIGH);
72                 msleep(4000);
73                 gpio_set_value(pdata->bp_power, GPIO_LOW);
74                 msleep(200);
75   }
76   else
77   {
78                 gpio_set_value(pdata->bp_power, GPIO_HIGH);
79                 msleep(4000);
80                 gpio_set_value(pdata->bp_power, GPIO_LOW);
81                 gpio_set_value(pdata->bp_sys, GPIO_LOW);
82                 msleep(50);
83                 gpio_set_value(pdata->bp_power, GPIO_LOW);
84   }
85   return 0;
86 }
87 static int sew868_open(struct inode *inode, struct file *file)
88 {
89         return 0;
90 }
91
92 static int sew868_release(struct inode *inode, struct file *file)
93 {
94         return 0;
95 }
96
97 static long sew868_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
98 {
99         struct rk30_sew868_data *pdata = gpdata;
100         switch(cmd)
101         {
102                 case SEW868_RESET:                                      
103                         gpio_set_value(pdata->bp_reset, GPIO_HIGH);
104                         mdelay(100);
105                         gpio_set_value(pdata->bp_reset, GPIO_LOW);
106                         mdelay(200);
107                         modem_poweron_off(1);
108                         break;
109                 case SEW868_POWON:
110                         modem_poweron_off(1);
111                         break;
112                 case SEW868_POWOFF:
113                         modem_poweron_off(0);
114                         break;
115                 default:
116                         break;
117         }
118         return 0;
119 }
120
121 static struct file_operations sew868_fops = {
122         .owner = THIS_MODULE,
123         .open = sew868_open,
124         .release = sew868_release,
125         .unlocked_ioctl = sew868_ioctl
126 };
127
128 static struct miscdevice sew868_misc = {
129         .minor = MISC_DYNAMIC_MINOR,
130         .name = MODEM_NAME,
131         .fops = &sew868_fops
132 };
133
134 static int sew868_probe(struct platform_device *pdev)
135 {
136         struct rk30_sew868_data *pdata = gpdata = pdev->dev.platform_data;
137         struct modem_dev *sew868_data = NULL;
138         int result, irq = 0;    
139         
140         if(pdata->io_init)
141                 pdata->io_init();
142
143         modem_poweron_off(1);
144         sew868_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
145         if(sew868_data == NULL)
146         {
147                 printk("failed to request sew868_data\n");
148                 goto err1;
149         }
150         platform_set_drvdata(pdev, sew868_data);
151         
152         irq = gpio_to_irq(pdata->bp_wakeup_ap);
153         if(irq < 0)
154         {
155                 gpio_free(pdata->bp_wakeup_ap);
156                 printk("failed to request bp_wakeup_ap\n");
157         }
158
159         wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
160         gpio_direction_input(pdata->bp_wakeup_ap);
161         gpio_pull_updown(pdata->bp_wakeup_ap, GPIONormal);      
162         result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
163         if (result < 0) {
164                 printk("%s: request_irq(%d) failed\n", __func__, irq);
165                 gpio_free(pdata->bp_wakeup_ap);
166                 goto err0;
167         }
168         enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap)); 
169         result = misc_register(&sew868_misc);
170         if(result)
171         {
172                 MODEMDBG("misc_register err\n");
173         }       
174
175         return result;
176 err0:
177         cancel_work_sync(&sew868_data->work);
178 err1:
179         kfree(sew868_data);
180         return 0;
181 }
182
183 static int sew868_suspend(struct platform_device *pdev, pm_message_t state)
184 {
185         do_wakeup_irq = 1;
186         return 0;
187 }
188
189 static int sew868_resume(struct platform_device *pdev)
190 {
191         return 0;
192 }
193
194 static void sew868_shutdown(struct platform_device *pdev)
195 {
196         struct rk30_sew868_data *pdata = pdev->dev.platform_data;
197         struct modem_dev *sew868_data = platform_get_drvdata(pdev);
198         modem_poweron_off(0);
199         if(pdata->io_deinit)
200                 pdata->io_deinit();
201         cancel_work_sync(&sew868_data->work);
202         kfree(sew868_data);
203 }
204
205 static struct platform_driver sew868_driver = {
206         .probe  = sew868_probe,
207         .shutdown       = sew868_shutdown,
208         .suspend        = sew868_suspend,
209         .resume         = sew868_resume,
210         .driver = {
211                 .name   = "sew868",
212                 .owner  = THIS_MODULE,
213         },
214 };
215
216 static int __init sew868_init(void)
217 {
218         return platform_driver_register(&sew868_driver);
219 }
220
221 static void __exit sew868_exit(void)
222 {
223         platform_driver_unregister(&sew868_driver);
224 }
225
226 module_init(sew868_init);
227
228 module_exit(sew868_exit);