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/mt6229.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 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)
46 struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
48 gpio_set_value(pdata->modem_usb_en,wake);
53 gpio_set_value(pdata->modem_uart_en,wake);
56 extern void rk28_send_wakeup_key(void);
58 static void do_wakeup(struct work_struct *work)
60 gpio_set_value(gpdata->ap_ready,GPIO_HIGH);
61 gpio_set_value(gpdata->modem_usb_en,GPIO_HIGH);
64 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
65 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
70 wake_lock_timeout(&modem_wakelock, 10 * HZ);
71 //schedule_delayed_work(&wakeup_work, 2*HZ);
75 static int modem_poweron_off(int on_off)
77 struct rk29_mt6229_data *pdata = gpdata;
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);
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);
94 static int mt6229_open(struct inode *inode, struct file *file)
96 struct rk29_mt6229_data *pdata = gpdata;
97 device_init_wakeup(pdata->dev, 1);
100 static ssize_t mt6229_write(struct file *file, const char __user *buf,size_t len, loff_t *off)
108 ret = copy_from_user(&cmd, buf, len);
112 printk(" received cmd = %c\n",cmd[0]);
115 gpio_set_value(gpdata->ap_ready, GPIO_LOW);
119 gpio_set_value(gpdata->ap_ready, GPIO_HIGH);
123 gpio_set_value(gpdata->modem_uart_en, GPIO_LOW);
127 gpio_set_value(gpdata->modem_uart_en, GPIO_HIGH);
131 gpio_set_value(gpdata->modem_usb_en, GPIO_HIGH);
134 gpio_set_value(gpdata->modem_usb_en, GPIO_LOW);
138 static int mt6229_release(struct inode *inode, struct file *file)
143 static long mt6229_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
145 struct rk29_mt6229_data *pdata = gpdata;
149 modem_poweron_off(0);
151 modem_poweron_off(1);
159 static struct file_operations mt6229_fops = {
160 .owner = THIS_MODULE,
162 .write = mt6229_write,
163 .release = mt6229_release,
164 .unlocked_ioctl = mt6229_ioctl
167 static struct miscdevice mt6229_misc = {
168 .minor = MISC_DYNAMIC_MINOR,
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)
175 static ssize_t modem_status_read(struct class *cls, char *_buf)
179 return sprintf(_buf, "%d\n", modem_status);
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)
185 static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
188 int new_state = simple_strtoul(_buf, NULL, 16);
189 if(new_state == modem_status) return _count;
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);
203 printk("%s, invalid parameter \n", __FUNCTION__);
205 modem_status = new_state;
208 static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
209 static int mt6229_probe(struct platform_device *pdev)
211 struct rk29_mt6229_data *pdata = gpdata = pdev->dev.platform_data;
212 struct modem_dev *mt6229_data = NULL;
214 pdata->dev = &pdev->dev;
217 mt6229_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
218 if(mt6229_data == NULL)
220 printk("failed to request mt6229_data\n");
223 platform_set_drvdata(pdev, mt6229_data);
224 result = gpio_request(pdata->modem_power_en,"modem_power_en");
226 printk("failed to request modem_power_en gpio\n");
229 gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
231 result = gpio_request(pdata->bp_power,"modem_power");
233 printk("failed to request modem_power gpio\n");
236 result = gpio_request(pdata->modem_usb_en, "modem_usb_en");
238 printk("failed to request modem_usb_en gpio\n");
241 result = gpio_request(pdata->modem_uart_en,"modem_uart_en");
243 printk("failed to request modem_uart_en gpio\n");
246 result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
248 printk("failed to request bp_wakeup_ap gpio\n");
251 gpio_direction_input(pdata->bp_wakeup_ap);
252 irq = gpio_to_irq(pdata->bp_wakeup_ap);
255 gpio_free(pdata->bp_wakeup_ap);
256 printk("failed to request bp_wakeup_ap\n");
258 result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
260 printk("%s: request_irq(%d) failed\n", __func__, irq);
261 gpio_free(pdata->bp_wakeup_ap);
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");
268 printk("failed to request ap_ready gpio\n");
272 modem_poweron_off(1);
275 result = misc_register(&mt6229_misc);
278 printk("misc_register err\n");
284 gpio_free(pdata->modem_power_en);
286 gpio_free(pdata->bp_power);
288 gpio_free(pdata->modem_usb_en);
290 gpio_free(pdata->modem_uart_en);
292 gpio_free(pdata->bp_wakeup_ap);
294 gpio_free(pdata->ap_ready);
298 static int mt6229_suspend(struct platform_device *pdev, pm_message_t state)
301 ap_wakeup_bp(pdev, 0);
302 gpio_set_value(gpdata->ap_ready,0);
306 static int mt6229_resume(struct platform_device *pdev)
308 gpio_set_value(gpdata->modem_uart_en,GPIO_LOW);
309 schedule_delayed_work(&wakeup_work, 2*HZ);
313 static void mt6229_shutdown(struct platform_device *pdev)
315 struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
316 struct modem_dev *mt6229_data = platform_get_drvdata(pdev);
318 modem_poweron_off(0);
319 gpio_set_value(pdata->modem_power_en, GPIO_LOW);
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);
332 static struct platform_driver mt6229_driver = {
333 .probe = mt6229_probe,
334 .shutdown = mt6229_shutdown,
335 .suspend = mt6229_suspend,
336 .resume = mt6229_resume,
339 .owner = THIS_MODULE,
343 static int __init mt6229_init(void)
346 modem_class = class_create(THIS_MODULE, "rk291x_modem");
347 ret = class_create_file(modem_class, &class_attr_modem_status);
350 printk("Fail to class rk291x_modem.\n");
352 return platform_driver_register(&mt6229_driver);
355 static void __exit mt6229_exit(void)
357 platform_driver_unregister(&mt6229_driver);
358 class_remove_file(modem_class, &class_attr_modem_status);
361 module_init(mt6229_init);
363 module_exit(mt6229_exit);