UPSTREAM: PCI: rockchip: cleanup bit definition for PCIE_RC_CONFIG_LCS
[firefly-linux-kernel-4.4.55.git] / drivers / misc / 3g_module / mw100.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/mw100.h>
22 #include <mach/iomux.h>
23 #include<linux/ioctl.h>
24
25 #include <linux/slab.h>
26    
27 MODULE_LICENSE("GPL");
28
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 MW100_RESET 0x01
41 #define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_RISING
42 //#define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_RISING
43 struct rk29_mw100_data *gpdata = NULL;
44 static int  bp_wakeup_ap_irq = 0;
45
46 static struct wake_lock bp_wakelock;
47 static bool bpstatus_irq_enable = false;
48
49 static void do_wakeup(struct work_struct *work)
50 {
51     enable_irq(bp_wakeup_ap_irq);
52 }
53
54 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
55 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
56 {
57       wake_lock_timeout(&bp_wakelock, 10 * HZ);
58    
59     return IRQ_HANDLED;
60 }
61
62 static int mw100_open(struct inode *inode, struct file *file)
63 {
64         return 0;
65 }
66
67 static int mw100_release(struct inode *inode, struct file *file)
68 {
69         return 0;
70 }
71
72 static long mw100_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
73 {
74         struct rk29_mw100_data *pdata = gpdata;
75         switch(cmd)
76         {
77                 case MW_IOCTL_RESET:                    
78                 gpio_direction_output(pdata->bp_reset,GPIO_LOW);
79                 mdelay(120);
80                 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
81                 
82                         break;
83                 default:
84                         break;
85         }
86         return 0;
87 }
88
89 static struct file_operations mw100_fops = {
90         .owner = THIS_MODULE,
91         .open = mw100_open,
92         .release = mw100_release,
93         .unlocked_ioctl = mw100_ioctl
94 };
95
96 static struct miscdevice mw100_misc = {
97         .minor = MISC_DYNAMIC_MINOR,
98         .name = "mw100",
99         .fops = &mw100_fops
100 };
101
102 static int mw100_probe(struct platform_device *pdev)
103 {
104         struct rk29_mw100_data *pdata = gpdata = pdev->dev.platform_data;
105         struct modem_dev *mw100_data = NULL;
106         int result, irq = 0;    
107
108         gpio_request(pdata->bp_power,"bp_power");
109         gpio_request(pdata->bp_reset,"bp_reset");
110         gpio_request(pdata->bp_wakeup_ap,"bp_wakeup_ap");
111         gpio_request(pdata->ap_wakeup_bp,"ap_wakeup_bp");
112         gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
113         msleep(1000);
114         gpio_direction_output(pdata->bp_reset,GPIO_LOW);
115         mdelay(120);
116         gpio_set_value(pdata->bp_reset, GPIO_HIGH);
117         
118         gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
119         gpio_direction_output(pdata->ap_wakeup_bp,GPIO_HIGH);   
120         
121         gpio_set_value(pdata->bp_power, GPIO_HIGH);
122         gpio_direction_output(pdata->bp_power,GPIO_HIGH);       
123         mdelay(120);
124         gpio_set_value(pdata->bp_power, GPIO_LOW);
125         gpio_direction_output(pdata->bp_power,GPIO_LOW);        
126         
127         mw100_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
128         if(mw100_data == NULL){
129                 printk("failed to request mw100_data\n");
130                 goto err2;
131         }
132         platform_set_drvdata(pdev, mw100_data); 
133         
134         gpio_direction_input(pdata->bp_wakeup_ap);
135         irq     = gpio_to_irq(pdata->bp_wakeup_ap);
136         if(irq < 0){
137                 gpio_free(pdata->bp_wakeup_ap);
138                 printk("failed to request bp_wakeup_ap\n");
139         }
140         
141         bp_wakeup_ap_irq = irq;
142         
143         result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
144         if (result < 0) {
145                 printk("%s: request_irq(%d) failed\n", __func__, irq);
146                 gpio_free(pdata->bp_wakeup_ap);
147                 goto err0;
148         }
149
150         enable_irq_wake(bp_wakeup_ap_irq); 
151
152         wake_lock_init(&bp_wakelock, WAKE_LOCK_SUSPEND, "bp_resume");
153
154         result = misc_register(&mw100_misc);
155         if(result){
156                 MODEMDBG("misc_register err\n");
157         }       
158         return result;
159 err0:
160         gpio_free(pdata->bp_wakeup_ap);
161 err2:
162         kfree(mw100_data);
163         return 0;
164 }
165
166 static int mw100_suspend(struct platform_device *pdev, pm_message_t state)
167 {
168         
169         struct rk29_mw100_data *pdata = pdev->dev.platform_data;
170         int irq;
171         gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
172         irq = gpio_to_irq(pdata->bp_wakeup_ap);
173         if (irq < 0) {
174                 printk("can't get pdata->bp_statue irq \n");
175         }
176         else
177         {
178                 bpstatus_irq_enable = true;
179                 enable_irq_wake(irq);
180         }
181         return 0;
182 }
183
184 static int mw100_resume(struct platform_device *pdev)
185 {
186         struct rk29_mw100_data *pdata = pdev->dev.platform_data;
187         int irq;
188         gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH); 
189                 irq = gpio_to_irq(pdata->bp_wakeup_ap);
190         if (irq ) {
191                 disable_irq_wake(irq);
192                 bpstatus_irq_enable = false;
193         }
194         return 0;
195 }
196
197 static void mw100_shutdown(struct platform_device *pdev)
198 {
199         struct rk29_mw100_data *pdata = pdev->dev.platform_data;
200         struct modem_dev *mw100_data = platform_get_drvdata(pdev);
201         
202         gpio_set_value(pdata->bp_power, GPIO_HIGH);
203         mdelay(2010);
204         gpio_free(pdata->modem_power_en);
205         gpio_free(pdata->bp_power);
206         gpio_free(pdata->bp_reset);
207         gpio_free(pdata->ap_wakeup_bp);
208         gpio_free(pdata->bp_wakeup_ap);
209         kfree(mw100_data);
210 }
211
212 static struct platform_driver mw100_driver = {
213         .probe  = mw100_probe,
214         .shutdown       = mw100_shutdown,
215         .suspend        = mw100_suspend,
216         .resume         = mw100_resume,
217         .driver = {
218                 .name   = "mw100",
219                 .owner  = THIS_MODULE,
220         },
221 };
222
223 static int __init mw100_init(void)
224 {
225         return platform_driver_register(&mw100_driver);
226 }
227
228 static void __exit mw100_exit(void)
229 {
230         platform_driver_unregister(&mw100_driver);
231 }
232
233 module_init(mw100_init);
234
235 module_exit(mw100_exit);