add mt6229 for rk30

This commit is contained in:
赵子初
2012-07-10 11:22:48 +08:00
parent a823ab919a
commit 9f1e202b42
7 changed files with 439 additions and 1 deletions

View File

@@ -57,6 +57,9 @@
#if defined(CONFIG_MW100)
#include <linux/mw100.h>
#endif
#if defined(CONFIG_MT6229)
#include <linux/mt6229.h>
#endif
#if defined(CONFIG_ANDROID_TIMED_GPIO)
#include "../../../drivers/staging/android/timed_gpio.h"
#endif
@@ -739,6 +742,7 @@ static int mw100_io_deinit(void)
struct rk29_mw100_data rk29_mw100_info = {
.io_init = mw100_io_init,
.io_deinit = mw100_io_deinit,
.modem_power_en = RK30_PIN6_PB2,
.bp_power = RK30_PIN2_PB6,
.bp_reset = RK30_PIN4_PD2,
.ap_wakeup_bp = RK30_PIN2_PB7,
@@ -752,6 +756,39 @@ struct platform_device rk29_device_mw100 = {
}
};
#endif
#if defined(CONFIG_MT6229)
static int mt6229_io_init(void)
{
rk30_mux_api_set(GPIO2B6_LCDC1DATA14_SMCADDR18_TSSYNC_NAME, GPIO2B_GPIO2B6);
rk30_mux_api_set(GPIO4D2_SMCDATA10_TRACEDATA10_NAME, GPIO4D_GPIO4D2);
rk30_mux_api_set(GPIO2B7_LCDC1DATA15_SMCADDR19_HSADCDATA7_NAME, GPIO2B_GPIO2B7);
rk30_mux_api_set(GPIO2C0_LCDCDATA16_GPSCLK_HSADCCLKOUT_NAME, GPIO2C_GPIO2C0);
return 0;
}
static int mt6229_io_deinit(void)
{
return 0;
}
struct rk29_mt6229_data rk29_mt6229_info = {
.io_init = mt6229_io_init,
.io_deinit = mt6229_io_deinit,
.modem_power_en = RK30_PIN6_PB2,
.bp_power = RK30_PIN2_PB7,//RK30_PIN2_PB6,
.bp_reset = RK30_PIN4_PD2,
.ap_wakeup_bp = RK30_PIN2_PC0,
.bp_wakeup_ap = RK30_PIN6_PA0,
};
struct platform_device rk29_device_mt6229 = {
.name = "mt6229",
.id = -1,
.dev = {
.platform_data = &rk29_mt6229_info,
}
};
#endif
/*MMA8452 gsensor*/
#if defined (CONFIG_GS_MMA8452)
@@ -1357,6 +1394,9 @@ static struct platform_device *devices[] __initdata = {
#if defined(CONFIG_MW100)
&rk29_device_mw100,
#endif
#if defined(CONFIG_MT6229)
&rk29_device_mt6229,
#endif
#ifdef CONFIG_BATTERY_RK30_ADC
&rk30_device_adc_battery,
#endif

View File

@@ -544,6 +544,9 @@ config MU509
config MW100
bool "MW100 modem control driver"
config MT6229
bool "MT6229 modem control driver"
config RK29_NEWTON
bool "RK29_NEWTON misc driver"

View File

@@ -55,6 +55,7 @@ obj-$(CONFIG_MTK23D) += mtk23d.o
obj-$(CONFIG_FM580X) += fm580x.o
obj-$(CONFIG_MU509) += mu509.o
obj-$(CONFIG_MW100) += mw100.o
obj-$(CONFIG_MT6229) += mt6229.o
obj-$(CONFIG_STE) += ste.o
obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem/
obj-$(CONFIG_GPS_GNS7560) += gps/

353
drivers/misc/mt6229.c Executable file
View File

@@ -0,0 +1,353 @@
#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/mt6229.h>
#include <linux/slab.h>
#include <linux/earlysuspend.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
static struct wake_lock modem_wakelock;
//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_FALLING
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
#define MT6229_RESET 0x01
struct rk29_mt6229_data *gpdata = NULL;
struct class *modem_class = NULL;
static int do_wakeup_irq = 0;
static int modem_status;
int suspend_int =0;
static void ap_wakeup_bp(struct platform_device *pdev, int wake)
{
struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
gpio_set_value(pdata->ap_wakeup_bp, wake);
}
extern void rk28_send_wakeup_key(void);
static void do_wakeup(struct work_struct *work)
{
if(suspend_int)
{
gpio_set_value(gpdata->ap_wakeup_bp, 0);
suspend_int = 0;
}
}
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;
// MODEMDBG("%s[%d]: %s\n", __FILE__, __LINE__, __FUNCTION__);
wake_lock_timeout(&modem_wakelock, 10 * HZ);
schedule_delayed_work(&wakeup_work, 2*HZ);
}
return IRQ_HANDLED;
}
int modem_poweron_off(int on_off)
{
struct rk29_mt6229_data *pdata = gpdata;
if(on_off)
{
MODEMDBG("------------modem_poweron\n");
//gpio_set_value(pdata->bp_reset, GPIO_HIGH);
//msleep(100);
//gpio_set_value(pdata->bp_reset, GPIO_LOW);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(10);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
}
else
{
MODEMDBG("------------modem_poweroff\n");
gpio_set_value(pdata->bp_power, GPIO_HIGH);
gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
}
return 0;
}
static int mt6229_open(struct inode *inode, struct file *file)
{
//MODEMDBG("-------------%s\n",__FUNCTION__);
struct rk29_mt6229_data *pdata = gpdata;
// struct platform_data *pdev = container_of(pdata, struct device, platform_data);
device_init_wakeup(pdata->dev, 1);
return 0;
}
static int mt6229_release(struct inode *inode, struct file *file)
{
//MODEMDBG("-------------%s\n",__FUNCTION__);
return 0;
}
static long mt6229_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct rk29_mt6229_data *pdata = gpdata;
//MODEMDBG("-------------%s\n",__FUNCTION__);
switch(cmd)
{
case MT6229_RESET:
//gpio_set_value(pdata->bp_reset, GPIO_HIGH);
//msleep(100);
//gpio_set_value(pdata->bp_reset, GPIO_LOW);
//msleep(100);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
msleep(10);
gpio_set_value(pdata->bp_power, GPIO_LOW);
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
break;
default:
break;
}
return 0;
}
static struct file_operations mt6229_fops = {
.owner = THIS_MODULE,
.open = mt6229_open,
.release = mt6229_release,
.unlocked_ioctl = mt6229_ioctl
};
static struct miscdevice mt6229_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = MODEM_NAME,
.fops = &mt6229_fops
};
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
#else
static ssize_t modem_status_read(struct class *cls, char *_buf)
#endif
{
return sprintf(_buf, "%d\n", modem_status);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
static ssize_t modem_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
#else
static ssize_t modem_status_write(struct class *cls, const char *_buf, size_t _count)
#endif
{
int new_state = simple_strtoul(_buf, NULL, 16);
if(new_state == modem_status) return _count;
if (new_state == 1){
printk("%s, c(%d), open modem \n", __FUNCTION__, new_state);
modem_poweron_off(1);
}else if(new_state == 0){
printk("%s, c(%d), close modem \n", __FUNCTION__, new_state);
modem_poweron_off(0);
}else{
printk("%s, invalid parameter \n", __FUNCTION__);
}
modem_status = new_state;
return _count;
}
static CLASS_ATTR(modem_status, 0777, modem_status_read, modem_status_write);
static void rk29_early_suspend(struct early_suspend *h)
{
printk("*********************mt6229____suspend\n");
}
static void rk29_early_resume(struct early_suspend *h)
{
if(suspend_int)
{
printk("***************mt6229____resume\n");
gpio_set_value(gpdata->ap_wakeup_bp, 0);
suspend_int = 0;
}
}
static struct early_suspend mt6229_early_suspend = {
.suspend = rk29_early_suspend,
.resume = rk29_early_resume,
.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,
};
static int mt6229_probe(struct platform_device *pdev)
{
struct rk29_mt6229_data *pdata = gpdata = pdev->dev.platform_data;
struct modem_dev *mt6229_data = NULL;
int result, irq = 0;
//MODEMDBG("-------------%s\n",__FUNCTION__);
pdata->dev = &pdev->dev;
if(pdata->io_init)
pdata->io_init();
gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
msleep(1000);
modem_poweron_off(1);
modem_status = 1;
register_early_suspend(&mt6229_early_suspend);
mt6229_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
if(mt6229_data == NULL)
{
printk("failed to request mt6229_data\n");
goto err2;
}
platform_set_drvdata(pdev, mt6229_data);
result = gpio_request(pdata->ap_wakeup_bp, "mt6229");
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_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));
result = misc_register(&mt6229_misc);
if(result)
{
printk("misc_register err\n");
}
return result;
err0:
cancel_work_sync(&mt6229_data->work);
gpio_free(pdata->bp_wakeup_ap);
err1:
gpio_free(pdata->ap_wakeup_bp);
err2:
kfree(mt6229_data);
return 0;
}
int mt6229_suspend(struct platform_device *pdev, pm_message_t state)
{
suspend_int = 1;
do_wakeup_irq = 1;
//MODEMDBG("-------------%s\n",__FUNCTION__);
ap_wakeup_bp(pdev, 1);
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);
//gpio_direction_output(RK29_PIN1_PC1, 1);
#endif
#if defined(CONFIG_ARCH_RK30)
rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_GPIO1A7);
#endif
return 0;
}
int mt6229_resume(struct platform_device *pdev)
{
//MODEMDBG("-------------%s\n",__FUNCTION__);
//ap_wakeup_bp(pdev, 0);
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
#endif
#if defined(CONFIG_ARCH_RK30)
rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_UART1_RTS_N);
#endif
if(gpio_get_value(gpdata->bp_wakeup_ap))
{
schedule_delayed_work(&wakeup_work, 2*HZ);
}
return 0;
}
void mt6229_shutdown(struct platform_device *pdev)
{
struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
struct modem_dev *mt6229_data = platform_get_drvdata(pdev);
//MODEMDBG("-------------%s\n",__FUNCTION__);
modem_poweron_off(0);
if(pdata->io_deinit)
pdata->io_deinit();
cancel_work_sync(&mt6229_data->work);
gpio_free(pdata->modem_power_en);
gpio_free(pdata->bp_power);
gpio_free(pdata->bp_reset);
gpio_free(pdata->ap_wakeup_bp);
gpio_free(pdata->bp_wakeup_ap);
kfree(mt6229_data);
}
static struct platform_driver mt6229_driver = {
.probe = mt6229_probe,
.shutdown = mt6229_shutdown,
.suspend = mt6229_suspend,
.resume = mt6229_resume,
.driver = {
.name = "mt6229",
.owner = THIS_MODULE,
},
};
static int __init mt6229_init(void)
{
//MODEMDBG("-------------%s\n",__FUNCTION__);
int ret ;
modem_class = class_create(THIS_MODULE, "rk291x_modem");
ret = class_create_file(modem_class, &class_attr_modem_status);
if (ret)
{
printk("Fail to class rk291x_modem.\n");
}
return platform_driver_register(&mt6229_driver);
}
static void __exit mt6229_exit(void)
{
//MODEMDBG("-------------%s\n",__FUNCTION__);
platform_driver_unregister(&mt6229_driver);
class_remove_file(modem_class, &class_attr_modem_status);
}
module_init(mt6229_init);
module_exit(mt6229_exit);

View File

@@ -139,6 +139,8 @@ static int mw100_probe(struct platform_device *pdev)
gpio_request(pdata->bp_reset,"bp_reset");
gpio_request(pdata->bp_wakeup_ap,"bp_wakeup_ap");
gpio_request(pdata->ap_wakeup_bp,"ap_wakeup_bp");
gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
msleep(1000);
#if defined(CONFIG_ARCH_RK29)
rk29_mux_api_set(GPIO6C76_CPUTRACEDATA76_NAME, GPIO4H_GPIO6C76);
#endif
@@ -245,7 +247,7 @@ void mw100_shutdown(struct platform_device *pdev)
MODEMDBG("%s::%d--bruins--\n",__func__,__LINE__);
gpio_set_value(pdata->bp_power, GPIO_HIGH);
mdelay(2010);
gpio_free(pdata->modem_power_en);
gpio_free(pdata->bp_power);
gpio_free(pdata->bp_reset);
gpio_free(pdata->ap_wakeup_bp);

View File

@@ -61,6 +61,10 @@ static int MU509_USB = 0;
static int MW100_USB = 0;
#define MW100_USB_PORT (SERIAL_TTY_MINORS - 10)
#endif
#ifdef CONFIG_MT6229
static int MT6229_USB = 0;
#define MT6229_USB_PORT (SERIAL_TTY_MINORS - 10)
#endif
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
the MODULE_DEVICE_TABLE declarations in each serial driver
@@ -118,6 +122,10 @@ static struct usb_serial *get_free_serial(struct usb_serial *serial,
#ifdef CONFIG_MW100
if (MW100_USB)
a= MW100_USB_PORT;
#endif
#ifdef CONFIG_MT6229
if (MT6229_USB)
a= MT6229_USB_PORT;
#endif
for (i = a; i < SERIAL_TTY_MINORS; ++i) {
if (serial_table[i])
@@ -1087,6 +1095,12 @@ int usb_serial_probe(struct usb_interface *interface,
else
MW100_USB = 0;
#endif
#ifdef CONFIG_MT6229
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0E8D) && (le16_to_cpu(dev->descriptor.idProduct) == 0x00A2))
MT6229_USB =1;
else
MT6229_USB = 0;
#endif
if (get_free_serial(serial, num_ports, &minor) == NULL) {
dev_err(&interface->dev, "No more free serial devices\n");

25
include/linux/mt6229.h Normal file
View File

@@ -0,0 +1,25 @@
#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_mt6229_data {
struct device *dev;
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;
unsigned int modem_power_en;
};
#define MODEM_NAME "mt6229"