UPSTREAM: PCI: rockchip: cleanup bit definition for PCIE_RC_CONFIG_LCS
[firefly-linux-kernel-4.4.55.git] / drivers / misc / 3g_module / mt6229.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/mt6229.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 MT6229_RESET 0x01
40 struct rk29_mt6229_data *gpdata = NULL;
41 struct class *modem_class = NULL; 
42 static int do_wakeup_irq = 0;
43 static int modem_status;
44 static void ap_wakeup_bp(struct platform_device *pdev, int wake)
45 {
46         struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
47  
48           gpio_set_value(pdata->modem_usb_en,wake);
49           if(wake == 1)
50                   wake = 0;
51           else
52                   wake = 1;
53           gpio_set_value(pdata->modem_uart_en,wake);
54
55 }
56 extern void rk28_send_wakeup_key(void);
57
58 static void do_wakeup(struct work_struct *work)
59 {
60                 gpio_set_value(gpdata->ap_ready,GPIO_HIGH);
61                 gpio_set_value(gpdata->modem_usb_en,GPIO_HIGH);
62 }
63
64 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
65 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
66 {
67     if(do_wakeup_irq)
68     {
69         do_wakeup_irq = 0;
70         wake_lock_timeout(&modem_wakelock, 10 * HZ);
71         //schedule_delayed_work(&wakeup_work, 2*HZ);
72     }
73     return IRQ_HANDLED;
74 }
75 static int modem_poweron_off(int on_off)
76 {
77         struct rk29_mt6229_data *pdata = gpdata;                
78   if(on_off)
79   {
80                 gpio_set_value(pdata->bp_power, GPIO_LOW);
81                 gpio_set_value(pdata->modem_usb_en, GPIO_HIGH);
82                 gpio_set_value(pdata->modem_uart_en, GPIO_LOW);
83                 gpio_set_value(pdata->ap_ready, GPIO_HIGH);
84   }
85   else
86   {
87                 gpio_set_value(pdata->bp_power, GPIO_HIGH);
88                 gpio_set_value(pdata->modem_usb_en, GPIO_LOW);
89                 gpio_set_value(pdata->modem_uart_en, GPIO_HIGH);
90                 gpio_set_value(pdata->ap_ready, GPIO_LOW);
91   }
92   return 0;
93 }
94 static int mt6229_open(struct inode *inode, struct file *file)
95 {
96         struct rk29_mt6229_data *pdata = gpdata;
97         device_init_wakeup(pdata->dev, 1);
98         return 0;
99 }
100 static ssize_t mt6229_write(struct file *file, const char __user *buf,size_t len, loff_t *off)
101 {
102         static char cmd[2];
103         int ret = 0;
104         if (len > 2) 
105         {
106                 return -EINVAL;
107         }
108         ret = copy_from_user(&cmd, buf, len);
109         if (ret != 0) {
110                 return -EFAULT;
111         }
112         printk(" received cmd = %c\n",cmd[0]);
113         if (cmd[0] == '0')
114         {
115                 gpio_set_value(gpdata->ap_ready, GPIO_LOW);
116         }       
117         if (cmd[0] == '1')
118         {
119                 gpio_set_value(gpdata->ap_ready, GPIO_HIGH);
120         }
121         if (cmd[0] == '2')
122         {
123                 gpio_set_value(gpdata->modem_uart_en, GPIO_LOW);
124         }
125         if (cmd[0] == '3')
126         {
127                 gpio_set_value(gpdata->modem_uart_en, GPIO_HIGH);
128         }
129         if (cmd[0] == '4')
130         {
131                 gpio_set_value(gpdata->modem_usb_en, GPIO_HIGH);
132         }if (cmd[0] == '5')
133         {
134                 gpio_set_value(gpdata->modem_usb_en, GPIO_LOW);
135         }
136         return len;
137 }
138 static int mt6229_release(struct inode *inode, struct file *file)
139 {
140         return 0;
141 }
142
143 static long mt6229_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
144 {
145         struct rk29_mt6229_data *pdata = gpdata;
146         switch(cmd)
147         {
148                 case MT6229_RESET:                                      
149                         modem_poweron_off(0);
150                         msleep(10);
151                         modem_poweron_off(1);
152                         break;
153                 default:
154                         break;
155         }
156         return 0;
157 }
158
159 static struct file_operations mt6229_fops = {
160         .owner = THIS_MODULE,
161         .open = mt6229_open,
162         .write = mt6229_write,
163         .release = mt6229_release,
164         .unlocked_ioctl = mt6229_ioctl
165 };
166
167 static struct miscdevice mt6229_misc = {
168         .minor = MISC_DYNAMIC_MINOR,
169         .name = MODEM_NAME,
170         .fops = &mt6229_fops
171 };
172 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
173 static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
174 #else
175 static ssize_t modem_status_read(struct class *cls, char *_buf)
176 #endif
177 {
178
179         return sprintf(_buf, "%d\n", modem_status);
180         
181 }
182 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
183 static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
184 #else
185 static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
186 #endif
187 {
188     int new_state = simple_strtoul(_buf, NULL, 16);
189    if(new_state == modem_status) return _count;
190    if (new_state == 1){
191     // printk("%s, c(%d), modem resume \n", __FUNCTION__, new_state);
192     // gpio_set_value(gpdata->modem_usb_en, GPIO_HIGH);
193     // gpio_set_value(gpdata->modem_uart_en,GPIO_LOW);
194          printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);   
195          modem_poweron_off(1);
196    }else if(new_state == 0){
197     // printk("%s, c(%d), modem suspend \n", __FUNCTION__, new_state);
198     // gpio_set_value(gpdata->modem_usb_en, GPIO_LOW);
199     // gpio_set_value(gpdata->modem_uart_en,GPIO_HIGH);
200          printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);  
201           modem_poweron_off(0);
202    }else{
203      printk("%s, invalid parameter \n", __FUNCTION__);
204    }
205         modem_status = new_state;
206     return _count; 
207 }
208 static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
209 static int mt6229_probe(struct platform_device *pdev)
210 {
211         struct rk29_mt6229_data *pdata = gpdata = pdev->dev.platform_data;
212         struct modem_dev *mt6229_data = NULL;
213         int result, irq = 0;    
214         pdata->dev = &pdev->dev;
215         if(pdata->io_init)
216                 pdata->io_init();
217         mt6229_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
218         if(mt6229_data == NULL)
219         {
220                 printk("failed to request mt6229_data\n");
221                 goto err0;
222         }
223         platform_set_drvdata(pdev, mt6229_data);        
224         result = gpio_request(pdata->modem_power_en,"modem_power_en");
225         if(result){
226                         printk("failed to request modem_power_en gpio\n");
227                         goto err1;
228                 }
229         gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
230         msleep(1000);
231   result = gpio_request(pdata->bp_power,"modem_power");
232   if(result){
233                 printk("failed to request modem_power gpio\n");
234                         goto err2;
235         }
236   result = gpio_request(pdata->modem_usb_en, "modem_usb_en");
237         if (result) {
238                 printk("failed to request modem_usb_en gpio\n");
239                 goto err3;
240         }       
241         result = gpio_request(pdata->modem_uart_en,"modem_uart_en");
242         if(result){
243                         printk("failed to request modem_uart_en gpio\n");
244                         goto err4;
245         }
246         result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
247         if (result) {
248                         printk("failed to request bp_wakeup_ap gpio\n");
249                         goto err5;
250         }
251         gpio_direction_input(pdata->bp_wakeup_ap);
252         irq     = gpio_to_irq(pdata->bp_wakeup_ap);
253         if(irq < 0)
254         {
255                 gpio_free(pdata->bp_wakeup_ap);
256                 printk("failed to request bp_wakeup_ap\n");
257         }
258         result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
259         if (result < 0) {
260                 printk("%s: request_irq(%d) failed\n", __func__, irq);
261                 gpio_free(pdata->bp_wakeup_ap);
262                 goto err5;
263         }
264         enable_irq_wake(irq);
265         wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
266         result = gpio_request(pdata->ap_ready, "ap_ready");
267         if (result < 0) {
268                 printk("failed to request ap_ready gpio\n");    
269                 goto err6;
270         }
271
272         modem_poweron_off(1);
273         modem_status = 1;
274          
275         result = misc_register(&mt6229_misc);
276         if(result)
277         {
278                 printk("misc_register err\n");
279         }       
280         return result;
281 err0:
282         kfree(mt6229_data);
283 err1:
284         gpio_free(pdata->modem_power_en);
285 err2:
286         gpio_free(pdata->bp_power);
287 err3:
288         gpio_free(pdata->modem_usb_en);
289 err4:
290         gpio_free(pdata->modem_uart_en);
291 err5:
292         gpio_free(pdata->bp_wakeup_ap);
293 err6:
294         gpio_free(pdata->ap_ready);
295         return 0;
296 }
297
298 static int mt6229_suspend(struct platform_device *pdev, pm_message_t state)
299 {
300         do_wakeup_irq = 1;
301         ap_wakeup_bp(pdev, 0);
302         gpio_set_value(gpdata->ap_ready,0);
303         return 0;
304 }
305
306 static int mt6229_resume(struct platform_device *pdev)
307 {
308         gpio_set_value(gpdata->modem_uart_en,GPIO_LOW);
309         schedule_delayed_work(&wakeup_work, 2*HZ);
310         return 0;
311 }
312
313 static void mt6229_shutdown(struct platform_device *pdev)
314 {
315         struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
316         struct modem_dev *mt6229_data = platform_get_drvdata(pdev);
317         
318         modem_poweron_off(0);
319         gpio_set_value(pdata->modem_power_en, GPIO_LOW);
320
321         if(pdata->io_deinit)
322                 pdata->io_deinit();
323         cancel_work_sync(&mt6229_data->work);
324         gpio_free(pdata->modem_power_en);
325         gpio_free(pdata->bp_power);
326         gpio_free(pdata->modem_usb_en);
327         gpio_free(pdata->modem_uart_en);
328         gpio_free(pdata->bp_wakeup_ap);
329         kfree(mt6229_data);
330 }
331
332 static struct platform_driver mt6229_driver = {
333         .probe  = mt6229_probe,
334         .shutdown       = mt6229_shutdown,
335         .suspend        = mt6229_suspend,
336         .resume         = mt6229_resume,
337         .driver = {
338                 .name   = "mt6229",
339                 .owner  = THIS_MODULE,
340         },
341 };
342
343 static int __init mt6229_init(void)
344 {
345         int ret ;
346         modem_class = class_create(THIS_MODULE, "rk291x_modem");
347         ret =  class_create_file(modem_class, &class_attr_modem_status);
348         if (ret)
349         {
350                 printk("Fail to class rk291x_modem.\n");
351         }
352         return platform_driver_register(&mt6229_driver);
353 }
354
355 static void __exit mt6229_exit(void)
356 {
357         platform_driver_unregister(&mt6229_driver);
358         class_remove_file(modem_class, &class_attr_modem_status);
359 }
360
361 module_init(mt6229_init);
362
363 module_exit(mt6229_exit);