1 #include <linux/module.h>
2 #include <linux/kernel.h>
5 #include <linux/gpio.h>
6 #include <linux/input.h>
7 #include <linux/platform_device.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>
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/mu509.h>
23 #include <linux/slab.h>
24 #include <linux/earlysuspend.h>
26 MODULE_LICENSE("GPL");
30 #define MODEMDBG(x...) printk(x)
32 #define MODEMDBG(fmt,argss...)
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 airplane_mode RK29_PIN6_PC1
40 #define MU509_RESET 0x01
41 #define AIRPLANE_MODE_OFF 0x03
42 #define AIRPLANE_MODE_ON 0x00
43 struct rk29_mu509_data *gpdata = NULL;
44 struct class *modem_class = NULL;
45 static int do_wakeup_irq = 0;
46 static int modem_status;
47 static int online = 0;
49 static void ap_wakeup_bp(struct platform_device *pdev, int wake)
51 struct rk29_mu509_data *pdata = pdev->dev.platform_data;
53 gpio_set_value(pdata->ap_wakeup_bp, wake);
56 extern void rk28_send_wakeup_key(void);
58 static void do_wakeup(struct work_struct *work)
62 gpio_set_value(gpdata->ap_wakeup_bp, 0);
68 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
69 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
74 // MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
75 wake_lock_timeout(&modem_wakelock, 10 * HZ);
76 schedule_delayed_work(&wakeup_work, 2*HZ);
80 int modem_poweron_off(int on_off)
82 struct rk29_mu509_data *pdata = gpdata;
85 MODEMDBG("------------modem_poweron\n");
86 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
88 gpio_set_value(pdata->bp_reset, GPIO_LOW);
89 gpio_set_value(pdata->bp_power, GPIO_LOW);
91 gpio_set_value(pdata->bp_power, GPIO_HIGH);
93 gpio_set_value(pdata->bp_power, GPIO_LOW);
94 gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
95 gpio_set_value(airplane_mode, GPIO_HIGH);
99 MODEMDBG("------------modem_poweroff\n");
100 gpio_set_value(pdata->bp_power, GPIO_LOW);
101 gpio_set_value(pdata->bp_power, GPIO_HIGH);
103 gpio_set_value(pdata->bp_power, GPIO_LOW);
107 static int mu509_open(struct inode *inode, struct file *file)
109 //MODEMDBG("-------------%s\n",__FUNCTION__);
110 struct rk29_mu509_data *pdata = gpdata;
111 // struct platform_data *pdev = container_of(pdata, struct device, platform_data);
112 device_init_wakeup(pdata->dev, 1);
116 static int mu509_release(struct inode *inode, struct file *file)
118 //MODEMDBG("-------------%s\n",__FUNCTION__);
122 static long mu509_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
124 struct rk29_mu509_data *pdata = gpdata;
125 //MODEMDBG("-------------%s\n",__FUNCTION__);
129 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
131 gpio_set_value(pdata->bp_reset, GPIO_LOW);
133 gpio_set_value(pdata->bp_power, GPIO_LOW);
135 gpio_set_value(pdata->bp_power, GPIO_HIGH);
137 gpio_set_value(pdata->bp_power, GPIO_LOW);
138 gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
139 gpio_set_value(airplane_mode, GPIO_HIGH);
141 case AIRPLANE_MODE_ON:
142 gpio_set_value(airplane_mode, GPIO_LOW);
144 case AIRPLANE_MODE_OFF:
145 gpio_set_value(airplane_mode, GPIO_HIGH);
153 static struct file_operations mu509_fops = {
154 .owner = THIS_MODULE,
156 .release = mu509_release,
157 .unlocked_ioctl = mu509_ioctl
160 static struct miscdevice mu509_misc = {
161 .minor = MISC_DYNAMIC_MINOR,
165 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
166 static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
168 static ssize_t modem_status_read(struct class *cls, char *_buf)
172 return sprintf(_buf, "%d\n", modem_status);
175 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
176 static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
178 static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
181 int new_state = simple_strtoul(_buf, NULL, 16);
182 if(new_state == modem_status) return _count;
184 printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);
185 modem_poweron_off(1);
186 }else if(new_state == 0){
187 printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);
188 modem_poweron_off(0);
190 printk("%s, invalid parameter \n", __FUNCTION__);
192 modem_status = new_state;
195 static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
196 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
197 static ssize_t online_read(struct class *cls, struct class_attribute *attr, char *_buf)
199 static ssize_t online_read(struct class *cls, char *_buf)
202 return sprintf(_buf, "%d\n", online);
205 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
206 static ssize_t online_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
208 static ssize_t online_write(struct class *cls, const char *_buf, size_t _count)
211 int new_value = simple_strtoul(_buf, NULL, 16);
212 if(new_value == online) return _count;
216 static CLASS_ATTR(online, 0777, online_read, online_write);
217 static void rk29_early_suspend(struct early_suspend *h)
219 printk("*********************509____suspend\n");
222 static void rk29_early_resume(struct early_suspend *h)
226 printk("***************509____resume\n");
227 gpio_set_value(gpdata->ap_wakeup_bp, 0);
232 static struct early_suspend mu509_early_suspend = {
233 .suspend = rk29_early_suspend,
234 .resume = rk29_early_resume,
235 .level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,
237 static int mu509_probe(struct platform_device *pdev)
239 struct rk29_mu509_data *pdata = gpdata = pdev->dev.platform_data;
240 struct modem_dev *mu509_data = NULL;
242 //MODEMDBG("-------------%s\n",__FUNCTION__);
244 pdata->dev = &pdev->dev;
247 gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
249 modem_poweron_off(1);
252 register_early_suspend(&mu509_early_suspend);
253 mu509_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
254 if(mu509_data == NULL)
256 printk("failed to request mu509_data\n");
259 platform_set_drvdata(pdev, mu509_data);
260 result = gpio_request(pdata->ap_wakeup_bp, "mu509");
262 printk("failed to request AP_BP_WAKEUP gpio\n");
265 irq = gpio_to_irq(pdata->bp_wakeup_ap);
266 enable_irq_wake(irq);
269 gpio_free(pdata->bp_wakeup_ap);
270 printk("failed to request bp_wakeup_ap\n");
272 result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
274 printk("%s: gpio_request(%d) failed\n", __func__, pdata->bp_wakeup_ap);
276 wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
277 gpio_direction_input(pdata->bp_wakeup_ap);
278 gpio_pull_updown(pdata->bp_wakeup_ap, 1);
279 result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
281 printk("%s: request_irq(%d) failed\n", __func__, irq);
282 gpio_free(pdata->bp_wakeup_ap);
285 enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap));
287 result = misc_register(&mu509_misc);
290 printk("misc_register err\n");
294 cancel_work_sync(&mu509_data->work);
295 gpio_free(pdata->bp_wakeup_ap);
297 gpio_free(pdata->ap_wakeup_bp);
303 int mu509_suspend(struct platform_device *pdev, pm_message_t state)
307 //MODEMDBG("-------------%s\n",__FUNCTION__);
309 ap_wakeup_bp(pdev, 1);
310 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);
311 //gpio_direction_output(RK29_PIN1_PC1, 1);
315 int mu509_resume(struct platform_device *pdev)
317 //MODEMDBG("-------------%s\n",__FUNCTION__);
318 //ap_wakeup_bp(pdev, 0);
319 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
320 if(gpio_get_value(gpdata->bp_wakeup_ap))
322 schedule_delayed_work(&wakeup_work, 2*HZ);
327 void mu509_shutdown(struct platform_device *pdev)
329 struct rk29_mu509_data *pdata = pdev->dev.platform_data;
330 struct modem_dev *mu509_data = platform_get_drvdata(pdev);
332 //MODEMDBG("-------------%s\n",__FUNCTION__);
333 modem_poweron_off(0);
337 cancel_work_sync(&mu509_data->work);
338 gpio_free(pdata->modem_power_en);
339 gpio_free(pdata->bp_power);
340 gpio_free(pdata->bp_reset);
341 gpio_free(pdata->ap_wakeup_bp);
342 gpio_free(pdata->bp_wakeup_ap);
346 static struct platform_driver mu509_driver = {
347 .probe = mu509_probe,
348 .shutdown = mu509_shutdown,
349 .suspend = mu509_suspend,
350 .resume = mu509_resume,
353 .owner = THIS_MODULE,
357 static int __init mu509_init(void)
359 //MODEMDBG("-------------%s\n",__FUNCTION__);
363 modem_class = class_create(THIS_MODULE, "rk291x_modem");
364 ret = class_create_file(modem_class, &class_attr_modem_status);
365 ret = class_create_file(modem_class, &class_attr_online);
368 printk("Fail to class rk291x_modem.\n");
370 return platform_driver_register(&mu509_driver);
373 static void __exit mu509_exit(void)
375 //MODEMDBG("-------------%s\n",__FUNCTION__);
376 platform_driver_unregister(&mu509_driver);
377 class_remove_file(modem_class, &class_attr_modem_status);
378 class_remove_file(modem_class, &class_attr_online);
381 module_init(mu509_init);
383 module_exit(mu509_exit);