kernel for u7501 3G modem

This commit is contained in:
zzy
2013-05-21 14:45:03 +08:00
parent baf38c2cb3
commit e678c7499e
4 changed files with 266 additions and 1 deletions

View File

@@ -19,3 +19,6 @@ bool "modem c66a"
config BP_AUTO_SEW290
bool "modem sew290"
default n
config BP_AUTO_U7501
bool "modem u7501"
default n

View File

@@ -7,3 +7,4 @@ obj-$(CONFIG_BP_AUTO) += m51.o
obj-$(CONFIG_BP_AUTO) += mtk6250.o
obj-$(CONFIG_BP_AUTO) += c66a.o
obj-$(CONFIG_BP_AUTO) += sew290.o
obj-$(CONFIG_BP_AUTO) += u7501.o

View File

@@ -0,0 +1,261 @@
/* drivers/misc/bp/chips/U7501.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* 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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/earlysuspend.h>
#include <linux/bp-auto.h>
#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("<-----U7501 bp_active-------->\n");
if(enable)
{
printk("<-----U7501 bp_active---enable---HIGH-->\n");
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_HIGH);
}
else
{
printk("<-----U7501 bp_active---disenable----->\n");
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)
{
printk("<-----U7501 ap_wake_bp-------->\n");
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("<-----U7501 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("<-----U7501 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("<-----U7501 bp_suspend---000000----->\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("<-----U7501 bp_resume-----hhhh--->\n");
bp->suspend_status = 0;
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_HIGH);
return 0;
}
struct bp_operate bp_U7501_ops = {
.name = "U7501",
.bp_id = BP_ID_U7501,
.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_PC4,
.bp_wakeup_ap = RK30_PIN2_PC5, //
.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_U7501_ops;
}
static int __init bp_U7501_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_U7501_exit(void)
{
//struct bp_operate *ops = bp_get_ops();
bp_unregister_slave(NULL, NULL, bp_get_ops);
}
subsys_initcall(bp_U7501_init);
module_exit(bp_U7501_exit);

View File

@@ -1075,7 +1075,7 @@ 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) == 0x1782 ) && (le16_to_cpu(dev->descriptor.idProduct) == 0x0002) && (bp_id == 2))
if (((le16_to_cpu(dev->descriptor.idVendor) == 0x1782 ) && (le16_to_cpu(dev->descriptor.idProduct) == 0x0002) && (bp_id == 12))
|| ((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))