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 MU509_RESET 0x01
40 struct rk29_mu509_data *gpdata = NULL;
41 struct class *modem_class = NULL;
42 static int do_wakeup_irq = 0;
43 static int modem_status;
45 static void ap_wakeup_bp(struct platform_device *pdev, int wake)
47 struct rk29_mu509_data *pdata = pdev->dev.platform_data;
49 gpio_set_value(pdata->ap_wakeup_bp, wake);
52 extern void rk28_send_wakeup_key(void);
54 static void do_wakeup(struct work_struct *work)
58 gpio_set_value(gpdata->ap_wakeup_bp, 0);
64 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
65 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
70 // MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
71 wake_lock_timeout(&modem_wakelock, 10 * HZ);
72 schedule_delayed_work(&wakeup_work, 2*HZ);
76 static int modem_poweron_off(int on_off)
78 struct rk29_mu509_data *pdata = gpdata;
81 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
83 gpio_set_value(pdata->bp_reset, GPIO_LOW);
84 gpio_set_value(pdata->bp_power, GPIO_LOW);
86 gpio_set_value(pdata->bp_power, GPIO_HIGH);
88 gpio_set_value(pdata->bp_power, GPIO_LOW);
89 gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
93 gpio_set_value(pdata->bp_power, GPIO_LOW);
94 gpio_set_value(pdata->bp_power, GPIO_HIGH);
96 gpio_set_value(pdata->bp_power, GPIO_LOW);
100 static int mu509_open(struct inode *inode, struct file *file)
102 struct rk29_mu509_data *pdata = gpdata;
103 device_init_wakeup(pdata->dev, 1);
107 static int mu509_release(struct inode *inode, struct file *file)
112 static long mu509_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
114 struct rk29_mu509_data *pdata = gpdata;
118 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
120 gpio_set_value(pdata->bp_reset, GPIO_LOW);
122 gpio_set_value(pdata->bp_power, GPIO_LOW);
124 gpio_set_value(pdata->bp_power, GPIO_HIGH);
126 gpio_set_value(pdata->bp_power, GPIO_LOW);
127 gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
135 static struct file_operations mu509_fops = {
136 .owner = THIS_MODULE,
138 .release = mu509_release,
139 .unlocked_ioctl = mu509_ioctl
142 static struct miscdevice mu509_misc = {
143 .minor = MISC_DYNAMIC_MINOR,
147 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
148 static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
150 static ssize_t modem_status_read(struct class *cls, char *_buf)
154 return sprintf(_buf, "%d\n", modem_status);
157 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
158 static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
160 static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
163 int new_state = simple_strtoul(_buf, NULL, 16);
164 if(new_state == modem_status) return _count;
166 printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);
167 modem_poweron_off(1);
168 }else if(new_state == 0){
169 printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);
170 modem_poweron_off(0);
172 printk("%s, invalid parameter \n", __FUNCTION__);
174 modem_status = new_state;
177 static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
178 static void rk29_early_suspend(struct early_suspend *h)
182 static void rk29_early_resume(struct early_suspend *h)
186 gpio_set_value(gpdata->ap_wakeup_bp, 0);
191 static struct early_suspend mu509_early_suspend = {
192 .suspend = rk29_early_suspend,
193 .resume = rk29_early_resume,
194 .level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,
196 static int mu509_probe(struct platform_device *pdev)
198 struct rk29_mu509_data *pdata = gpdata = pdev->dev.platform_data;
199 struct modem_dev *mu509_data = NULL;
202 pdata->dev = &pdev->dev;
206 printk("******** mu509_probe_mu509_probe*********\n");
209 rk30_mux_api_set(GPIO1A1_UART0SOUT_NAME, GPIO1A_GPIO1A4);
210 result = gpio_request(RK30_PIN1_PA4, "uart1_sout");
213 printk("%s: gpio_request( uart1_sout ) failed\n", __func__);
217 printk("******* uart0_sout low ( %s ) 88 ********\n", __FUNCTION__);
218 gpio_set_value(RK30_PIN1_PA4, GPIO_LOW); // Make sure the uart1_rx of MU509 is low for usb autosuspend
225 mu509_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
226 if(mu509_data == NULL)
228 printk("failed to request mu509_data\n");
231 platform_set_drvdata(pdev, mu509_data);
232 result = gpio_request(pdata->modem_power_en,"modem_power_en");
234 printk("failed to request modem_power_en gpio\n");
237 gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
238 result = gpio_request(pdata->bp_power,"modem_power");
240 printk("failed to request modem_power gpio\n");
245 register_early_suspend(&mu509_early_suspend);
247 result = gpio_request(pdata->ap_wakeup_bp, "mu509");
249 printk("failed to request AP_BP_WAKEUP gpio\n");
252 irq = gpio_to_irq(pdata->bp_wakeup_ap);
253 enable_irq_wake(irq);
256 gpio_free(pdata->bp_wakeup_ap);
257 printk("failed to request bp_wakeup_ap\n");
259 result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
261 printk("%s: gpio_request(%d) failed\n", __func__, pdata->bp_wakeup_ap);
263 wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
264 gpio_direction_input(pdata->bp_wakeup_ap);
265 gpio_pull_updown(pdata->bp_wakeup_ap, 1);
266 result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
268 printk("%s: request_irq(%d) failed\n", __func__, irq);
269 gpio_free(pdata->bp_wakeup_ap);
272 enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap));
275 modem_poweron_off(1);
278 result = misc_register(&mu509_misc);
281 printk("misc_register err\n");
287 gpio_free(pdata->modem_power_en);
289 gpio_free(pdata->bp_power);
291 gpio_free(pdata->ap_wakeup_bp);
293 cancel_work_sync(&mu509_data->work);
294 gpio_free(pdata->bp_wakeup_ap);
298 static int mu509_suspend(struct platform_device *pdev, pm_message_t state)
302 ap_wakeup_bp(pdev, 1);
303 #if defined(CONFIG_ARCH_RK29)
304 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);
306 #if defined(CONFIG_ARCH_RK30)
307 rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_GPIO1A7);
312 static int mu509_resume(struct platform_device *pdev)
314 #if defined(CONFIG_ARCH_RK29)
315 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
317 #if defined(CONFIG_ARCH_RK30)
318 rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_UART1_RTS_N);
320 if(gpio_get_value(gpdata->bp_wakeup_ap))
322 schedule_delayed_work(&wakeup_work, 2*HZ);
327 static 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 modem_poweron_off(0);
333 gpio_set_value(pdata->modem_power_en, GPIO_LOW);
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)
360 modem_class = class_create(THIS_MODULE, "rk291x_modem");
361 ret = class_create_file(modem_class, &class_attr_modem_status);
364 printk("Fail to class rk291x_modem.\n");
366 return platform_driver_register(&mu509_driver);
369 static void __exit mu509_exit(void)
371 platform_driver_unregister(&mu509_driver);
372 class_remove_file(modem_class, &class_attr_modem_status);
375 module_init(mu509_init);
377 module_exit(mu509_exit);