From d6f984c58956460c8c9bb08d5efcdadf228f2cf0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E8=B5=B5=E5=AD=90=E5=88=9D?= Date: Tue, 24 May 2011 09:50:56 +0800 Subject: [PATCH] TCL-PHONE-PAD:add mu509 --- arch/arm/configs/rk29_phonepadsdk_defconfig | 1 + arch/arm/mach-rk29/board-rk29phonepadsdk.c | 37 +++ drivers/misc/Kconfig | 4 + drivers/misc/Makefile | 1 + drivers/misc/mu509.c | 316 ++++++++++++++++++++ drivers/usb/serial/option.c | 9 + include/linux/mu509.h | 24 ++ 7 files changed, 392 insertions(+) mode change 100755 => 100644 arch/arm/mach-rk29/board-rk29phonepadsdk.c mode change 100755 => 100644 drivers/misc/Kconfig mode change 100755 => 100644 drivers/misc/Makefile create mode 100644 drivers/misc/mu509.c create mode 100644 include/linux/mu509.h diff --git a/arch/arm/configs/rk29_phonepadsdk_defconfig b/arch/arm/configs/rk29_phonepadsdk_defconfig index 8bd01373a3f4..37ffb0994648 100755 --- a/arch/arm/configs/rk29_phonepadsdk_defconfig +++ b/arch/arm/configs/rk29_phonepadsdk_defconfig @@ -822,6 +822,7 @@ CONFIG_APANIC_PLABEL="kpanic" # CONFIG_STE is not set # CONFIG_MTK23D is not set # CONFIG_C2PORT is not set +CONFIG_MU509=y # # EEPROM support diff --git a/arch/arm/mach-rk29/board-rk29phonepadsdk.c b/arch/arm/mach-rk29/board-rk29phonepadsdk.c old mode 100755 new mode 100644 index 7f1cd7ffe807..390110d0dbf0 --- a/arch/arm/mach-rk29/board-rk29phonepadsdk.c +++ b/arch/arm/mach-rk29/board-rk29phonepadsdk.c @@ -52,6 +52,9 @@ #include #include "devices.h" +#if defined(CONFIG_MU509) +#include +#endif #include "../../../drivers/input/touchscreen/xpt2046_cbn_ts.h" #ifdef CONFIG_VIDEO_RK29 @@ -902,6 +905,37 @@ static struct platform_device rk29_device_pwm_regulator = { #endif +#if defined(CONFIG_MU509) +static int mu509_io_init(void) +{ + + return 0; +} + +static int mu509_io_deinit(void) +{ + + return 0; +} + +struct rk29_mu509_data rk29_mu509_info = { + .io_init = mu509_io_init, + .io_deinit = mu509_io_deinit, + .bp_power = RK29_PIN6_PB1,//RK29_PIN0_PB4, + .bp_power_active_low = 1, + .bp_reset = RK29_PIN6_PC7,//RK29_PIN0_PB3, + .bp_reset_active_low = 1, + .bp_wakeup_ap = RK29_PIN0_PA4,//RK29_PIN0_PC2, + .ap_wakeup_bp = RK29_PIN2_PB3,//RK29_PIN0_PB0, +}; +struct platform_device rk29_device_mu509 = { + .name = "mu509", + .id = -1, + .dev = { + .platform_data = &rk29_mu509_info, + } + }; +#endif /***************************************************************************************** * SDMMC devices *****************************************************************************************/ @@ -1284,6 +1318,9 @@ static struct platform_device *devices[] __initdata = { &rk29sdk_rfkill, #endif +#if defined(CONFIG_MU509) + &rk29_device_mu509, +#endif #ifdef CONFIG_MTD_NAND_RK29 &rk29_device_nand, #endif diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig old mode 100755 new mode 100644 index f4310a51125c..b47b6b51cfde --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -296,6 +296,10 @@ config FM580X bool "FM rda580x driver" default n +config MU509 + bool "MU509 modem control driver" + default n + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile old mode 100755 new mode 100644 index 7a05b09c5fb1..73819025e527 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_WL127X_RFKILL) += wl127x-rfkill.o obj-$(CONFIG_APANIC) += apanic.o obj-$(CONFIG_MTK23D) += mtk23d.o obj-$(CONFIG_FM580X) += fm580x.o +obj-$(CONFIG_MU509) += mu509.o obj-$(CONFIG_STE) += ste.o obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem/ obj-$(CONFIG_GPS_GNS7560) += gps/ diff --git a/drivers/misc/mu509.c b/drivers/misc/mu509.c new file mode 100644 index 000000000000..e226ebbcad53 --- /dev/null +++ b/drivers/misc/mu509.c @@ -0,0 +1,316 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +//#include +//#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +#define DEBUG +#ifdef DEBUG +#define MODEMDBG(x...) printk(x) +#else +#define MODEMDBG(fmt,argss...) +#endif +#define SLEEP 1 +#define READY 0 +#define MU509_RESET 0x01 +/* +struct rk29_mu509_data rk29_mu509_info = { + .io_init = mu509_io_init, + .io_deinit = mu509_io_deinit, + .bp_power = RK29_PIN6_PB1,//RK29_PIN0_PB4, + .bp_power_active_low = 1, + .bp_reset = RK29_PIN6_PC7,//RK29_PIN0_PB3, + .bp_reset_active_low = 1, + .bp_wakeup_ap = RK29_PIN0_PA4,//RK29_PIN0_PC2, + .ap_wakeup_bp = RK29_PIN2_PB3,//RK29_PIN0_PB0, +}; +*/ +static struct wake_lock modem_wakelock; +#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_FALLING +//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING +struct rk29_mu509_data *gpdata = NULL; +static int do_wakeup_irq = 0; + +static void ap_wakeup_bp(struct platform_device *pdev, int wake) +{ + struct rk29_mu509_data *pdata = pdev->dev.platform_data; + //struct modem_dev *mu509_data = platform_get_drvdata(pdev); + MODEMDBG("ap_wakeup_bp\n"); + + gpio_set_value(pdata->ap_wakeup_bp, wake); + +} +/* +static void bpwakeup_work_func_work(struct work_struct *work) +{ + struct modem_dev *bdata = container_of(work, struct modem_dev, work); + wake_lock_timeout(&modem_wakelock, 10 * HZ); + MODEMDBG("%s\n", __FUNCTION__); + +}*/ +/*static irqreturn_t bpwakeup_work_func(int irq, void *data) +{ + struct modem_dev *mu509_data = (struct modem_dev *)data; + + MODEMDBG("bpwakeup_work_func\n"); + wake_lock_timeout(&modem_wakelock, 10 * HZ); + return IRQ_HANDLED; +}*/ +/*static irqreturn_t bp_apwakeup_work_func(int irq, void *data) +{ + MODEMDBG("bp_apwakeup_work_func\n"); + return IRQ_HANDLED; +}*/ +extern void rk28_send_wakeup_key(void); + +static void do_wakeup(struct work_struct *work) +{ + printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__); + rk28_send_wakeup_key(); +} + +static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup); +static irqreturn_t detect_irq_handler(int irq, void *dev_id) +{ + if(do_wakeup_irq) + { + do_wakeup_irq = 0; + printk("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__); + wake_lock_timeout(&modem_wakelock, 10 * HZ); + schedule_delayed_work(&wakeup_work, HZ / 10); + } + return IRQ_HANDLED; +} +int modem_poweron_off(int on_off) +{ + struct rk29_mu509_data *pdata = gpdata; + //gpio_set_value(pdata->bp_power,0); + + if(on_off) + { + printk("modem_poweron\n"); + gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH); + mdelay(300); + gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW); + msleep(4000); + gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW); + } + else + { + printk("modem_poweroff\n"); + gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH); + mdelay(100); + gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW); + } + return 0; +} +static int power_on =1; +static int mu509_open(struct inode *inode, struct file *file) +{ + //struct rk29_mu509_data *pdata = gpdata; + //struct platform_data *pdev = container_of(pdata, struct device, platform_data); + + MODEMDBG("modem_open\n"); + modem_poweron_off(1); + //int ret = 0; +/* if(power_on) + { + power_on = 0; + modem_poweron_off(1); + #if 1 + rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT); + rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN); + rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N); + rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N); + #endif + } + device_init_wakeup(&pdev, 1); +*/ + printk("%s\n",__FUNCTION__); + return 0; +} + +static int mu509_release(struct inode *inode, struct file *file) +{ + MODEMDBG("mu509_release\n"); + return 0; +} + +static int mu509_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg) +{ + struct rk29_mu509_data *pdata = gpdata; + //int i; + //void __user *argp = (void __user *)arg; + printk("mu509_ioctl\n"); + switch(cmd) + { + case MU509_RESET: + gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_LOW:GPIO_HIGH); + mdelay(100); + gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_LOW:GPIO_HIGH); + mdelay(300); + gpio_set_value(pdata->bp_reset, pdata->bp_reset_active_low? GPIO_HIGH:GPIO_LOW); + msleep(4000); + gpio_set_value(pdata->bp_power, pdata->bp_power_active_low? GPIO_HIGH:GPIO_LOW); + break; + default: + break; + } + return 0; +} + +static struct file_operations mu509_fops = { + .owner = THIS_MODULE, + .open = mu509_open, + .release = mu509_release, + .ioctl = mu509_ioctl +}; + +static struct miscdevice mu509_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = MODEM_NAME, + .fops = &mu509_fops +}; + +static int mu509_probe(struct platform_device *pdev) +{ + struct rk29_mu509_data *pdata = gpdata = pdev->dev.platform_data; + struct modem_dev *mu509_data = NULL; + int result, irq = 0; + + MODEMDBG("mu509_probe\n"); + power_on =1; + modem_poweron_off(1); + mu509_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL); + if(mu509_data == NULL) + { + printk("failed to request mu509_data\n"); + goto err2; + } + platform_set_drvdata(pdev, mu509_data); + + result = gpio_request(pdata->ap_wakeup_bp, "mu509"); + if (result) { + printk("failed to request AP_BP_WAKEUP gpio\n"); + goto err1; + } + irq = gpio_to_irq(pdata->bp_wakeup_ap); + enable_irq_wake(irq); + if(irq < 0) + { + gpio_free(pdata->bp_wakeup_ap); + printk("failed to request bp_wakeup_ap\n"); + } + result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap"); + if (result < 0) { + printk("%s: gpio_request(%d) failed\n", __func__, pdata->bp_wakeup_ap); + } + wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap"); + gpio_direction_output(pdata->ap_wakeup_bp, 1); + gpio_direction_input(pdata->bp_wakeup_ap); + gpio_pull_updown(pdata->bp_wakeup_ap, 1); + result = request_irq(irq, detect_irq_handler, IRQ_BB_WAKEUP_AP_TRIGGER, "bp_wakeup_ap", NULL); + if (result < 0) { + printk("%s: request_irq(%d) failed\n", __func__, irq); + gpio_free(pdata->bp_wakeup_ap); + goto err0; + } + enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap)); + printk("%s: request_irq(%d) success\n", __func__, irq); + result = misc_register(&mu509_misc); + if(result) + { + MODEMDBG("misc_register err\n"); + } + return result; +err0: + cancel_work_sync(&mu509_data->work); + gpio_free(pdata->bp_wakeup_ap); +err1: + gpio_free(pdata->ap_wakeup_bp); +err2: + kfree(mu509_data); + return 0; +} + +int mu509_suspend(struct platform_device *pdev) +{ + do_wakeup_irq = 1; + //struct rk29_mu509_data *pdata = pdev->dev.platform_data; + printk("------------mu509_suspend"); + MODEMDBG("%s \n", __FUNCTION__); + ap_wakeup_bp(pdev, 0); + return 0; +} + +int mu509_resume(struct platform_device *pdev) +{ + //struct rk29_mu509_data *pdata = pdev->dev.platform_data; + printk("-------------mu509_resume"); + MODEMDBG("%s \n", __FUNCTION__); + ap_wakeup_bp(pdev, 1); + return 0; +} + +void mu509_shutdown(struct platform_device *pdev, pm_message_t state) +{ + struct rk29_mu509_data *pdata = pdev->dev.platform_data; + struct modem_dev *mu509_data = platform_get_drvdata(pdev); + + MODEMDBG("%s \n", __FUNCTION__); + + cancel_work_sync(&mu509_data->work); + gpio_free(pdata->bp_power); + gpio_free(pdata->bp_reset); + gpio_free(pdata->ap_wakeup_bp); + gpio_free(pdata->bp_wakeup_ap); + kfree(mu509_data); +} + +static struct platform_driver mu509_driver = { + .probe = mu509_probe, + .shutdown = mu509_shutdown, + .suspend = mu509_suspend, + .resume = mu509_resume, + .driver = { + .name = "mu509", + .owner = THIS_MODULE, + }, +}; + +static int __init mu509_init(void) +{ + printk("-----%s----------zzc\n",__FUNCTION__); + return platform_driver_register(&mu509_driver); +} + +static void __exit mu509_exit(void) +{ + MODEMDBG("mu509_exit\n"); + platform_driver_unregister(&mu509_driver); +} + +module_init(mu509_init); + +module_exit(mu509_exit); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 325750a3bf38..27bccb282897 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -383,6 +383,12 @@ static int option_resume(struct usb_serial *serial); /* Celot products */ #define CELOT_VENDOR_ID 0x211f #define CELOT_PRODUCT_CT680M 0x6801 +/* leadcore LC1808*/ +#define LEADCORE_VENDOR_ID 0x1ab7 +#define LEADCORE_PRODUCT_LC1808 0x2200 +/*չѶģ×é*/ +#define SC8800G_VENDOR_ID 0x067b +#define SC8800G_PRODUCT_ID 0x2303 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, @@ -416,6 +422,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, + { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600)}, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, @@ -907,6 +914,8 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, + { USB_DEVICE(LEADCORE_VENDOR_ID, LEADCORE_PRODUCT_LC1808) }, //zzc + { USB_DEVICE(SC8800G_VENDOR_ID,SC8800G_PRODUCT_ID)}, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ diff --git a/include/linux/mu509.h b/include/linux/mu509.h new file mode 100644 index 000000000000..8db5ac2286c7 --- /dev/null +++ b/include/linux/mu509.h @@ -0,0 +1,24 @@ +#include +#include +#include + +struct modem_dev +{ + const char *name; + struct miscdevice miscdev; + struct work_struct work; +}; + +/* 耳机数据结构体 */ +struct rk29_mu509_data { + int (*io_init)(void); + int (*io_deinit)(void); + unsigned int bp_power; + unsigned int bp_power_active_low; + unsigned int bp_reset; + unsigned int bp_reset_active_low; + unsigned int bp_wakeup_ap; + unsigned int ap_wakeup_bp; +}; + +#define MODEM_NAME "mu509" -- 2.34.1