mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
TCL-PHONE-PAD:add mu509
This commit is contained in:
@@ -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
|
||||
|
||||
37
arch/arm/mach-rk29/board-rk29phonepadsdk.c
Executable file → Normal file
37
arch/arm/mach-rk29/board-rk29phonepadsdk.c
Executable file → Normal file
@@ -52,6 +52,9 @@
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include "devices.h"
|
||||
#if defined(CONFIG_MU509)
|
||||
#include <linux/mu509.h>
|
||||
#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
|
||||
|
||||
4
drivers/misc/Kconfig
Executable file → Normal file
4
drivers/misc/Kconfig
Executable file → Normal file
@@ -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"
|
||||
|
||||
1
drivers/misc/Makefile
Executable file → Normal file
1
drivers/misc/Makefile
Executable file → Normal file
@@ -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/
|
||||
|
||||
316
drivers/misc/mu509.c
Normal file
316
drivers/misc/mu509.c
Normal file
@@ -0,0 +1,316 @@
|
||||
#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 <mach/spi_fpga.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/wait.h>
|
||||
//#include <linux/android_power.h>
|
||||
//#include <asm/arch/gpio_extend.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mu509.h>
|
||||
|
||||
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);
|
||||
@@ -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
|
||||
/*չѶģ<D1B6><C4A3>*/
|
||||
#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 */
|
||||
|
||||
|
||||
24
include/linux/mu509.h
Normal file
24
include/linux/mu509.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/miscdevice.h>
|
||||
|
||||
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"
|
||||
Reference in New Issue
Block a user