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>
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/mi700.h>
22 #include <mach/iomux.h>
23 #include<linux/ioctl.h>
24 #include <linux/slab.h>
26 MODULE_LICENSE("GPL");
30 #define MODEMDBG(x...) printk(x)
32 #define MODEMDBG(fmt,argss...)
36 #define MW_IOCTL_RESET _IO(MW100IO,0X01)
40 #define MI700_RESET 0x01
41 static struct wake_lock modem_wakelock;
42 #define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
43 struct rk29_mi700_data *gpdata = NULL;
44 static int bp_wakeup_ap_irq = 0;
45 struct class *modem_class = NULL;
46 static int do_wakeup_irq = 1;
47 static int modem_status;
48 static int online = 0;
50 static void ap_wakeup_bp(struct platform_device *pdev, int wake)
52 struct rk29_mi700_data *pdata = pdev->dev.platform_data;
53 MODEMDBG("ap_wakeup_bp\n");
55 gpio_set_value(pdata->ap_wakeup_bp, wake);
58 extern void rk28_send_wakeup_key(void);
60 static void do_wakeup(struct work_struct *work)
62 MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
63 //rk28_send_wakeup_key();
66 static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
67 static irqreturn_t detect_irq_handler(int irq, void *dev_id)
72 printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
73 wake_lock_timeout(&modem_wakelock, 10 * HZ);
74 schedule_delayed_work(&wakeup_work, HZ / 10);
76 printk("%s: already wakeup\n", __FUNCTION__);
80 int modem_poweron_off(int on_off)
82 struct rk29_mi700_data *pdata = gpdata;
84 mutex_lock(&pdata->bp_mutex);
87 MODEMDBG("------------modem_poweron\n");
88 gpio_set_value(pdata->bp_reset, GPIO_LOW);
90 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
91 gpio_set_value(pdata->bp_power, GPIO_HIGH);
93 gpio_set_value(pdata->bp_power, GPIO_LOW);
95 gpio_set_value(pdata->bp_power, 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);
105 mutex_unlock(&pdata->bp_mutex);
108 static int mi700_open(struct inode *inode, struct file *file)
110 //MODEMDBG("-------------%s\n",__FUNCTION__);
111 struct rk29_mi700_data *pdata = gpdata;
112 // struct platform_data *pdev = container_of(pdata, struct device, platform_data);
113 device_init_wakeup(pdata->dev, 1);
117 static int mi700_release(struct inode *inode, struct file *file)
119 MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
120 //modem_poweron_off(0);
124 static long mi700_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
126 struct rk29_mi700_data *pdata = gpdata;
130 gpio_set_value(pdata->bp_reset, GPIO_LOW);
132 gpio_set_value(pdata->bp_reset, GPIO_HIGH);
134 gpio_set_value(pdata->bp_power, GPIO_HIGH);
136 gpio_set_value(pdata->bp_power, GPIO_LOW);
138 gpio_set_value(pdata->bp_power, GPIO_HIGH);
146 static struct file_operations mi700_fops = {
147 .owner = THIS_MODULE,
149 .release = mi700_release,
150 .unlocked_ioctl = mi700_ioctl
153 static struct miscdevice mi700_misc = {
154 .minor = MISC_DYNAMIC_MINOR,
158 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
159 static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
161 static ssize_t modem_status_read(struct class *cls, char *_buf)
165 return sprintf(_buf, "%d\n", modem_status);
168 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
169 static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
171 static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
174 int new_state = simple_strtoul(_buf, NULL, 16);
175 if(new_state == modem_status)
179 printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);
180 modem_poweron_off(1);
181 }else if(new_state == 0){
182 printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);
183 modem_poweron_off(0);
185 printk("%s, invalid parameter \n", __FUNCTION__);
188 modem_status = new_state;
191 static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
192 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
193 static ssize_t online_read(struct class *cls, struct class_attribute *attr, char *_buf)
195 static ssize_t online_read(struct class *cls, char *_buf)
198 return sprintf(_buf, "%d\n", online);
201 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
202 static ssize_t online_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
204 static ssize_t online_write(struct class *cls, const char *_buf, size_t _count)
207 int new_value = simple_strtoul(_buf, NULL, 16);
208 if(new_value == online) return _count;
212 static CLASS_ATTR(online, 0777, online_read, online_write);
213 static int mi700_probe(struct platform_device *pdev)
215 struct rk29_mi700_data *pdata = gpdata = pdev->dev.platform_data;
216 struct modem_dev *mi700_data = NULL;
218 MODEMDBG("-------------%s\n",__FUNCTION__);
220 pdata->dev = &pdev->dev;
224 mi700_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
225 if(mi700_data == NULL)
227 printk("failed to request mi700_data\n");
230 platform_set_drvdata(pdev, mi700_data);
232 result = gpio_request(pdata->ap_wakeup_bp, "mi700");
234 printk("failed to request AP_BP_WAKEUP gpio\n");
238 irq = gpio_to_irq(pdata->bp_wakeup_ap);
239 enable_irq_wake(irq);
242 gpio_free(pdata->bp_wakeup_ap);
243 printk("failed to request bp_wakeup_ap\n");
245 result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
247 printk("%s: gpio_request(%d) failed\n", __func__, pdata->bp_wakeup_ap);
249 wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
250 gpio_direction_input(pdata->bp_wakeup_ap);
251 gpio_pull_updown(pdata->bp_wakeup_ap, 1);
252 result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL);
254 printk("%s: request_irq(%d) failed\n", __func__, irq);
255 gpio_free(pdata->bp_wakeup_ap);
258 enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap));
260 mutex_init(&pdata->bp_mutex);
262 modem_poweron_off(1);
265 result = misc_register(&mi700_misc);
268 printk("misc_register err\n");
272 cancel_work_sync(&mi700_data->work);
273 gpio_free(pdata->bp_wakeup_ap);
275 //gpio_free(pdata->ap_wakeup_bp);
281 int mi700_suspend(struct platform_device *pdev)
284 struct rk29_mi700_data *pdata = pdev->dev.platform_data;
286 MODEMDBG("%s::%d--\n",__func__,__LINE__);
287 //gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
291 int mi700_resume(struct platform_device *pdev)
293 MODEMDBG("-------------%s\n",__FUNCTION__);
294 //ap_wakeup_bp(pdev, 0);
295 //rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
299 void mi700_shutdown(struct platform_device *pdev, pm_message_t state)
301 struct rk29_mi700_data *pdata = pdev->dev.platform_data;
302 struct modem_dev *mi700_data = platform_get_drvdata(pdev);
304 MODEMDBG("-------------%s\n",__FUNCTION__);
305 modem_poweron_off(0);
309 cancel_work_sync(&mi700_data->work);
310 //gpio_free(pdata->bp_power);
311 //gpio_free(pdata->bp_reset);
312 //gpio_free(pdata->ap_wakeup_bp);
313 gpio_free(pdata->bp_wakeup_ap);
317 static struct platform_driver mi700_driver = {
318 .probe = mi700_probe,
319 .shutdown = mi700_shutdown,
320 .suspend = mi700_suspend,
321 .resume = mi700_resume,
324 .owner = THIS_MODULE,
328 static int __init mi700_init(void)
330 MODEMDBG("-------------%s\n",__FUNCTION__);
333 modem_class = class_create(THIS_MODULE, "rk291x_modem");
334 ret = class_create_file(modem_class, &class_attr_modem_status);
335 ret = class_create_file(modem_class, &class_attr_online);
338 printk("Fail to class rk291x_modem.\n");
340 return platform_driver_register(&mi700_driver);
343 static void __exit mi700_exit(void)
345 MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
346 platform_driver_unregister(&mi700_driver);
347 class_remove_file(modem_class, &class_attr_modem_status);
348 class_remove_file(modem_class, &class_attr_online);
351 module_init(mi700_init);
352 module_exit(mi700_exit);