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 <mach/spi_fpga.h>
17 #include <linux/delay.h>
18 #include <linux/poll.h>
19 #include <linux/wait.h>
20 //#include <linux/android_power.h>
21 //#include <asm/arch/gpio_extend.h>
22 #include <linux/workqueue.h>
23 #include <linux/mtk23d.h>
24 #include <linux/wakelock.h>
25 #include "../mtd/rknand/api_flash.h"
27 MODULE_LICENSE("GPL");
31 #define MODEMDBG(x...) printk(x)
33 #define MODEMDBG(fmt,argss...)
36 #define MTK23D_RESET 0x01
37 #define MTK23D_POWERON 0x02
38 #define MTK23D_POWER_HIGH 0x03
39 #define MTK23D_IMEI_READ 0x04
40 //#define BP_POW_EN TCA6424_P02
41 //#define BP_STATUS RK2818_PIN_PH7 //input high bp sleep
42 //#define AP_STATUS RK2818_PIN_PA4 //output high ap sleep
44 //#define BP_RESET TCA6424_P11 //Ryan
46 //#define AP_BP_WAKEUP RK2818_PIN_PF5 //output AP wake up BP used rising edge
47 //#define BP_AP_WAKEUP RK2818_PIN_PE0 //input BP wake up AP
49 static bool bpstatus_irq_enable = false;
50 static bool wakelock_inited;
51 static struct wake_lock mtk23d_wakelock;
56 //struct modem_dev *mt6223d_data = NULL;
57 struct rk2818_23d_data *gpdata = NULL;
59 static int get_bp_statue(struct platform_device *pdev)
61 struct rk2818_23d_data *pdata = pdev->dev.platform_data;
63 if(gpio_get_value(pdata->bp_statue))
68 static void ap_sleep(struct platform_device *pdev)
70 struct rk2818_23d_data *pdata = pdev->dev.platform_data;
72 MODEMDBG("ap sleep!\n");
73 gpio_set_value(pdata->ap_statue,GPIO_HIGH);
75 static void ap_wakeup(struct platform_device *pdev)
77 struct rk2818_23d_data *pdata = pdev->dev.platform_data;
79 MODEMDBG("ap wakeup!\n");
80 gpio_set_value(pdata->ap_statue,GPIO_LOW);
83 static void ap_wakeup_bp(struct platform_device *pdev, int wake)//low to wakeup bp
85 struct rk2818_23d_data *pdata = pdev->dev.platform_data;
86 struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
87 MODEMDBG("ap_wakeup_bp\n");
89 gpio_set_value(pdata->ap_bp_wakeup, wake); // phc
90 //gpio_set_value(RK2818_PIN_PF5, wake);
93 static void bpwakeup_work_func_work(struct work_struct *work)
95 struct modem_dev *bdata = container_of(work, struct modem_dev, work);
97 MODEMDBG("%s\n", __FUNCTION__);
101 static irqreturn_t bpwakeup_work_func(int irq, void *data)
103 struct modem_dev *mt6223d_data = (struct modem_dev *)data;
105 MODEMDBG("bpwakeup_work_func\n");
106 schedule_work(&mt6223d_data->work);
109 static irqreturn_t bp_apwakeup_work_func(int irq, void *data)
111 //struct modem_dev *dev = &mtk23d_misc;
113 MODEMDBG("bp_apwakeup_work_func\n");
114 //wake_up_interruptible(&dev->wakeup);
118 static irqreturn_t BBwakeup_isr(int irq, void *dev_id)
120 struct rk2818_23d_data *pdata = dev_id;
122 MODEMDBG("%s \n", __FUNCTION__);
123 //if(irq != gpio_to_irq(RK29_PIN1_PC0))
125 // printk("irq != gpio_to_irq(RK29_PIN1_PC0) \n");
129 // disable_irq_wake(irq);
131 if(bpstatus_irq_enable == true)
133 MODEMDBG("mtk23d_wakelock 3s \n");
134 wake_lock_timeout(&mtk23d_wakelock, 3 * HZ);
141 int modem_poweron_off(int on_off)
143 struct rk2818_23d_data *pdata = gpdata;
144 int result, error = 0, irq = 0;
148 printk("modem_poweron\n");
150 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH); // power on enable
152 gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW); // release reset
154 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW); // power on relase
157 rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT);
158 rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN);
159 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
160 rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N);
163 gpio_direction_input(pdata->bp_statue);
164 if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
165 gpio_direction_input(pdata->bp_ap_wakeup);
167 /* ³õʼ»¯BP»½ÐÑAPµÄ¹¦ÄÜ */
168 wakelock_inited = false;
169 irq = gpio_to_irq(pdata->bp_statue);
171 printk("can't get pdata->bp_statue irq \n");
175 error = request_irq(irq, BBwakeup_isr,
176 IRQF_TRIGGER_FALLING,
180 printk("mtk23d_probe bp_statue request_irq error!!! \n");
183 if (!wakelock_inited) {
184 wake_lock_init(&mtk23d_wakelock, WAKE_LOCK_SUSPEND, "23d_resume");
185 wakelock_inited = true;
190 printk("modem_poweroff\n");
191 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
193 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
196 static int power_on =1;
197 static int mtk23d_open(struct inode *inode, struct file *file)
199 struct rk2818_23d_data *pdata = gpdata;
200 //struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
201 struct platform_data *pdev = container_of(pdata, struct device, platform_data);
203 MODEMDBG("modem_open\n");
209 modem_poweron_off(1);
211 device_init_wakeup(&pdev, 1);
216 static int mtk23d_release(struct inode *inode, struct file *file)
218 MODEMDBG("mtk23d_release\n");
220 //gpio_free(pdata->bp_power);
224 //extern char imei_value[16]; // phc, no find 'imei_value' in rk29 project
225 //char imei_value[16] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5};
227 static int mtk23d_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg)
229 struct rk2818_23d_data *pdata = gpdata;
231 void __user *argp = (void __user *)arg;
233 char SectorBuffer[512];
235 printk("mtk23d_ioctl\n");
239 printk("MTK23D_RESET\n");
240 gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
242 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH);
244 gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
246 gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW);
248 case MTK23D_IMEI_READ:
249 printk("MTK23D_IMEI_READ\n");
251 GetSNSectorInfo(SectorBuffer); // phc,20110624
253 if(copy_to_user(argp, &(SectorBuffer[451]), 16)) // IMEIºó´Ó451Æ«ÒÆ¿ªÊ¼µÄ16bytes£¬µÚÒ»¸öbyteΪ³¤¶È¹Ì¶¨Îª15
255 printk("ERROR: copy_to_user---%s\n", __FUNCTION__);
258 //printk("IMEI:%d %d %d %d\n", SectorBuffer[451], SectorBuffer[452], SectorBuffer[453], SectorBuffer[454]);
266 static struct file_operations mtk23d_fops = {
267 .owner = THIS_MODULE,
269 .release = mtk23d_release,
270 .ioctl = mtk23d_ioctl
273 static struct miscdevice mtk23d_misc = {
274 .minor = MISC_DYNAMIC_MINOR,
279 static int mtk23d_probe(struct platform_device *pdev)
281 struct rk2818_23d_data *pdata = gpdata = pdev->dev.platform_data;
282 struct modem_dev *mt6223d_data = NULL;
283 int result, error = 0, irq = 0;
285 MODEMDBG("mtk23d_probe\n");
289 mt6223d_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
290 if(NULL == mt6223d_data)
292 printk("failed to request mt6223d_data\n");
295 platform_set_drvdata(pdev, mt6223d_data);
297 result = gpio_request(pdata->bp_statue, "mtk23d");
299 printk("failed to request BP_STATUS gpio\n");
303 result = gpio_request(pdata->ap_statue, "mtk23d");
305 printk("failed to request AP_STATUS gpio\n");
309 result = gpio_request(pdata->ap_bp_wakeup, "mtk23d");
311 printk("failed to request AP_BP_WAKEUP gpio\n");
314 result = gpio_request(pdata->bp_reset, "mtk23d");
316 printk("failed to request BP_RESET gpio\n");
319 result = gpio_request(pdata->bp_power, "mtk23d");
321 printk("failed to request BP_POW_EN gpio\n");
325 if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
327 result = gpio_request(pdata->bp_ap_wakeup, "mtk23d");
329 printk("failed to request BP_AP_WAKEUP gpio\n");
334 #if 1 // GPIO³õʼ»¯£¬²¢ÇÒ·Àֹ©µç
335 rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_GPIO1B7);
336 gpio_request(RK29_PIN1_PB7, NULL);
337 gpio_direction_output(RK29_PIN1_PB7,GPIO_LOW);
338 gpio_pull_updown(RK29_PIN1_PB7, PullDisable); // ÏÂÀ½ûÖ¹
340 rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_GPIO1B6);
341 gpio_request(RK29_PIN1_PB6, NULL);
342 gpio_direction_output(RK29_PIN1_PB6,GPIO_LOW);
343 gpio_pull_updown(RK29_PIN1_PB6, PullDisable); // ÏÂÀ½ûÖ¹
345 rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);
346 gpio_request(RK29_PIN1_PC1, NULL);
347 gpio_direction_output(RK29_PIN1_PC1,GPIO_LOW);
349 rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_GPIO1C0);
350 gpio_request(RK29_PIN1_PC0, NULL);
351 //gpio_direction_input(RK29_PIN1_PC0);
352 gpio_direction_output(RK29_PIN1_PC0,GPIO_LOW);
355 gpio_direction_output(pdata->bp_power, GPIO_LOW);
356 gpio_direction_output(pdata->ap_statue, GPIO_LOW);
357 gpio_direction_output(pdata->ap_bp_wakeup, GPIO_LOW);
358 gpio_direction_output(pdata->bp_reset, GPIO_LOW);
359 //gpio_direction_output(pdata->bp_statue,GPIO_LOW);
360 gpio_direction_input(pdata->bp_statue);
361 if(pdata->bp_ap_wakeup) // SDK°åÖУ¬¸Ã¿ÚûÓÐÒý³ö
363 //gpio_direction_output(pdata->bp_ap_wakeup,GPIO_LOW);
364 gpio_direction_input(pdata->bp_ap_wakeup);
368 gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH);
370 //gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW);
373 INIT_WORK(&mt6223d_data->work, bpwakeup_work_func_work);
375 result = misc_register(&mtk23d_misc);
378 MODEMDBG("misc_register err\n");
380 MODEMDBG("mtk23d_probe ok\n");
384 cancel_work_sync(&mt6223d_data->work);
385 gpio_free(pdata->bp_ap_wakeup);
387 gpio_free(pdata->bp_power);
389 gpio_free(pdata->bp_reset);
391 gpio_free(pdata->ap_bp_wakeup);
393 gpio_free(pdata->ap_statue);
395 gpio_free(pdata->bp_statue);
402 int mtk23d_suspend(struct platform_device *pdev)
405 struct rk2818_23d_data *pdata = pdev->dev.platform_data;
407 MODEMDBG("%s \n", __FUNCTION__);
409 //enable_irq_wake(irq);
411 ap_wakeup_bp(pdev, 0);
413 irq = gpio_to_irq(pdata->bp_statue);
415 printk("can't get pdata->bp_statue irq \n");
419 printk("enable pdata->bp_statue irq_wake!! \n");
420 bpstatus_irq_enable = true;
421 enable_irq_wake(irq);
427 int mtk23d_resume(struct platform_device *pdev)
429 struct rk2818_23d_data *pdata = pdev->dev.platform_data;
432 MODEMDBG("%s \n", __FUNCTION__);
434 irq = gpio_to_irq(pdata->bp_statue);
437 printk("disable pdata->bp_statue irq_wake!! \n");
438 bpstatus_irq_enable = false;
439 disable_irq_wake(irq);
443 ap_wakeup_bp(pdev, 1);
448 void mtk23d_shutdown(struct platform_device *pdev, pm_message_t state)
450 struct rk2818_23d_data *pdata = pdev->dev.platform_data;
451 struct modem_dev *mt6223d_data = platform_get_drvdata(pdev);
453 MODEMDBG("%s \n", __FUNCTION__);
455 modem_poweron_off(0); // power down
457 cancel_work_sync(&mt6223d_data->work);
458 gpio_free(pdata->bp_ap_wakeup);
459 gpio_free(pdata->bp_power);
460 gpio_free(pdata->bp_reset);
461 gpio_free(pdata->ap_bp_wakeup);
462 gpio_free(pdata->ap_statue);
463 gpio_free(pdata->bp_statue);
467 static struct platform_driver mtk23d_driver = {
468 .probe = mtk23d_probe,
469 .shutdown = mtk23d_shutdown,
470 .suspend = mtk23d_suspend,
471 .resume = mtk23d_resume,
474 .owner = THIS_MODULE,
478 static int __init mtk23d_init(void)
480 MODEMDBG("mtk23d_init ret=%d\n");
481 return platform_driver_register(&mtk23d_driver);
484 static void __exit mtk23d_exit(void)
486 MODEMDBG("mtk23d_exit\n");
487 platform_driver_unregister(&mtk23d_driver);
490 module_init(mtk23d_init);
491 //late_initcall_sync(mtk23d_init);
492 module_exit(mtk23d_exit);