menuconfig RK29_SUPPORT_MODEM
tristate "RK29 support Modem"
- depends on USB11_HOST_EN
+# depends on USB11_HOST_EN
---help---
Say Y here if you have a support modem
depends on RK29_SUPPORT_MODEM
prompt "Select 3G Modem"
- config MODEM_ROCKCHIP_DEMO
+ config MODEM_ROCKCHIP_DEMO
bool "ROCKCHIP_GENERAL_MODEM_DEVICE"
-# config MODEM_ZTE_MG3732
-# bool "ZTE_MG3732"
+ config MODEM_LONGCHEER_U6300V
+ bool "LONGCHEER_U6300V"
-#config MODEM_ZTE_MF210
-# bool "ZTE_MF210"
-
-#config MODEM_ZTE_AD3812
-# bool "ZTE_AD3812"
-
-#config MODEM_THINKWILL_ME800
-# bool "THINKWILL_ME800"
-
-#config MODEM_HUAWEI_EM660
-# bool "HUAWEI_EM660"
-
-#config MODEM_HUAWEI_EM770
-# bool "HUAWEI_EM770"
-
-#config MODEM_HUAWEI_EM660C
- # bool "HUAWEI_EM660C"
-
-#config MODEM_ZTE_MU301
-# bool "ZTE_MU301"
-
-#config MODEM_TDM_330
-# bool "TDM_330"
+ config MODEM_THINKWILL_MW100G
+ bool "THINKWILL_MW100G"
endchoice
-obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem.o
-
-obj-$(CONFIG_MODEM_ROCKCHIP_DEMO) +=modem_rockchip_demo.o
-
-obj-$(CONFIG_MODEM_ZTE_MG3732) +=modem_zte_mg3732.o
-
-#obj-$(CONFIG_MODEM_ZTE_MF210) += modem_zte_mf210.o
-#obj-$(CONFIG_MODEM_ZTE_AD3812) += modem_zte_ad3812.o
-#obj-$(CONFIG_MODEM_THINKWILL_ME800) += modem_thinkwill_me800.o
-#obj-$(CONFIG_MODEM_HUAWEI_EM660) += modem_huawei_em660.o
-#obj-$(CONFIG_MODEM_HUAWEI_EM770) += modem_huawei_em770.o
-#obj-$(CONFIG_MODEM_HUAWEI_EM660C) += modem_huawei_em660c.o
-#obj-$(CONFIG_MODEM_ZTE_MU301) += modem_zte_mu301.o
-#obj-$(CONFIG_MODEM_TDM_330) += modem_tdm_330.o
-
+obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem.o
+obj-$(CONFIG_MODEM_ROCKCHIP_DEMO) += modem_rockchip_demo.o
+obj-$(CONFIG_MODEM_LONGCHEER_U6300V) +=modem_longcheer_u6300v.o
+obj-$(CONFIG_MODEM_THINKWILL_MW100G) +=modem_thinkwill_mw100g.o
--- /dev/null
+#include <linux/kernel.h>\r
+#include <linux/module.h>\r
+#include <linux/moduleparam.h>\r
+#include <linux/init.h>\r
+#include <linux/device.h>\r
+#include <linux/errno.h>\r
+#include <linux/types.h>\r
+#include <linux/stat.h> /* permission constants */\r
+#include <linux/io.h>\r
+#include <linux/vmalloc.h>\r
+#include <asm/io.h>\r
+#include <asm/sizes.h>\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <linux/delay.h>\r
+\r
+#include <linux/wakelock.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/gpio.h>\r
+#include <mach/board.h>\r
+\r
+#include <linux/platform_device.h>\r
+\r
+#include "rk29_modem.h"\r
+\r
+// È·±£²»³öÏÖÖظ´´¦Àíwakeup\r
+static int do_wakeup_handle = 0;\r
+static irqreturn_t u6300v_irq_handler(int irq, void *dev_id);\r
+static int __devinit u6300v_resume(struct platform_device *pdev);\r
+\r
+static struct rk29_io_t u6300v_io_ap_ready = {\r
+ .io_addr = RK29_PIN3_PC2,\r
+ .enable = GPIO_LOW,\r
+ .disable = GPIO_HIGH,\r
+};\r
+\r
+static struct rk29_io_t u6300v_io_power = {\r
+ .io_addr = RK29_PIN6_PB1,\r
+ .enable = GPIO_HIGH,\r
+ .disable = GPIO_LOW,\r
+};\r
+\r
+static struct rk29_irq_t u6300v_irq_bp_wakeup_ap= {\r
+ .irq_addr = RK29_PIN3_PD7,\r
+ .irq_trigger = IRQF_TRIGGER_FALLING, // ϽµÑØ´¥·¢\r
+};\r
+\r
+static struct platform_driver u6300v_platform_driver = {\r
+ .driver = {\r
+ .name = "longcheer_u6300v",\r
+ },
+ .suspend = rk29_modem_suspend,\r
+ .resume = rk29_modem_resume,\r
+};\r
+\r
+static struct rk29_modem_t u6300v_driver = {\r
+ .driver = &u6300v_platform_driver,\r
+ .modem_power = &u6300v_io_power,\r
+ .ap_ready = &u6300v_io_ap_ready,\r
+ .bp_wakeup_ap = &u6300v_irq_bp_wakeup_ap,\r
+ .status = MODEM_ENABLE,\r
+ .dev_init = NULL,\r
+ .dev_uninit = NULL,\r
+ .irq_handler = u6300v_irq_handler,\r
+ .suspend = NULL,\r
+ .resume = u6300v_resume,\r
+ \r
+ .enable = NULL,\r
+ .disable = NULL,\r
+ .sleep = NULL,\r
+ .wakeup = NULL,\r
+};\r
+\r
+static void do_test1(struct work_struct *work)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ // ±êÖ¾APÒѾÍÐ÷£¬BB¿ÉÒÔÉϱ¨Êý¾Ý¸øAP\r
+ gpio_direction_output(u6300v_driver.ap_ready->io_addr, u6300v_driver.ap_ready->enable);\r
+}\r
+\r
+static DECLARE_DELAYED_WORK(test1, do_test1);\r
+\r
+static int __devinit u6300v_resume(struct platform_device *pdev)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+/* cmy: Ä¿Ç°ÔÚϵͳ±»»½ÐѺó£¬ÔÚÕâ±ßÉèÖÃAP_RDY£¬µ«ÓÉÓÚͨÐÅÒÀÀµÓÚÆäËüµÄÉ豸Çý¶¯(±ÈÈçUSB»òÕß´®¿Ú)\r
+ ÐèÒªÑÓʱÉèÖÃAP_RDYÐźÅ\r
+ ¸üºÃµÄ×ö·¨ÊÇÔÚËüËùÒÀÀµµÄÉ豸¾ÍÐ÷ºó(»½ÐÑ)£¬ÔÙÉèÖÃAP_RDY¡£×ö·¨Á½ÖÖ:\r
+ 1 ½«ÉèÖÃAP_RDYµÄº¯Êý×¢È뵽Ŀ±êÉ豸µÄresumeº¯ÊýÖÐ\r
+ 2 ÔÚrk29_modem_resumeÖУ¬µÈ´ýÄ¿±êÉ豸resumeÖ®ºó£¬ÔÙÉèÖÃAP_RDY\r
+ */\r
+ schedule_delayed_work(&test1, 2*HZ);\r
+\r
+ return 0;\r
+}\r
+\r
+/*\r
+ u6300v Ä£×éµÄ IRQ ´¦Àíº¯Êý£¬¸Ãº¯ÊýÓÉrk29_modemÖеÄIRQ´¦Àíº¯Êýµ÷ÓÃ\r
+ */\r
+static irqreturn_t u6300v_irq_handler(int irq, void *dev_id)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ if( irq == gpio_to_irq(u6300v_driver.bp_wakeup_ap->irq_addr) )\r
+ {\r
+ if( !do_wakeup_handle )\r
+ {\r
+ do_wakeup_handle = 1;\r
+ // µ±½ÓÊÕµ½ bb wakeup ap µÄIRQºó£¬ÉêÇëÒ»¸ö8ÃëµÄsuspendËø£¬Ê±¼äµ½ºó×Ô¶¯ÊÍ·Å\r
+ // ÊÍ·ÅʱÈç¹ûûÓÐÆäËüµÄËø£¬¾Í½«ÔٴιÒÆð.\r
+ wake_lock_timeout(&u6300v_driver.wakelock_bbwakeupap, 8 * HZ);\r
+ } else\r
+ printk("%s: already wakeup\n", __FUNCTION__);\r
+ return IRQ_HANDLED;\r
+ }\r
+ \r
+ return IRQ_NONE;\r
+}\r
+\r
+static int __init u6300v_init(void)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ return rk29_modem_init(&u6300v_driver);\r
+}\r
+\r
+static void __exit u6300v_exit(void)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ rk29_modem_exit();\r
+}\r
+\r
+module_init(u6300v_init);\r
+module_exit(u6300v_exit);\r
+\r
+MODULE_AUTHOR("lintao lintao@rock-chips.com");\r
+MODULE_DESCRIPTION("ROCKCHIP modem driver");\r
+MODULE_LICENSE("GPL");\r
+\r
+#if 0\r
+int test(void)\r
+{\r
+ printk(">>>>>> test \n ");\r
+ int ret = gpio_request(IRQ_BB_WAKEUP_AP, NULL);\r
+ if(ret != 0)\r
+ {\r
+ printk(">>>>>> gpio_request failed! \n ");\r
+ gpio_free(IRQ_BB_WAKEUP_AP);\r
+ return ret;\r
+ }\r
+\r
+// printk(">>>>>> set GPIOPullUp \n ");\r
+// gpio_pull_updown(IRQ_BB_WAKEUP_AP, GPIOPullUp);\r
+// printk(">>>>>> set GPIO_HIGH \n ");\r
+// gpio_direction_output(IRQ_BB_WAKEUP_AP, GPIO_HIGH);\r
+\r
+// printk(">>>>>> set GPIO_LOW \n ");\r
+// gpio_direction_output(IRQ_BB_WAKEUP_AP, GPIO_LOW);\r
+// msleep(1000);\r
+ \r
+ gpio_free(IRQ_BB_WAKEUP_AP);\r
+\r
+ printk(">>>>>> END \n ");\r
+}\r
+#endif\r
+\r
#include <linux/device.h>\r
#include <linux/errno.h>\r
#include <linux/types.h>\r
-#include <linux/stat.h> /* permission constants */\r
+#include <linux/stat.h>\r
#include <linux/io.h>\r
#include <linux/vmalloc.h>\r
#include <asm/io.h>\r
#include <asm/sizes.h>\r
#include <mach/iomux.h>\r
#include <mach/gpio.h>\r
-//#include <asm/arch/iomux.h>\r
#include <linux/delay.h>\r
\r
-#include "rk29_modem.h"\r
-\r
-/****************************************************************\r
- huawei-em660/em660c/em770\r
- zte-ad3812/mf210/mu301\r
- thinkwill-me800 \r
-\r
-*****************************************************************/\r
-\r
-static int modem_enable(void){\r
- printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
- // PG1: 3G reset\r
- /*arch/arm/mach-rockchip/iomux.c*/\r
-// rockchip_mux_api_set(G3_RESET_IOMUX_NAME, G3_RESET_IOMUX_MODE);\r
- // PB0: 3G poweron\r
-// rockchip_mux_api_set(G3_POWER_ON_IOMUX_NAME, G3_POWER_ON_IOMUX_MODE);\r
- // PG0: 3G Radio On/Off\r
-// rockchip_mux_api_set(G3_RADIO_ON_OFF_IOMUX_NAME, G3_RADIO_ON_OFF_IOMUX_MODE);\r
-// msleep(10);\r
- \r
- /*3G Modem Power On*/\r
- int ret = gpio_request(G3_POWER_ON, NULL);\r
- if(ret != 0)\r
- {\r
- gpio_free(G3_POWER_ON);\r
- printk(">>>>>> G3_POWER_ON gpio_request err \n ");\r
- return ret;\r
- }\r
- gpio_direction_output(G3_POWER_ON, G3_POWER_ENABLE);\r
-// gpio_set_value(FB_LCD_CABC_EN_PIN, GPIO_LOW);\r
-\r
-// GPIOSetPinDirection(G3_POWER_ON, GPIO_OUT);\r
-// GPIOSetPinLevel(G3_POWER_ON, G3_POWER_ENABLE);\r
- msleep(100);\r
- gpio_free(G3_POWER_ON);\r
- \r
- /*3G Modem Radio On*/\r
-// GPIOSetPinDirection(G3_RADIO_ON_OFF, GPIO_OUT);\r
-// GPIOSetPinLevel(G3_RADIO_ON_OFF, G3_RADIO_ENABLE);\r
-// msleep(100);\r
-\r
- /*3G Modem Reset Controll if needed*/\r
-// if(G3_RESET){\r
-// GPIOSetPinDirection(G3_RESET, GPIO_OUT);\r
-// GPIOSetPinLevel(G3_RESET, G3_RESET_ENABLE);\r
-// msleep(120);\r
-// GPIOSetPinLevel(G3_RESET, G3_RESET_DISABLE);\r
-// }\r
- return 0;\r
-}\r
-\r
-static int modem_disable(void){\r
- printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
- // PG1: 3G reset\r
-// rockchip_mux_api_set(G3_RESET_IOMUX_NAME, G3_RESET_IOMUX_MODE);\r
- // PB0: 3G poweron\r
-// rockchip_mux_api_set(G3_POWER_ON_IOMUX_NAME, G3_POWER_ON_IOMUX_MODE);\r
- // PG0: 3G On/Off\r
-// rockchip_mux_api_set(G3_RADIO_ON_OFF_IOMUX_NAME, G3_RADIO_ON_OFF_IOMUX_MODE);\r
-// msleep(10);\r
-\r
-#if 1\r
- int ret = gpio_request(G3_POWER_ON, NULL);\r
- if(ret != 0)\r
- {\r
- gpio_free(G3_POWER_ON);\r
- printk(">>>>>> G3_POWER_ON gpio_request err \n ");\r
- return ret;\r
- }\r
- gpio_direction_output(G3_POWER_ON, G3_POWER_DISABLE);\r
-#else \r
- /*3G Modem Power off*/\r
- GPIOSetPinDirection(G3_POWER_ON, GPIO_OUT);\r
- GPIOSetPinLevel(G3_POWER_ON, G3_POWER_DISABLE);\r
-#endif\r
- msleep(100);\r
- gpio_free(G3_POWER_ON);\r
+#include <linux/wakelock.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/gpio.h>\r
+#include <mach/board.h>\r
\r
- /*3G Modem Radio off*/\r
-// GPIOSetPinDirection(G3_RADIO_ON_OFF, GPIO_OUT);\r
-// GPIOSetPinLevel(G3_RADIO_ON_OFF, G3_RADIO_DISABLE);\r
-// msleep(10);\r
+#include <linux/platform_device.h>\r
\r
- /*3G Modem Reset enable if needed*/\r
-// if(G3_RESET){\r
-// GPIOSetPinDirection(G3_RESET, GPIO_OUT);\r
-// GPIOSetPinLevel(G3_RESET, G3_RESET_ENABLE);\r
-// }\r
- return 0;\r
-}\r
+#include "rk29_modem.h"\r
\r
-static int modem_sleep(void){\r
- printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
- \r
- return 0;\r
-}\r
+static struct rk29_io_t demo_io_power = {\r
+ .io_addr = RK29_PIN6_PB1,\r
+ .enable = GPIO_HIGH,\r
+ .disable = GPIO_LOW,\r
+};\r
\r
-static int modem_init(void){\r
- return modem_disable();\r
-}\r
+static struct platform_driver demo_platform_driver = {\r
+ .driver = {\r
+ .name = "rk29_demo",\r
+ },
+};\r
\r
-struct rk29_modem_t rk29_modem = {\r
- .name = "ThinkWill_ME800",\r
- .enable = modem_enable,\r
- .disable = modem_disable,\r
- .sleep = modem_sleep,\r
- .init = modem_init,\r
+static struct rk29_modem_t demo_driver = {\r
+ .driver = &demo_platform_driver,\r
+ .modem_power = &demo_io_power,\r
+ .ap_ready = NULL,\r
+ .bp_wakeup_ap = NULL,\r
+ .status = MODEM_ENABLE,\r
+ .dev_init = NULL,\r
+ .dev_uninit = NULL,\r
+ .irq_handler = NULL,\r
+ \r
+ .enable = NULL,\r
+ .disable = NULL,\r
+ .sleep = NULL,\r
+ .wakeup = NULL,\r
};\r
\r
-static int __init rk29_modem_init(void)\r
+static int __init demo_init(void)\r
{\r
- return rk29_modem_register(&rk29_modem);\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ return rk29_modem_init(&demo_driver);\r
}\r
\r
-static void __exit rk29_modem_exit(void)\r
+static void __exit demo_exit(void)\r
{\r
- rk29_modem_unregister(&rk29_modem);\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ rk29_modem_exit();\r
}\r
\r
-\r
-late_initcall(rk29_modem_init);\r
-//module_init(rk29_modem_init);\r
-module_exit(rk29_modem_exit);\r
+module_init(demo_init);\r
+module_exit(demo_exit);\r
\r
MODULE_AUTHOR("lintao lintao@rock-chips.com");\r
MODULE_DESCRIPTION("ROCKCHIP modem driver");\r
MODULE_LICENSE("GPL");\r
\r
-\r
--- /dev/null
+#include <linux/kernel.h>\r
+#include <linux/module.h>\r
+#include <linux/moduleparam.h>\r
+#include <linux/init.h>\r
+#include <linux/device.h>\r
+#include <linux/errno.h>\r
+#include <linux/types.h>\r
+#include <linux/stat.h> /* permission constants */\r
+#include <linux/io.h>\r
+#include <linux/vmalloc.h>\r
+#include <asm/io.h>\r
+#include <asm/sizes.h>\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <linux/delay.h>\r
+\r
+#include <linux/wakelock.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/gpio.h>\r
+#include <mach/board.h>\r
+\r
+#include <linux/platform_device.h>\r
+\r
+#include "rk29_modem.h"\r
+\r
+// È·±£²»³öÏÖÖظ´´¦Àíwakeup\r
+static int do_wakeup_handle = 0;\r
+static irqreturn_t mw100g_irq_handler(int irq, void *dev_id);\r
+\r
+static int __devinit mw100g_suspend(struct platform_device *pdev, pm_message_t state)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ do_wakeup_handle = 0;\r
+ return rk29_modem_suspend(pdev, state);\r
+}\r
+
+static int __devinit mw100g_resume(struct platform_device *pdev)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ return rk29_modem_resume(pdev);\r
+}\r
+\r
+static struct rk29_io_t mw100g_io_power = {\r
+ .io_addr = RK29_PIN6_PB1,\r
+ .enable = GPIO_HIGH,\r
+ .disable = GPIO_LOW,\r
+};\r
+\r
+static struct rk29_irq_t mw100g_irq_bp_wakeup_ap= {\r
+ .irq_addr = RK29_PIN3_PC4,\r
+ .irq_trigger = IRQF_TRIGGER_FALLING, // ϽµÑØ´¥·¢\r
+};\r
+\r
+static struct platform_driver mw100g_platform_driver = {\r
+ .driver = {\r
+ .name = "thinkwill_mw100g",\r
+ },
+ .suspend = mw100g_suspend,\r
+ .resume = mw100g_resume,\r
+};\r
+\r
+static struct rk29_modem_t mw100g_driver = {\r
+ .driver = &mw100g_platform_driver,\r
+ .modem_power = &mw100g_io_power,\r
+ .ap_ready = NULL,\r
+ .bp_wakeup_ap = &mw100g_irq_bp_wakeup_ap,\r
+ .status = MODEM_ENABLE,\r
+ .dev_init = NULL,\r
+ .dev_uninit = NULL,\r
+ .irq_handler = mw100g_irq_handler,\r
+ \r
+ .enable = NULL,\r
+ .disable = NULL,\r
+ .sleep = NULL,\r
+ .wakeup = NULL,\r
+};\r
+\r
+static void do_wakeup(struct work_struct *work)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+// rk28_send_wakeup_key();\r
+}\r
+\r
+static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);\r
+\r
+/*\r
+ mw100g Ä£×éµÄ IRQ ´¦Àíº¯Êý£¬¸Ãº¯ÊýÓÉrk29_modemÖеÄIRQ´¦Àíº¯Êýµ÷ÓÃ\r
+ */\r
+static irqreturn_t mw100g_irq_handler(int irq, void *dev_id)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ if( irq == gpio_to_irq(mw100g_driver.bp_wakeup_ap->irq_addr) )\r
+ {\r
+ if( !do_wakeup_handle )\r
+ {\r
+ do_wakeup_handle = 1;\r
+ // µ±½ÓÊÕµ½ bb wakeup ap µÄIRQºó£¬ÉêÇëÒ»¸ö8ÃëµÄsuspendËø£¬Ê±¼äµ½ºó×Ô¶¯ÊÍ·Å\r
+ // ÊÍ·ÅʱÈç¹ûûÓÐÆäËüµÄËø£¬¾Í½«ÔٴιÒÆð.\r
+ wake_lock_timeout(&mw100g_driver.wakelock_bbwakeupap, 20 * HZ);\r
+ schedule_delayed_work(&wakeup_work, HZ / 10);\r
+ } else\r
+ printk("%s: already wakeup\n", __FUNCTION__);\r
+ return IRQ_HANDLED;\r
+ }\r
+ \r
+ return IRQ_NONE;\r
+}\r
+\r
+static int __init mw100g_init(void)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ return rk29_modem_init(&mw100g_driver);\r
+}\r
+\r
+static void __exit mw100g_exit(void)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ rk29_modem_exit();\r
+}\r
+\r
+module_init(mw100g_init);\r
+module_exit(mw100g_exit);\r
+\r
+MODULE_AUTHOR("lintao lintao@rock-chips.com");\r
+MODULE_DESCRIPTION("ROCKCHIP modem driver");\r
+MODULE_LICENSE("GPL");\r
+\r
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/stat.h> /* permission constants */
-
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-#include "rk29_modem.h"
-
-struct rk29_modem_t *g_rk29_modem = NULL;
-
-extern void rk29_host11_driver_enable(void);
-extern void rk29_host11_driver_disable(void);
-
-static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
-{
- struct rk29_modem_t *rk29_modem = g_rk29_modem;
-
- int new_mode = simple_strtoul(_buf, NULL, 16);
- printk("[%s] new_mode: %s\n", __func__, _buf);
-
- if(rk29_modem == NULL){
- printk("!!!! g_rk29_modem is NULL !!!!\n");
- return _count;
- }
-
- if(new_mode == rk29_modem->cur_mode){
- printk("[%s] current already in %d mode\n", __func__, new_mode);
- return _count;
- }
-
- switch(new_mode){
- case MODEM_DISABLE:
- if(rk29_modem->disable){
- printk("modem disable!\n");
-// rk29_host11_driver_disable();
- // mdelay(10);
- rk29_modem->disable();
- rk29_modem->cur_mode = new_mode;
- }
- break;
-
- case MODEM_ENABLE :
- if(rk29_modem->enable){
- printk("modem enable!\n");
-// rk29_host11_driver_enable();
-// mdelay(100);
- rk29_modem->enable();
- rk29_modem->cur_mode = new_mode;
- }
- break;
-
- case MODEM_SLEEP:
- if(rk29_modem->sleep){
- printk("modem sleep!\n");
- rk29_modem->sleep();
- rk29_modem->cur_mode = new_mode;
- }
- break;
-
- default:
- printk("[%s] invalid new mode: %d\n", __func__, new_mode);
- break;
- }
-
- return _count;
-}
-
-static ssize_t modem_status_read(struct class *cls, char *_buf)
-{
- struct rk29_modem_t *rk29_modem = g_rk29_modem;
-
-// printk("Modem type: %s, cur_mode = %d\n", rk29_modem->name, rk29_modem->cur_mode);
-
- return sprintf(_buf, "%d\n", rk29_modem->cur_mode);
-}
-
-static struct class *rk29_modem_class = NULL;
-static CLASS_ATTR(modem_status, 0666, modem_status_read, modem_status_write);
-
-int modem_is_turn_on()
-{
- return (g_rk29_modem->cur_mode != 0);
-}
-
-void turn_off_modem()
+#include <linux/vmalloc.h>\r
+#include <asm/io.h>\r
+#include <asm/sizes.h>\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <linux/delay.h>\r
+\r
+#include <linux/wakelock.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/gpio.h>\r
+#include <mach/board.h>\r
+\r
+#include "rk29_modem.h"\r
+\r
+struct rk29_modem_t *g_rk29_modem;\r
+//static struct wake_lock wakelock_bbwakeupap;\r
+static struct class *rk29_modem_class = NULL;\r
+static void rk29_modem_turnon(struct rk29_io_t *modem_power, int onoff);\r
+\r
+int rk29_modem_change_status(struct rk29_modem_t *rk29_modem, int status)\r
+{\r
+ int ret = 0;\r
+ switch(status)\r
+ {\r
+ case MODEM_DISABLE:\r
+ rk29_modem_turnon(rk29_modem->modem_power, 0);\r
+ break;\r
+ case MODEM_ENABLE :\r
+ rk29_modem_turnon(rk29_modem->modem_power, 1);\r
+ break;\r
+ case MODEM_SLEEP:\r
+ ret = -1;\r
+ case MODEM_WAKEUP:\r
+ ret = -1;\r
+ break;\r
+ }\r
+ \r
+ return ret;\r
+}\r
+\r
+static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)\r
+{\r
+ struct rk29_modem_t *rk29_modem = g_rk29_modem;\r
+ int ret = 0;\r
+ int new_state = simple_strtoul(_buf, NULL, 16);\r
+\r
+ if(rk29_modem == NULL){\r
+ printk("!!!! g_rk29_modem is NULL !!!!\n");\r
+ return _count;\r
+ }\r
+ \r
+ printk("[%s] statue change: %d -> %d\n", __func__, rk29_modem->status, new_state);\r
+\r
+ if(new_state == rk29_modem->status) return _count;\r
+\r
+\r
+ switch(new_state)\r
+ {\r
+ case MODEM_DISABLE:\r
+ if(rk29_modem->disable)\r
+ ret = rk29_modem->disable(rk29_modem);\r
+ else\r
+ ret = rk29_modem_change_status(rk29_modem, new_state);\r
+ break;\r
+ case MODEM_ENABLE :\r
+ if(rk29_modem->enable)\r
+ ret = rk29_modem->enable(rk29_modem);\r
+ else\r
+ ret = rk29_modem_change_status(rk29_modem, new_state);\r
+ break;\r
+ case MODEM_SLEEP:\r
+ if(rk29_modem->sleep)\r
+ ret = rk29_modem->sleep(rk29_modem);\r
+ else\r
+ ret = rk29_modem_change_status(rk29_modem, new_state);\r
+ break;\r
+ case MODEM_WAKEUP:\r
+ if(rk29_modem->wakeup)\r
+ ret = rk29_modem->wakeup(rk29_modem);\r
+ else\r
+ ret = rk29_modem_change_status(rk29_modem, new_state);\r
+ break;\r
+ default:\r
+ ret = -1;\r
+ printk("[%s] Invalid new status: %d\n", __func__, new_state);\r
+ break;\r
+ }\r
+\r
+ if( !ret ) rk29_modem->status = new_state;\r
+ \r
+ return _count;\r
+}\r
+\r
+static ssize_t modem_status_read(struct class *cls, char *_buf)\r
+{\r
+ struct rk29_modem_t *rk29_modem = g_rk29_modem;\r
+\r
+ return sprintf(_buf, "%d\n", rk29_modem->status);\r
+}\r
+static CLASS_ATTR(modem_status, 0666, modem_status_read, modem_status_write);\r
+\r
+int __devinit rk29_modem_suspend(struct platform_device *pdev, pm_message_t state)\r
{
- modem_status_write( NULL, "0", sizeof("0") );
+#ifdef CONFIG_PM\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ if( g_rk29_modem->suspend )\r
+ g_rk29_modem->suspend(pdev, state);\r
+ else\r
+ {\r
+ if(g_rk29_modem->ap_ready) // ±êÖ¾APÒѹÒÆð\r
+ gpio_direction_output(g_rk29_modem->ap_ready->io_addr, g_rk29_modem->ap_ready->disable);\r
+ }\r
+#endif\r
+ return 0;
}
-void turn_on_modem()
+int __devinit rk29_modem_resume(struct platform_device *pdev)\r
{
- modem_status_write( NULL, "1", sizeof("1") );
-}
-
-int rk29_modem_register(struct rk29_modem_t *rk29_modem){
- int ret = -1;
-
- if(rk29_modem == NULL)
- return -1;
-
-#if 1
- if(rk29_modem->enable) rk29_modem->enable();
-#else
- if(rk29_modem->disable) rk29_modem->disable();
-#endif
- rk29_modem_class = class_create(THIS_MODULE, "rk291x_modem");
- if(rk29_modem_class == NULL){
- printk("create class rk291x_modem failed!\n");
- goto err1;
- }
-
- ret = class_create_file(rk29_modem_class, &class_attr_modem_status);
- if(ret != 0){
- printk("create rk291x_modem class file failed!\n");
- goto err2;
- }
-
- g_rk29_modem = rk29_modem;
-
+#ifdef CONFIG_PM\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ if( g_rk29_modem->resume )\r
+ g_rk29_modem->resume(pdev);\r
+ else\r
+ {\r
+ if(g_rk29_modem->ap_ready) // ±êÖ¾APÒѻָ´\r
+ gpio_direction_output(g_rk29_modem->ap_ready->io_addr, g_rk29_modem->ap_ready->enable);\r
+ }\r
+#endif\r
return 0;
-
-err2:
- class_destroy(rk29_modem_class);
-err1:
- return ret;
-}
-
-void rk29_modem_unregister(struct rk29_modem_t *rk29_modem){
- /* disable 3G modem */
- if(rk29_modem->disable)
- rk29_modem->disable();
-
- class_remove_file(rk29_modem_class, &class_attr_modem_status);
- class_destroy(rk29_modem_class);
-
- rk29_modem_class = NULL;
-}
-
+}\r
+\r
+static irqreturn_t irq_bbwakeupap_handler(int irq, void *dev_id)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ irqreturn_t irqret = IRQ_NONE;\r
+ if( g_rk29_modem->irq_handler )\r
+ {\r
+ irqret = g_rk29_modem->irq_handler(irq, dev_id);\r
+ if( irqret != IRQ_NONE ) return irqret;\r
+ }\r
+\r
+ // ¾ßÌåÉ豸ûÓÐ irq_handler º¯Êý£¬»òÕßËüµÄirq_handlerº¯ÊýûÓд¦Àí¸Ã irq£¬ÔòʹÓÃ\r
+ // ÒÔÏµĹ«¹²irq´¦Àí.\r
+\r
+ return IRQ_HANDLED;\r
+}\r
+\r
+static void uninstall_irq(struct rk29_irq_t *irq)\r
+{\r
+ gpio_free(irq->irq_addr);\r
+}\r
+\r
+static int install_irq(struct rk29_irq_t *rk29_irq, const char* label)\r
+{\r
+ int ret;\r
+ int irq;\r
+ \r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ irq = gpio_to_irq(rk29_irq->irq_addr);\r
+ printk("%s: %d ==> %d\n", __func__, rk29_irq->irq_addr, irq);\r
+\r
+ ret = gpio_request(rk29_irq->irq_addr, label);\r
+ if (ret < 0) {\r
+ pr_err("%s: gpio_request(%d) failed\n", __func__, rk29_irq->irq_addr);\r
+ return ret;\r
+ }\r
+\r
+ gpio_direction_input(rk29_irq->irq_addr);\r
+ gpio_pull_updown(rk29_irq->irq_addr, 0);\r
+ ret = request_irq(irq, irq_bbwakeupap_handler, rk29_irq->irq_trigger, label, NULL);\r
+ if (ret < 0) {\r
+ pr_err("%s: request_irq(%d) failed\n", __func__, irq);\r
+ gpio_free(rk29_irq->irq_addr);\r
+ return ret;\r
+ }\r
+\r
+ enable_irq_wake(irq);\r
+ return 0;\r
+}\r
+\r
+// ¸ømodemÉϵç\r
+static void rk29_modem_turnon(struct rk29_io_t *modem_power, int onoff)\r
+{\r
+ if( modem_power )\r
+ gpio_direction_output(modem_power->io_addr, onoff?modem_power->enable:modem_power->disable);\r
+}\r
+\r
+/*\r
+ RK29 modem ͨÓõÄÉ豸³õʼ»¯º¯Êý\r
+ Ö÷ÒªÉèÖø÷¸öGPIOÒÔ¼°IRQµÄÉêÇëµÈ\r
+ */\r
+static int rk29_modem_dev_init(struct rk29_modem_t *rk29_modem)\r
+{\r
+ int ret=0;\r
+ \r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+// ÉêÇë¿ØÖÆmodemµçÔ´µÄGPIO\r
+ if( rk29_modem->modem_power )\r
+ {\r
+ ret = gpio_request(rk29_modem->modem_power->io_addr, "modem_power");\r
+ if(ret != 0)\r
+ {\r
+ gpio_free(rk29_modem->modem_power->io_addr);\r
+ printk(">>>>>> Modem power io request failed!\n");\r
+ return ret;\r
+ }\r
+ \r
+ // ÉèÖóõʼµÄmodem״̬\r
+ rk29_modem_change_status(rk29_modem, rk29_modem->status);\r
+ }\r
+\r
+// ÉêÇë¿ØÖÆAP¾ÍÐ÷״̬µÄGPIO\r
+ if( rk29_modem->ap_ready )\r
+ {\r
+ ret = gpio_request(rk29_modem->ap_ready->io_addr, "ap_ready");\r
+ if(ret != 0)\r
+ {\r
+ gpio_free(rk29_modem->ap_ready->io_addr);\r
+ printk(">>>>>> AP ready io request failed!\n");\r
+ return ret;\r
+ }\r
+\r
+ // ĬÈÏ AP is ready\r
+ gpio_direction_output(rk29_modem->ap_ready->io_addr, rk29_modem->ap_ready->enable);\r
+ }\r
+\r
+// ÉèÖà bb_wakeup_ap µÄirq£¬ÓÃÓÚap¹ÒÆðÖ®ºó£¬ÓÉbbÀ´»½ÐÑap\r
+ if( rk29_modem->bp_wakeup_ap )\r
+ {\r
+ ret = install_irq(rk29_modem->bp_wakeup_ap, "bb_wakeup_ap");\r
+ }\r
+ \r
+ wake_lock_init(&rk29_modem->wakelock_bbwakeupap, WAKE_LOCK_SUSPEND, "bb_wakeup_ap");\r
+\r
+ return ret;\r
+}\r
+\r
+/*\r
+ modemϵ硢ÊÍ·Ågpio wait_lock µÈ\r
+ */\r
+static void rk29_modem_dev_uninit(struct rk29_modem_t *rk29_modem)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ \r
+// ¸ømodemϵç\r
+ if( rk29_modem->modem_power )\r
+ rk29_modem_turnon(rk29_modem->modem_power, 0);\r
+\r
+// ÊÍ·ÅGPIO\r
+ if( rk29_modem->modem_power )\r
+ gpio_free(rk29_modem->modem_power->io_addr);\r
+\r
+ if(rk29_modem->ap_ready)\r
+ gpio_free(rk29_modem->ap_ready->io_addr);\r
+\r
+ if(rk29_modem->bp_wakeup_ap)\r
+ uninstall_irq(rk29_modem->bp_wakeup_ap);\r
+\r
+// ÊÍ·Å wake lock\r
+ wake_lock_destroy(&rk29_modem->wakelock_bbwakeupap);\r
+}\r
+\r
+/*\r
+ Çý¶¯¼ÓÔØ\r
+ */\r
+int rk29_modem_init(struct rk29_modem_t *rk29_modem)\r
+{\r
+ int retval = 0;\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+\r
+ retval = platform_driver_register(rk29_modem->driver);\r
+ if( retval )\r
+ {\r
+ printk("could not register rk29_modem!\n");\r
+ return retval;\r
+ }\r
+\r
+ rk29_modem_class = class_create(THIS_MODULE, "rk291x_modem");\r
+ if(rk29_modem_class == NULL){\r
+ printk("create class rk291x_modem failed!\n");\r
+ return -1;\r
+ }\r
+ retval = class_create_file(rk29_modem_class, &class_attr_modem_status);\r
+ if(retval != 0){\r
+ printk("create rk291x_modem class file failed!\n");\r
+ goto failed_create_class;\r
+ }\r
+ \r
+// ¶Ômodem³õʼ»¯\r
+ if( rk29_modem->dev_init )\r
+ retval = rk29_modem->dev_init(rk29_modem);\r
+ else\r
+ retval = rk29_modem_dev_init(rk29_modem);\r
+ \r
+ if( retval )\r
+ goto failed_device_init;\r
+\r
+ g_rk29_modem = rk29_modem;\r
+\r
+ return 0;\r
+\r
+failed_device_init:\r
+ platform_driver_unregister(rk29_modem->driver);\r
+\r
+failed_create_class:\r
+ class_destroy(rk29_modem_class);\r
+ \r
+ return retval;\r
+}\r
+\r
+/*\r
+ Í˳öÇý¶¯Ê±µ÷ÓÃ\r
+ Ä¿Ç°driverÊÇbuild-in£¬²»´æÔÚÍ˳öµÄÇé¿ö£¬²»»áµ÷Óõ½Õâ±ß\r
+ */\r
+void rk29_modem_exit(void)\r
+{\r
+ printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);\r
+ platform_driver_unregister(g_rk29_modem->driver);\r
+\r
+// ¶Ômodem·´³õʼ»¯\r
+ if( g_rk29_modem->dev_uninit )\r
+ g_rk29_modem->dev_uninit(g_rk29_modem);\r
+ else\r
+ rk29_modem_dev_uninit(g_rk29_modem);\r
+}\r
+\r
-#ifndef _rk29_MODEM_H
-#define _rk29_MODEM_H
-
-/* Modem states */
-#define MODEM_DISABLE 0
-#define MODEM_ENABLE 1
-#define MODEM_SLEEP 2
-#define MODEM_MAX_STATUS 3
-
-/*===================lintao@rock-chips====================*/
-#define G3_POWER_ON RK29_PIN6_PB1//GPIOPortB_Pin0
-//#define G3_POWER_ON_IOMUX_NAME GPIOB0_SPI0CSN1_MMC1PCA_NAME
-//#define G3_POWER_ON_IOMUX_MODE IOMUXA_GPIO0_B0
-#define G3_POWER_ENABLE GPIO_HIGH
-#define G3_POWER_DISABLE GPIO_LOW
-/*===================================================*/
-//#define G3_RADIO_ON_OFF GPIOPortG_Pin0
-//#define G3_RADIO_ON_OFF_IOMUX_NAME GPIOG0_UART0_MMC1DET_NAME
-//#define G3_RADIO_ON_OFF_IOMUX_MODE IOMUXA_GPIO1_C0
-//#define G3_RADIO_ENABLE GPIO_HIGH
-//#define G3_RADIO_DISABLE GPIO_LOW
-/*====================================================*/
-//#define G3_RESET GPIOPortG_Pin1
-//#define G3_RESET_IOMUX_NAME GPIOG1_UART0_MMC1WPT_NAME
-//#define G3_RESET_IOMUX_MODE IOMUXA_GPIO1_C1
-//#define G3_RESET_ENABLE GPIO_LOW
-//#define G3_RESET_DISABLE GPIO_HIGH
-/*====================================================*/
-struct rk29_modem_t {
- char *name;
- int cur_mode;
- int (*enable)(void);
- int (*disable)(void);
- int (*sleep)(void);
- int (*init)(void);
-};
-
-int rk29_modem_register(struct rk29_modem_t *rk29_modem);
-void rk29_modem_unregister(struct rk29_modem_t *rk29_modem);
-
-#endif
+#include <linux/platform_device.h>\r
+\r
+/* Modem states */\r
+#define MODEM_DISABLE 0\r
+#define MODEM_ENABLE 1\r
+#define MODEM_SLEEP 2\r
+#define MODEM_WAKEUP 3\r
+#define MODEM_MAX_STATUS 4\r
+\r
+struct rk29_io_t {\r
+ unsigned long io_addr;\r
+ unsigned long enable;\r
+ unsigned long disable;\r
+};\r
+\r
+struct rk29_irq_t {\r
+ unsigned long irq_addr;\r
+ unsigned long irq_trigger;\r
+};\r
+\r
+struct rk29_modem_t {\r
+ struct platform_driver *driver;\r
+ // ¿ØÖÆmodemµçÔ´µÄIO\r
+ struct rk29_io_t *modem_power;\r
+ // µ±AP¾ÍÐ÷»òÕßδ¾ÍÐ÷ʱ£¬Í¨¹ý ap_ready Õâ¸öIOÀ´Í¨ÖªBP¡£\r
+ struct rk29_io_t *ap_ready;\r
+ // µ±BP½ÓÊÕµ½¶ÌÐÅ»òÕßÀ´µçʱ£¬Í¨¹ý bp_wakeup_ap Õâ¸öIRQÀ´»½ÐÑAP\r
+ struct rk29_irq_t *bp_wakeup_ap;\r
+ // µ±Ç°modem״̬£¬Ä¿Ç°Ö»Óõ½MODEM_ENABLE(Éϵç)¡¢MODEM_DISABLE(ϵç)\r
+ // ͬʱ£¬statusµÄ³õʼֵҲ¾ö¶¨¿ª»úʱµÄmodemÊÇ·ñÉϵç\r
+ int status;\r
+ struct wake_lock wakelock_bbwakeupap;\r
+\r
+ // É豸³õʼ»¯º¯Êý, Ö÷ÒªÉèÖø÷¸öGPIOÒÔ¼°IRQµÄÉêÇëµÈ\r
+ int (*dev_init)(struct rk29_modem_t *driver);\r
+ int (*dev_uninit)(struct rk29_modem_t *driver);\r
+ irqreturn_t (*irq_handler)(int irq, void *dev_id);\r
+ int (*suspend)(struct platform_device *pdev, pm_message_t state);\r
+ int (*resume)(struct platform_device *pdev);\r
+\r
+ int (*enable)(struct rk29_modem_t *driver);\r
+ int (*disable)(struct rk29_modem_t *driver);\r
+ int (*sleep)(struct rk29_modem_t *driver);\r
+ int (*wakeup)(struct rk29_modem_t *driver);\r
+};\r
+\r
+void rk29_modem_exit(void);\r
+int rk29_modem_init(struct rk29_modem_t *rk29_modem);\r
+int rk29_modem_suspend(struct platform_device *pdev, pm_message_t state);\r
+int rk29_modem_resume(struct platform_device *pdev);\r
+\r