Merge remote-tracking branch 'origin/develop-3.0' into develop-3.0-jb
[firefly-linux-kernel-4.4.55.git] / drivers / misc / 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 //#define DEBUG
30 #ifdef DEBUG
31 #define MODEMDBG(x...) printk(x)
32 #else
33 #define MODEMDBG(fmt,argss...)
34 #endif
35
36 #define         MW100IO 0XA1
37 #define MW_IOCTL_RESET  _IO(MW100IO,0X01)
38
39 #define SLEEP 1
40 #define READY 0
41 #define MW100_RESET 0x01
42 #define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_RISING
43 //#define IRQ_BB_WAKEUP_AP_TRIGGER    IRQF_TRIGGER_RISING
44 struct rk29_mw100_data *gpdata = NULL;
45 static int  bp_wakeup_ap_irq = 0;
46
47 static struct wake_lock bp_wakelock;
48 static bool bpstatus_irq_enable = false;
49
50 #if 0
51 static void ap_wakeup_bp(struct platform_device *pdev, int wake)
52 {
53         struct rk29_mw100_data *pdata = pdev->dev.platform_data;
54         MODEMDBG("ap_wakeup_bp\n");
55
56         gpio_set_value(pdata->ap_wakeup_bp, wake);  
57 }
58 #endif
59
60 static void do_wakeup(struct work_struct *work)
61 {
62     MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
63     enable_irq(bp_wakeup_ap_irq);
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         printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
70       wake_lock_timeout(&bp_wakelock, 10 * HZ);
71    
72     return IRQ_HANDLED;
73 }
74 int modem_poweron_off(int on_off)
75 {
76   if(on_off)
77   {
78         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
79   }
80   else
81   {
82         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
83   }
84   return 0;
85 }
86
87 static int mw100_open(struct inode *inode, struct file *file)
88 {
89         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
90         //modem_poweron_off(1);
91         return 0;
92 }
93
94 static int mw100_release(struct inode *inode, struct file *file)
95 {
96         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
97         //modem_poweron_off(0);
98         return 0;
99 }
100
101 static long mw100_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
102 {
103         struct rk29_mw100_data *pdata = gpdata;
104         switch(cmd)
105         {
106                 case MW_IOCTL_RESET:                    
107                 printk("%s::%d--bruins--ioctl  mw100 reset\n",__func__,__LINE__);
108                 gpio_direction_output(pdata->bp_reset,GPIO_LOW);
109                 mdelay(120);
110                 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
111                 
112                         break;
113                 default:
114                         break;
115         }
116         return 0;
117 }
118
119 static struct file_operations mw100_fops = {
120         .owner = THIS_MODULE,
121         .open = mw100_open,
122         .release = mw100_release,
123         .unlocked_ioctl = mw100_ioctl
124 };
125
126 static struct miscdevice mw100_misc = {
127         .minor = MISC_DYNAMIC_MINOR,
128         .name = "mw100",
129         .fops = &mw100_fops
130 };
131
132 static int mw100_probe(struct platform_device *pdev)
133 {
134         struct rk29_mw100_data *pdata = gpdata = pdev->dev.platform_data;
135         struct modem_dev *mw100_data = NULL;
136         int result, irq = 0;    
137
138         gpio_request(pdata->bp_power,"bp_power");
139         gpio_request(pdata->bp_reset,"bp_reset");
140         gpio_request(pdata->bp_wakeup_ap,"bp_wakeup_ap");
141         gpio_request(pdata->ap_wakeup_bp,"ap_wakeup_bp");
142         gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
143         msleep(1000);
144 #if defined(CONFIG_ARCH_RK29)   
145         rk29_mux_api_set(GPIO6C76_CPUTRACEDATA76_NAME, GPIO4H_GPIO6C76);
146 #endif
147         gpio_direction_output(pdata->bp_reset,GPIO_LOW);
148         mdelay(120);
149         gpio_set_value(pdata->bp_reset, GPIO_HIGH);
150         
151         gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
152         gpio_direction_output(pdata->ap_wakeup_bp,GPIO_HIGH);   
153         
154         gpio_set_value(pdata->bp_power, GPIO_HIGH);
155         gpio_direction_output(pdata->bp_power,GPIO_HIGH);       
156         mdelay(120);
157         gpio_set_value(pdata->bp_power, GPIO_LOW);
158         gpio_direction_output(pdata->bp_power,GPIO_LOW);        
159         
160         
161         //±£Áô
162 /*      gpio_set_value(pdata->bp_reset, GPIO_LOW);
163         gpio_direction_output(pdata->bp_reset,GPIO_LOW);
164         mdelay(120);
165         gpio_set_value(pdata->bp_reset, GPIO_HIGH);
166         gpio_direction_output(pdata->bp_reset,GPIO_HIGH);
167 */
168         mw100_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
169         if(mw100_data == NULL){
170                 printk("failed to request mw100_data\n");
171                 goto err2;
172         }
173         platform_set_drvdata(pdev, mw100_data); 
174         
175         gpio_direction_input(pdata->bp_wakeup_ap);
176         irq     = gpio_to_irq(pdata->bp_wakeup_ap);
177         if(irq < 0){
178                 gpio_free(pdata->bp_wakeup_ap);
179                 printk("failed to request bp_wakeup_ap\n");
180         }
181         
182         bp_wakeup_ap_irq = irq;
183         
184         result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
185         if (result < 0) {
186                 printk("%s: request_irq(%d) failed\n", __func__, irq);
187                 gpio_free(pdata->bp_wakeup_ap);
188                 goto err0;
189         }
190
191         enable_irq_wake(bp_wakeup_ap_irq); 
192
193         wake_lock_init(&bp_wakelock, WAKE_LOCK_SUSPEND, "bp_resume");
194
195         result = misc_register(&mw100_misc);
196         if(result){
197                 MODEMDBG("misc_register err\n");
198         }       
199         return result;
200 err0:
201         gpio_free(pdata->bp_wakeup_ap);
202 err2:
203         kfree(mw100_data);
204         return 0;
205 }
206
207 int mw100_suspend(struct platform_device *pdev, pm_message_t state)
208 {
209         
210         struct rk29_mw100_data *pdata = pdev->dev.platform_data;
211         int irq;
212         MODEMDBG("%s::%d--\n",__func__,__LINE__);
213         gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
214         irq = gpio_to_irq(pdata->bp_wakeup_ap);
215         if (irq < 0) {
216                 printk("can't get pdata->bp_statue irq \n");
217         }
218         else
219         {
220                 printk("enable pdata->bp_statue irq_wake!! \n");
221                 bpstatus_irq_enable = true;
222                 enable_irq_wake(irq);
223         }
224         return 0;
225 }
226
227 int mw100_resume(struct platform_device *pdev)
228 {
229         struct rk29_mw100_data *pdata = pdev->dev.platform_data;
230         int irq;
231         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
232         gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH); 
233                 irq = gpio_to_irq(pdata->bp_wakeup_ap);
234         if (irq ) {
235                 printk("enable pdata->bp_statue irq_wake!! \n");
236                 disable_irq_wake(irq);
237                 bpstatus_irq_enable = false;
238         }
239         return 0;
240 }
241
242 void mw100_shutdown(struct platform_device *pdev)
243 {
244         struct rk29_mw100_data *pdata = pdev->dev.platform_data;
245         struct modem_dev *mw100_data = platform_get_drvdata(pdev);
246         
247         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
248         gpio_set_value(pdata->bp_power, GPIO_HIGH);
249         mdelay(2010);
250         gpio_free(pdata->modem_power_en);
251         gpio_free(pdata->bp_power);
252         gpio_free(pdata->bp_reset);
253         gpio_free(pdata->ap_wakeup_bp);
254         gpio_free(pdata->bp_wakeup_ap);
255         kfree(mw100_data);
256 }
257
258 static struct platform_driver mw100_driver = {
259         .probe  = mw100_probe,
260         .shutdown       = mw100_shutdown,
261         .suspend        = mw100_suspend,
262         .resume         = mw100_resume,
263         .driver = {
264                 .name   = "mw100",
265                 .owner  = THIS_MODULE,
266         },
267 };
268
269 static int __init mw100_init(void)
270 {
271         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
272         return platform_driver_register(&mw100_driver);
273 }
274
275 static void __exit mw100_exit(void)
276 {
277         MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
278         platform_driver_unregister(&mw100_driver);
279 }
280
281 module_init(mw100_init);
282
283 module_exit(mw100_exit);