From d24c73a5fd0bd1eff25503630c6a4b72c8779e89 Mon Sep 17 00:00:00 2001 From: zzy Date: Mon, 13 May 2013 11:49:36 +0800 Subject: [PATCH] add SEW290 3G modem --- arch/arm/mach-rk30/board-rk30-phonepad.c | 46 ++-- drivers/misc/bp/chips/Kconfig | 3 + drivers/misc/bp/chips/Makefile | 1 + drivers/misc/bp/chips/sew290.c | 258 +++++++++++++++++++++++ drivers/usb/serial/option.c | 2 + drivers/usb/serial/usb-serial.c | 3 +- include/linux/bp-auto.h | 1 + 7 files changed, 300 insertions(+), 14 deletions(-) mode change 100755 => 100644 arch/arm/mach-rk30/board-rk30-phonepad.c create mode 100644 drivers/misc/bp/chips/sew290.c mode change 100755 => 100644 drivers/usb/serial/option.c mode change 100755 => 100644 drivers/usb/serial/usb-serial.c diff --git a/arch/arm/mach-rk30/board-rk30-phonepad.c b/arch/arm/mach-rk30/board-rk30-phonepad.c old mode 100755 new mode 100644 index c9e157fb5cb6..dd47529cfc15 --- a/arch/arm/mach-rk30/board-rk30-phonepad.c +++ b/arch/arm/mach-rk30/board-rk30-phonepad.c @@ -1427,21 +1427,41 @@ static int bp_io_deinit(void) return 0; } - -struct bp_platform_data bp_auto_info = { - .board_id = BOARD_ID_C8003, - .bp_id = BP_ID_MT6229, - .init_platform_hw = bp_io_init, - .exit_platform_hw = bp_io_deinit, - .bp_power = RK30_PIN6_PB2, // 3g_power - .bp_en = RK30_PIN2_PB6, // 3g_en - .bp_usb_en = RK30_PIN2_PC0, //W_disable - .bp_uart_en = RK30_PIN2_PC1, //EINT9 - .bp_wakeup_ap = RK30_PIN6_PA1, // - .ap_ready = RK30_PIN2_PB7, // - .gpio_valid = 0, //don't use this gpios +static int bp_id_get(void) +{ + int bp_id = 0; + #if defined(CONFIG_BP_AUTO_MT6229) + bp_id = BP_ID_MT6229; + #elif defined(CONFIG_BP_AUTO_MU509) + bp_id = BP_ID_MU509; + #elif defined(CONFIG_BP_AUTO_MW100) + bp_id = BP_ID_MW100; + #elif defined(CONFIG_BP_AUTO_MI700) + bp_id = BP_ID_MI700; + #endif + #elif defined(CONFIG_BP_AUTO_MI700) + bp_id = BP_ID_SEW290; + #endif + return bp_id; +} + +struct bp_platform_data bp_auto_info = { + .init_platform_hw = bp_io_init, + .exit_platform_hw = bp_io_deinit, + .get_bp_id = bp_id_get, + .bp_power = RK30_PIN6_PB2, // 3g_power,¸ù¾Ýʵ¼Ê½ÓÏßÅäÖà + .bp_en = BP_UNKNOW_DATA, // 3g_en + .bp_reset = BP_UNKNOW_DATA, //¸ù¾Ýʵ¼ÊÅäÖà + .bp_usb_en = BP_UNKNOW_DATA, //W_disable + .bp_uart_en = BP_UNKNOW_DATA, //EINT9 + .bp_wakeup_ap = RK30_PIN2_PC4, //¸ù¾Ýʵ¼Ê½ÓÏßÅäÖà + .ap_wakeup_bp = RK30_PIN2_PC4, //¸ù¾Ýʵ¼ÊÅäÖà + .ap_ready = BP_UNKNOW_DATA, // + .bp_ready = BP_UNKNOW_DATA, + .gpio_valid = 1, //if 1:gpio is define in bp_auto_info,if 0:is not use gpio in bp_auto_info }; + struct platform_device device_bp_auto = { .name = "bp-auto", .id = -1, diff --git a/drivers/misc/bp/chips/Kconfig b/drivers/misc/bp/chips/Kconfig index 4b095c214060..29e63cc71fee 100755 --- a/drivers/misc/bp/chips/Kconfig +++ b/drivers/misc/bp/chips/Kconfig @@ -16,3 +16,6 @@ config BP_AUTO_C66A bool "modem c66a" default n +config BP_AUTO_SEW290 +bool "modem sew290" + default n diff --git a/drivers/misc/bp/chips/Makefile b/drivers/misc/bp/chips/Makefile index 87d0d739ea78..12fd8870b140 100755 --- a/drivers/misc/bp/chips/Makefile +++ b/drivers/misc/bp/chips/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_BP_AUTO) += sc6610.o obj-$(CONFIG_BP_AUTO) += m51.o obj-$(CONFIG_BP_AUTO) += mtk6250.o obj-$(CONFIG_BP_AUTO) += c66a.o +obj-$(CONFIG_BP_AUTO) += sew290.o diff --git a/drivers/misc/bp/chips/sew290.c b/drivers/misc/bp/chips/sew290.c new file mode 100644 index 000000000000..b456627ed199 --- /dev/null +++ b/drivers/misc/bp/chips/sew290.c @@ -0,0 +1,258 @@ +/* drivers/misc/bp/chips/mu509.c + * + * Copyright (C) 2012-2015 ROCKCHIP. + * Author: luowei + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#if 0 +#define DBG(x...) printk(x) + +#else +#define DBG(x...) +#endif + + +/****************operate according to bp chip:start************/ +static int bp_active(struct bp_private_data *bp, int enable) +{ + printk("<-----SEW290 bp_active-------->\n"); + if(enable) + { + gpio_set_value(bp->ops->bp_power, GPIO_LOW); + msleep(1000); + gpio_set_value(bp->ops->bp_power, GPIO_HIGH); + msleep(2500); + gpio_set_value(bp->ops->bp_power, GPIO_LOW); + gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW); + } + else + { + gpio_set_value(bp->ops->bp_en, GPIO_HIGH); + msleep(4000); + gpio_set_value(bp->ops->bp_en, GPIO_LOW); + + } + + return 0; +} + +static int ap_wake_bp(struct bp_private_data *bp, int wake) +{ + int result = 0; + + gpio_set_value(bp->ops->ap_wakeup_bp, wake); + + return result; + +} + +static void ap_wake_bp_work(struct work_struct *work) +{ + struct delayed_work *wakeup_work = container_of(work, struct delayed_work, work); + struct bp_private_data *bp = container_of(wakeup_work, struct bp_private_data, wakeup_work); + + if(bp->suspend_status) + { + if(bp->ops->ap_wake_bp) + bp->ops->ap_wake_bp(bp, 0); + } + else + { + if(bp->ops->ap_wake_bp) + bp->ops->ap_wake_bp(bp, 1); + } +} + + +static int bp_init(struct bp_private_data *bp) +{ + printk("<-----SEW290 bp_init-------->\n"); + gpio_direction_output(bp->ops->bp_power, GPIO_HIGH); + gpio_set_value(bp->ops->bp_power, GPIO_HIGH); + msleep(500); + //if(bp->ops->active) + // bp->ops->active(bp, 1); + gpio_direction_input(bp->ops->bp_wakeup_ap); + gpio_direction_output(bp->ops->bp_reset, GPIO_LOW); + gpio_direction_output(bp->ops->bp_en, GPIO_LOW); + gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_HIGH); + INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work); + return 0; +} + +static int bp_reset(struct bp_private_data *bp) +{ +// gpio_direction_output(bp->ops->bp_power, GPIO_HIGH); +// msleep(500); + gpio_set_value(bp->ops->bp_reset, GPIO_HIGH); + msleep(100); + gpio_set_value(bp->ops->bp_reset, GPIO_LOW); + gpio_set_value(bp->ops->bp_en, GPIO_LOW); + msleep(1000); + gpio_set_value(bp->ops->bp_en, GPIO_HIGH); + msleep(700); + gpio_set_value(bp->ops->bp_en, GPIO_LOW); + gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW); + + return 0; +} + +static int bp_wake_ap(struct bp_private_data *bp) +{ + printk("<-----SEW290 bp_wake_ap-------->\n"); + + bp->suspend_status = 0; + wake_lock_timeout(&bp->bp_wakelock, 20* HZ); + + return 0; +} + + +static int bp_shutdown(struct bp_private_data *bp) +{ + int result = 0; + + if(bp->ops->active) + bp->ops->active(bp, 0); + gpio_set_value(bp->ops->bp_power, GPIO_LOW); + cancel_delayed_work_sync(&bp->wakeup_work); + + return result; +} + + + +static int bp_suspend(struct bp_private_data *bp) +{ + + printk("<-----SEW290 bp_suspend-------->\n"); + + bp->suspend_status = 1; + gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW); + + return 0; +} + + + + +static int bp_resume(struct bp_private_data *bp) +{ + + printk("<-----SEW290 bp_resume-------->\n"); + bp->suspend_status = 0; + gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH); + + + return 0; +} + + +struct bp_operate bp_sew290_ops = { + .name = "sew290", + .bp_id = BP_ID_SEW290, + .bp_bus = BP_BUS_TYPE_USB_UART, + .bp_pid = 0, + .bp_vid = 0, + .bp_power = BP_UNKNOW_DATA, // 3g_power + .bp_en = BP_UNKNOW_DATA, // 3g_en + .bp_reset = BP_UNKNOW_DATA, + .ap_ready = BP_UNKNOW_DATA, // + .bp_ready = BP_UNKNOW_DATA, + .ap_wakeup_bp = RK30_PIN2_PC5, + .bp_wakeup_ap = RK30_PIN2_PC4, // + .bp_uart_en = BP_UNKNOW_DATA, //EINT9 + .bp_usb_en = BP_UNKNOW_DATA, //W_disable + .trig = IRQF_TRIGGER_RISING, + + .active = bp_active, + .init = bp_init, + .reset = bp_reset, + .ap_wake_bp = ap_wake_bp, + .bp_wake_ap = bp_wake_ap, + .shutdown = bp_shutdown, + .read_status = NULL, + .write_status = NULL, + .suspend = bp_suspend, + .resume = bp_resume, + .misc_name = NULL, + .private_miscdev = NULL, +}; + +/****************operate according to bp chip:end************/ + +//function name should not be changed +static struct bp_operate *bp_get_ops(void) +{ + return &bp_sew290_ops; +} + +static int __init bp_sew290_init(void) +{ + struct bp_operate *ops = bp_get_ops(); + int result = 0; + result = bp_register_slave(NULL, NULL, bp_get_ops); + if(result) + { + return result; + } + + if(ops->private_miscdev) + { + result = misc_register(ops->private_miscdev); + if (result < 0) { + printk("%s:misc_register err\n",__func__); + return result; + } + } + + DBG("%s\n",__func__); + return result; +} + +static void __exit bp_sew290_exit(void) +{ + //struct bp_operate *ops = bp_get_ops(); + bp_unregister_slave(NULL, NULL, bp_get_ops); +} + + +subsys_initcall(bp_sew290_init); +module_exit(bp_sew290_exit); + diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c old mode 100755 new mode 100644 index e24a7794c792..6f1d6c1b841a --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1331,6 +1331,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(0x1d09, 0x1010) }, { USB_DEVICE(0x19D2, 0x1181) }, { USB_DEVICE(0x2020, 0x1005)},//S830 3G Dongle + { USB_DEVICE(0x1782, 0x0002)},//U7501 + { USB_DEVICE(0x21f5, 0x2012) },//SEW290 // cmy end //xxh { USB_DEVICE_AND_INTERFACE_INFO(0x05c6, 0x1000, 0xff, 0xff, 0xff) }, diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c old mode 100755 new mode 100644 index a3ea0ac197dd..83e6259314d2 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1075,9 +1075,10 @@ int usb_serial_probe(struct usb_interface *interface, } #ifdef CONFIG_BP_AUTO int bp_id = get_current_bp_id(); - if (((le16_to_cpu(dev->descriptor.idVendor) == 0x12D1 ) && (le16_to_cpu(dev->descriptor.idProduct) == 0x1001) && (bp_id == 2)) + if (((le16_to_cpu(dev->descriptor.idVendor) == 0x1782 ) && (le16_to_cpu(dev->descriptor.idProduct) == 0x0002) && (bp_id == 2)) || ((le16_to_cpu(dev->descriptor.idVendor) == 0x19f5) && (le16_to_cpu(dev->descriptor.idProduct) == 0x9013) && (bp_id == 4)) || ((le16_to_cpu(dev->descriptor.idVendor) == 0x0E8D) && (le16_to_cpu(dev->descriptor.idProduct) == 0x00A2) && (bp_id == 1)) + || ((le16_to_cpu(dev->descriptor.idVendor) == 0x21f5) && (le16_to_cpu(dev->descriptor.idProduct) == 0x2012) && (bp_id == 10)) ){ BP_USB =1; diff --git a/include/linux/bp-auto.h b/include/linux/bp-auto.h index d0a9eb245171..76d89c2a1390 100644 --- a/include/linux/bp-auto.h +++ b/include/linux/bp-auto.h @@ -35,6 +35,7 @@ enum bp_id{ BP_ID_M50, //spreadtrum RDA GSM BP_ID_MT6250, //ZINN M50 EDGE BP_ID_C66A, //zhongben + BP_ID_SEW290, //SCV SEW290 WCDMA BP_ID_NUM, }; -- 2.34.1