mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
3G modem driver for 4.2.2
1.the driver is copy form 4.1
2.mu509,mt6229,mw100,sew868
3.other modem use rk29_modem_config
This commit is contained in:
parent
b0fa38e0b4
commit
401e7f1d2f
|
|
@ -57,10 +57,18 @@
|
|||
#if defined(CONFIG_SPIM_RK29)
|
||||
#include "../../../drivers/spi/rk29_spim.h"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MU509)
|
||||
#include <linux/mu509.h>
|
||||
#endif
|
||||
#if defined(CONFIG_MW100)
|
||||
#include <linux/mw100.h>
|
||||
#endif
|
||||
#if defined (CONFIG_BP_AUTO)
|
||||
#include <linux/bp-auto.h>
|
||||
#endif
|
||||
#if defined(CONFIG_SEW868)
|
||||
#include <linux/sew868.h>
|
||||
#endif
|
||||
#if defined(CONFIG_ANDROID_TIMED_GPIO)
|
||||
#include "../../../drivers/staging/android/timed_gpio.h"
|
||||
#endif
|
||||
|
|
@ -470,7 +478,144 @@ static struct platform_device rk30_device_modem = {
|
|||
}
|
||||
};
|
||||
#endif
|
||||
#if defined(CONFIG_MU509)
|
||||
static int mu509_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 mu509_io_deinit(void)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rk29_mu509_data rk29_mu509_info = {
|
||||
.io_init = mu509_io_init,
|
||||
.io_deinit = mu509_io_deinit,
|
||||
.modem_power_en = RK30_PIN6_PB2,//RK30_PIN4_PD1,
|
||||
.bp_power = RK30_PIN2_PB6,//RK30_PIN4_PD1,
|
||||
.bp_reset = RK30_PIN4_PD2,
|
||||
.ap_wakeup_bp = RK30_PIN2_PB7,
|
||||
.bp_wakeup_ap = RK30_PIN6_PA0,
|
||||
};
|
||||
struct platform_device rk29_device_mu509 = {
|
||||
.name = "mu509",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &rk29_mu509_info,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#if defined(CONFIG_MW100)
|
||||
static int mw100_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 mw100_io_deinit(void)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
||||
.bp_wakeup_ap = RK30_PIN6_PA0,
|
||||
};
|
||||
struct platform_device rk29_device_mw100 = {
|
||||
.name = "mw100",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &rk29_mw100_info,
|
||||
}
|
||||
};
|
||||
#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);
|
||||
rk30_mux_api_set(GPIO2C1_LCDC1DATA17_SMCBLSN0_HSADCDATA6_NAME, GPIO2C_GPIO2C1);
|
||||
rk30_mux_api_set(GPIO2C1_LCDC1DATA17_SMCBLSN0_HSADCDATA6_NAME, GPIO2C_GPIO2C1);
|
||||
return 0;
|
||||
|
||||
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_PB6,
|
||||
.modem_usb_en = RK30_PIN2_PC0,
|
||||
.modem_uart_en = RK30_PIN2_PC1,
|
||||
.bp_wakeup_ap = RK30_PIN6_PA1,
|
||||
.ap_ready = RK30_PIN2_PB7,
|
||||
|
||||
};
|
||||
struct platform_device rk29_device_mt6229 = {
|
||||
.name = "mt6229",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &rk29_mt6229_info,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#if defined(CONFIG_SEW868)
|
||||
static int sew868_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(GPIO4D4_SMCDATA12_TRACEDATA12_NAME, GPIO4D_GPIO4D4);
|
||||
return 0;
|
||||
}
|
||||
static int sew868_io_deinit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
struct rk30_sew868_data rk30_sew868_info = {
|
||||
.io_init = sew868_io_init,
|
||||
.io_deinit = sew868_io_deinit,
|
||||
.bp_power = RK30_PIN6_PB2,
|
||||
.bp_power_active_low = 1,
|
||||
.bp_sys = RK30_PIN2_PB6,
|
||||
.bp_reset = RK30_PIN4_PD2,
|
||||
.bp_reset_active_low = 1,
|
||||
.bp_wakeup_ap = RK30_PIN4_PD4,
|
||||
.ap_wakeup_bp = NULL,
|
||||
};
|
||||
|
||||
struct platform_device rk30_device_sew868 = {
|
||||
.name = "sew868",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &rk30_sew868_info,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/*MMA8452 gsensor*/
|
||||
#if defined (CONFIG_GS_MMA8452)
|
||||
|
|
@ -1440,6 +1585,18 @@ static struct platform_device *devices[] __initdata = {
|
|||
#ifdef CONFIG_RK29_SUPPORT_MODEM
|
||||
&rk30_device_modem,
|
||||
#endif
|
||||
#if defined(CONFIG_MU509)
|
||||
&rk29_device_mu509,
|
||||
#endif
|
||||
#if defined(CONFIG_MW100)
|
||||
&rk29_device_mw100,
|
||||
#endif
|
||||
#if defined(CONFIG_MT6229)
|
||||
&rk29_device_mt6229,
|
||||
#endif
|
||||
#if defined(CONFIG_SEW868)
|
||||
&rk30_device_sew868,
|
||||
#endif
|
||||
#if defined (CONFIG_RK_HEADSET_DET) || defined (CONFIG_RK_HEADSET_IRQ_HOOK_ADC_DET)
|
||||
&rk_device_headset,
|
||||
#endif
|
||||
|
|
|
|||
30
drivers/misc/3g_module/Kconfig
Executable file
30
drivers/misc/3g_module/Kconfig
Executable file
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# 3G device configuration
|
||||
#
|
||||
|
||||
menuconfig 3G_MODULE
|
||||
tristate "3G module for mid"
|
||||
---help---
|
||||
Say Y here if you have a support modem
|
||||
|
||||
choice
|
||||
depends on 3G_MODULE
|
||||
prompt "Select 3G Module"
|
||||
|
||||
config MU509
|
||||
bool "MU509"
|
||||
|
||||
config MT6229
|
||||
bool "MT6229"
|
||||
|
||||
config MW100
|
||||
bool "MW100"
|
||||
|
||||
config SEW868
|
||||
bool "SEW868"
|
||||
|
||||
|
||||
|
||||
|
||||
endchoice
|
||||
|
||||
4
drivers/misc/3g_module/Makefile
Executable file
4
drivers/misc/3g_module/Makefile
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
obj-$(CONFIG_MU509) += mu509.o
|
||||
obj-$(CONFIG_MW100) += mw100.o
|
||||
obj-$(CONFIG_MT6229) += mt6229.o
|
||||
obj-$(CONFIG_SEW868) += sew868.o
|
||||
359
drivers/misc/3g_module/mt6229.c
Executable file
359
drivers/misc/3g_module/mt6229.c
Executable file
|
|
@ -0,0 +1,359 @@
|
|||
#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;
|
||||
static void ap_wakeup_bp(struct platform_device *pdev, int wake)
|
||||
{
|
||||
struct rk29_mt6229_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
gpio_set_value(pdata->modem_usb_en,wake);
|
||||
if(wake == 1)
|
||||
wake = 0;
|
||||
else
|
||||
wake = 1;
|
||||
gpio_set_value(pdata->modem_uart_en,wake);
|
||||
|
||||
}
|
||||
extern void rk28_send_wakeup_key(void);
|
||||
|
||||
static void do_wakeup(struct work_struct *work)
|
||||
{
|
||||
gpio_set_value(gpdata->ap_ready,GPIO_HIGH);
|
||||
gpio_set_value(gpdata->modem_usb_en,GPIO_HIGH);
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
gpio_set_value(pdata->modem_usb_en, GPIO_HIGH);
|
||||
gpio_set_value(pdata->modem_uart_en, GPIO_LOW);
|
||||
gpio_set_value(pdata->ap_ready, GPIO_HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_value(pdata->bp_power, GPIO_HIGH);
|
||||
gpio_set_value(pdata->modem_usb_en, GPIO_LOW);
|
||||
gpio_set_value(pdata->modem_uart_en, GPIO_HIGH);
|
||||
gpio_set_value(pdata->ap_ready, GPIO_LOW);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int mt6229_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct rk29_mt6229_data *pdata = gpdata;
|
||||
device_init_wakeup(pdata->dev, 1);
|
||||
return 0;
|
||||
}
|
||||
static ssize_t mt6229_write(struct file *file, const char __user *buf,size_t len, loff_t *off)
|
||||
{
|
||||
static char cmd[2];
|
||||
int ret = 0;
|
||||
if (len > 2)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = copy_from_user(&cmd, buf, len);
|
||||
if (ret != 0) {
|
||||
return -EFAULT;
|
||||
}
|
||||
printk(" received cmd = %c\n",cmd[0]);
|
||||
if (cmd[0] == '0')
|
||||
{
|
||||
gpio_set_value(gpdata->ap_ready, GPIO_LOW);
|
||||
}
|
||||
if (cmd[0] == '1')
|
||||
{
|
||||
gpio_set_value(gpdata->ap_ready, GPIO_HIGH);
|
||||
}
|
||||
if (cmd[0] == '2')
|
||||
{
|
||||
gpio_set_value(gpdata->modem_uart_en, GPIO_LOW);
|
||||
}
|
||||
if (cmd[0] == '3')
|
||||
{
|
||||
gpio_set_value(gpdata->modem_uart_en, GPIO_HIGH);
|
||||
}
|
||||
if (cmd[0] == '4')
|
||||
{
|
||||
gpio_set_value(gpdata->modem_usb_en, GPIO_HIGH);
|
||||
}if (cmd[0] == '5')
|
||||
{
|
||||
gpio_set_value(gpdata->modem_usb_en, GPIO_LOW);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static int mt6229_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long mt6229_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct rk29_mt6229_data *pdata = gpdata;
|
||||
switch(cmd)
|
||||
{
|
||||
case MT6229_RESET:
|
||||
modem_poweron_off(0);
|
||||
msleep(10);
|
||||
modem_poweron_off(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations mt6229_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mt6229_open,
|
||||
.write = mt6229_write,
|
||||
.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), modem resume \n", __FUNCTION__, new_state);
|
||||
gpio_set_value(gpdata->modem_usb_en, GPIO_HIGH);
|
||||
gpio_set_value(gpdata->modem_uart_en,GPIO_LOW);
|
||||
}else if(new_state == 0){
|
||||
printk("%s, c(%d), modem suspend \n", __FUNCTION__, new_state);
|
||||
gpio_set_value(gpdata->modem_usb_en, GPIO_LOW);
|
||||
gpio_set_value(gpdata->modem_uart_en,GPIO_HIGH);
|
||||
}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 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;
|
||||
pdata->dev = &pdev->dev;
|
||||
if(pdata->io_init)
|
||||
pdata->io_init();
|
||||
mt6229_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
|
||||
if(mt6229_data == NULL)
|
||||
{
|
||||
printk("failed to request mt6229_data\n");
|
||||
goto err0;
|
||||
}
|
||||
platform_set_drvdata(pdev, mt6229_data);
|
||||
result = gpio_request(pdata->modem_power_en,"modem_power_en");
|
||||
if(result){
|
||||
printk("failed to request modem_power_en gpio\n");
|
||||
goto err1;
|
||||
}
|
||||
gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
|
||||
msleep(1000);
|
||||
result = gpio_request(pdata->bp_power,"modem_power");
|
||||
if(result){
|
||||
printk("failed to request modem_power gpio\n");
|
||||
goto err2;
|
||||
}
|
||||
result = gpio_request(pdata->modem_usb_en, "modem_usb_en");
|
||||
if (result) {
|
||||
printk("failed to request modem_usb_en gpio\n");
|
||||
goto err3;
|
||||
}
|
||||
result = gpio_request(pdata->modem_uart_en,"modem_uart_en");
|
||||
if(result){
|
||||
printk("failed to request modem_uart_en gpio\n");
|
||||
goto err4;
|
||||
}
|
||||
result = gpio_request(pdata->bp_wakeup_ap, "bp_wakeup_ap");
|
||||
if (result) {
|
||||
printk("failed to request bp_wakeup_ap gpio\n");
|
||||
goto err5;
|
||||
}
|
||||
gpio_direction_input(pdata->bp_wakeup_ap);
|
||||
irq = gpio_to_irq(pdata->bp_wakeup_ap);
|
||||
if(irq < 0)
|
||||
{
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
printk("failed to request bp_wakeup_ap\n");
|
||||
}
|
||||
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 err5;
|
||||
}
|
||||
enable_irq_wake(irq);
|
||||
wake_lock_init(&modem_wakelock, WAKE_LOCK_SUSPEND, "bp_wakeup_ap");
|
||||
result = gpio_request(pdata->ap_ready, "ap_ready");
|
||||
if (result < 0) {
|
||||
printk("failed to request ap_ready gpio\n");
|
||||
goto err6;
|
||||
}
|
||||
|
||||
modem_poweron_off(1);
|
||||
modem_status = 1;
|
||||
|
||||
result = misc_register(&mt6229_misc);
|
||||
if(result)
|
||||
{
|
||||
printk("misc_register err\n");
|
||||
}
|
||||
return result;
|
||||
err0:
|
||||
kfree(mt6229_data);
|
||||
err1:
|
||||
gpio_free(pdata->modem_power_en);
|
||||
err2:
|
||||
gpio_free(pdata->bp_power);
|
||||
err3:
|
||||
gpio_free(pdata->modem_usb_en);
|
||||
err4:
|
||||
gpio_free(pdata->modem_uart_en);
|
||||
err5:
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
err6:
|
||||
gpio_free(pdata->ap_ready);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt6229_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
do_wakeup_irq = 1;
|
||||
ap_wakeup_bp(pdev, 0);
|
||||
gpio_set_value(gpdata->ap_ready,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt6229_resume(struct platform_device *pdev)
|
||||
{
|
||||
gpio_set_value(gpdata->modem_uart_en,GPIO_LOW);
|
||||
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);
|
||||
|
||||
modem_poweron_off(0);
|
||||
gpio_set_value(pdata->modem_power_en, GPIO_LOW);
|
||||
|
||||
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->modem_usb_en);
|
||||
gpio_free(pdata->modem_uart_en);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
platform_driver_unregister(&mt6229_driver);
|
||||
class_remove_file(modem_class, &class_attr_modem_status);
|
||||
}
|
||||
|
||||
module_init(mt6229_init);
|
||||
|
||||
module_exit(mt6229_exit);
|
||||
377
drivers/misc/3g_module/mu509.c
Executable file
377
drivers/misc/3g_module/mu509.c
Executable file
|
|
@ -0,0 +1,377 @@
|
|||
#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/mu509.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 MU509_RESET 0x01
|
||||
struct rk29_mu509_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_mu509_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_mu509_data *pdata = gpdata;
|
||||
if(on_off)
|
||||
{
|
||||
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);
|
||||
msleep(1000);
|
||||
gpio_set_value(pdata->bp_power, GPIO_HIGH);
|
||||
msleep(700);
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
gpio_set_value(pdata->bp_power, GPIO_HIGH);
|
||||
msleep(2500);
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int mu509_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct rk29_mu509_data *pdata = gpdata;
|
||||
device_init_wakeup(pdata->dev, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mu509_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long mu509_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct rk29_mu509_data *pdata = gpdata;
|
||||
switch(cmd)
|
||||
{
|
||||
case MU509_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);
|
||||
msleep(1000);
|
||||
gpio_set_value(pdata->bp_power, GPIO_HIGH);
|
||||
msleep(700);
|
||||
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 mu509_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mu509_open,
|
||||
.release = mu509_release,
|
||||
.unlocked_ioctl = mu509_ioctl
|
||||
};
|
||||
|
||||
static struct miscdevice mu509_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = MODEM_NAME,
|
||||
.fops = &mu509_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)
|
||||
{
|
||||
|
||||
}
|
||||
static void rk29_early_resume(struct early_suspend *h)
|
||||
{
|
||||
if(suspend_int)
|
||||
{
|
||||
gpio_set_value(gpdata->ap_wakeup_bp, 0);
|
||||
suspend_int = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct early_suspend mu509_early_suspend = {
|
||||
.suspend = rk29_early_suspend,
|
||||
.resume = rk29_early_resume,
|
||||
.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1,
|
||||
};
|
||||
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;
|
||||
|
||||
pdata->dev = &pdev->dev;
|
||||
if(pdata->io_init)
|
||||
pdata->io_init();
|
||||
|
||||
printk("******** mu509_probe_mu509_probe usb autosuspend *********\n");
|
||||
// xxh begin
|
||||
#if 1
|
||||
rk30_mux_api_set(GPIO1A1_UART0SOUT_NAME, GPIO1A_GPIO1A4);
|
||||
result = gpio_request(RK30_PIN1_PA4, "uart1_sout");
|
||||
if (result < 0) {
|
||||
|
||||
printk("%s: gpio_request( uart1_sout ) failed\n", __func__);
|
||||
|
||||
}
|
||||
else {
|
||||
printk("******* uart0_sout low ( %s ) 88 ********\n", __FUNCTION__);
|
||||
gpio_set_value(RK30_PIN1_PA4, GPIO_LOW); // Make sure the uart1_rx of MU509 is low for usb autosuspend
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
// xxh end
|
||||
|
||||
mu509_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
|
||||
if(mu509_data == NULL)
|
||||
{
|
||||
printk("failed to request mu509_data\n");
|
||||
goto err0;
|
||||
}
|
||||
platform_set_drvdata(pdev, mu509_data);
|
||||
result = gpio_request(pdata->modem_power_en,"modem_power_en");
|
||||
if(result){
|
||||
printk("failed to request modem_power_en gpio\n");
|
||||
goto err1;
|
||||
}
|
||||
gpio_set_value(pdata->modem_power_en, GPIO_HIGH);
|
||||
result = gpio_request(pdata->bp_power,"modem_power");
|
||||
if(result){
|
||||
printk("failed to request modem_power gpio\n");
|
||||
goto err2;
|
||||
}
|
||||
|
||||
|
||||
register_early_suspend(&mu509_early_suspend);
|
||||
|
||||
result = gpio_request(pdata->ap_wakeup_bp, "mu509");
|
||||
if (result) {
|
||||
printk("failed to request AP_BP_WAKEUP gpio\n");
|
||||
goto err3;
|
||||
}
|
||||
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 err4;
|
||||
}
|
||||
enable_irq_wake(gpio_to_irq(pdata->bp_wakeup_ap));
|
||||
|
||||
msleep(1000);
|
||||
modem_poweron_off(1);
|
||||
modem_status = 1;
|
||||
|
||||
result = misc_register(&mu509_misc);
|
||||
if(result)
|
||||
{
|
||||
printk("misc_register err\n");
|
||||
}
|
||||
return result;
|
||||
err0:
|
||||
kfree(mu509_data);
|
||||
err1:
|
||||
gpio_free(pdata->modem_power_en);
|
||||
err2:
|
||||
gpio_free(pdata->bp_power);
|
||||
err3:
|
||||
gpio_free(pdata->ap_wakeup_bp);
|
||||
err4:
|
||||
cancel_work_sync(&mu509_data->work);
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mu509_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
suspend_int = 1;
|
||||
do_wakeup_irq = 1;
|
||||
ap_wakeup_bp(pdev, 1);
|
||||
#if defined(CONFIG_ARCH_RK29)
|
||||
rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_GPIO1C1);
|
||||
#endif
|
||||
#if defined(CONFIG_ARCH_RK30)
|
||||
rk30_mux_api_set(GPIO1A7_UART1RTSN_SPI0TXD_NAME, GPIO1A_GPIO1A7);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mu509_resume(struct platform_device *pdev)
|
||||
{
|
||||
#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 mu509_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rk29_mu509_data *pdata = pdev->dev.platform_data;
|
||||
struct modem_dev *mu509_data = platform_get_drvdata(pdev);
|
||||
|
||||
modem_poweron_off(0);
|
||||
gpio_set_value(pdata->modem_power_en, GPIO_LOW);
|
||||
|
||||
if(pdata->io_deinit)
|
||||
pdata->io_deinit();
|
||||
cancel_work_sync(&mu509_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(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)
|
||||
{
|
||||
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(&mu509_driver);
|
||||
}
|
||||
|
||||
static void __exit mu509_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mu509_driver);
|
||||
class_remove_file(modem_class, &class_attr_modem_status);
|
||||
}
|
||||
|
||||
module_init(mu509_init);
|
||||
|
||||
module_exit(mu509_exit);
|
||||
235
drivers/misc/3g_module/mw100.c
Executable file
235
drivers/misc/3g_module/mw100.c
Executable file
|
|
@ -0,0 +1,235 @@
|
|||
#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 <linux/delay.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/mw100.h>
|
||||
#include <mach/iomux.h>
|
||||
#include<linux/ioctl.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef DEBUG
|
||||
#define MODEMDBG(x...) printk(x)
|
||||
#else
|
||||
#define MODEMDBG(fmt,argss...)
|
||||
#endif
|
||||
|
||||
#define MW100IO 0XA1
|
||||
#define MW_IOCTL_RESET _IO(MW100IO,0X01)
|
||||
|
||||
#define SLEEP 1
|
||||
#define READY 0
|
||||
#define MW100_RESET 0x01
|
||||
#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
|
||||
//#define IRQ_BB_WAKEUP_AP_TRIGGER IRQF_TRIGGER_RISING
|
||||
struct rk29_mw100_data *gpdata = NULL;
|
||||
static int bp_wakeup_ap_irq = 0;
|
||||
|
||||
static struct wake_lock bp_wakelock;
|
||||
static bool bpstatus_irq_enable = false;
|
||||
|
||||
static void do_wakeup(struct work_struct *work)
|
||||
{
|
||||
enable_irq(bp_wakeup_ap_irq);
|
||||
}
|
||||
|
||||
static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
|
||||
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
wake_lock_timeout(&bp_wakelock, 10 * HZ);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int mw100_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mw100_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long mw100_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct rk29_mw100_data *pdata = gpdata;
|
||||
switch(cmd)
|
||||
{
|
||||
case MW_IOCTL_RESET:
|
||||
gpio_direction_output(pdata->bp_reset,GPIO_LOW);
|
||||
mdelay(120);
|
||||
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations mw100_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = mw100_open,
|
||||
.release = mw100_release,
|
||||
.unlocked_ioctl = mw100_ioctl
|
||||
};
|
||||
|
||||
static struct miscdevice mw100_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "mw100",
|
||||
.fops = &mw100_fops
|
||||
};
|
||||
|
||||
static int mw100_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk29_mw100_data *pdata = gpdata = pdev->dev.platform_data;
|
||||
struct modem_dev *mw100_data = NULL;
|
||||
int result, irq = 0;
|
||||
|
||||
gpio_request(pdata->bp_power,"bp_power");
|
||||
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);
|
||||
gpio_direction_output(pdata->bp_reset,GPIO_LOW);
|
||||
mdelay(120);
|
||||
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
|
||||
|
||||
gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
|
||||
gpio_direction_output(pdata->ap_wakeup_bp,GPIO_HIGH);
|
||||
|
||||
gpio_set_value(pdata->bp_power, GPIO_HIGH);
|
||||
gpio_direction_output(pdata->bp_power,GPIO_HIGH);
|
||||
mdelay(120);
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
gpio_direction_output(pdata->bp_power,GPIO_LOW);
|
||||
|
||||
mw100_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
|
||||
if(mw100_data == NULL){
|
||||
printk("failed to request mw100_data\n");
|
||||
goto err2;
|
||||
}
|
||||
platform_set_drvdata(pdev, mw100_data);
|
||||
|
||||
gpio_direction_input(pdata->bp_wakeup_ap);
|
||||
irq = gpio_to_irq(pdata->bp_wakeup_ap);
|
||||
if(irq < 0){
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
printk("failed to request bp_wakeup_ap\n");
|
||||
}
|
||||
|
||||
bp_wakeup_ap_irq = irq;
|
||||
|
||||
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(bp_wakeup_ap_irq);
|
||||
|
||||
wake_lock_init(&bp_wakelock, WAKE_LOCK_SUSPEND, "bp_resume");
|
||||
|
||||
result = misc_register(&mw100_misc);
|
||||
if(result){
|
||||
MODEMDBG("misc_register err\n");
|
||||
}
|
||||
return result;
|
||||
err0:
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
err2:
|
||||
kfree(mw100_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mw100_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
|
||||
struct rk29_mw100_data *pdata = pdev->dev.platform_data;
|
||||
int irq;
|
||||
gpio_set_value(pdata->ap_wakeup_bp, GPIO_LOW);
|
||||
irq = gpio_to_irq(pdata->bp_wakeup_ap);
|
||||
if (irq < 0) {
|
||||
printk("can't get pdata->bp_statue irq \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
bpstatus_irq_enable = true;
|
||||
enable_irq_wake(irq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mw100_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct rk29_mw100_data *pdata = pdev->dev.platform_data;
|
||||
int irq;
|
||||
gpio_set_value(pdata->ap_wakeup_bp, GPIO_HIGH);
|
||||
irq = gpio_to_irq(pdata->bp_wakeup_ap);
|
||||
if (irq ) {
|
||||
disable_irq_wake(irq);
|
||||
bpstatus_irq_enable = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mw100_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rk29_mw100_data *pdata = pdev->dev.platform_data;
|
||||
struct modem_dev *mw100_data = platform_get_drvdata(pdev);
|
||||
|
||||
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);
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
kfree(mw100_data);
|
||||
}
|
||||
|
||||
static struct platform_driver mw100_driver = {
|
||||
.probe = mw100_probe,
|
||||
.shutdown = mw100_shutdown,
|
||||
.suspend = mw100_suspend,
|
||||
.resume = mw100_resume,
|
||||
.driver = {
|
||||
.name = "mw100",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init mw100_init(void)
|
||||
{
|
||||
return platform_driver_register(&mw100_driver);
|
||||
}
|
||||
|
||||
static void __exit mw100_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mw100_driver);
|
||||
}
|
||||
|
||||
module_init(mw100_init);
|
||||
|
||||
module_exit(mw100_exit);
|
||||
228
drivers/misc/3g_module/sew868.c
Executable file
228
drivers/misc/3g_module/sew868.c
Executable file
|
|
@ -0,0 +1,228 @@
|
|||
#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 <linux/delay.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/sew868.h>
|
||||
#include<linux/ioctl.h>
|
||||
#include<linux/slab.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 SEW868_RESET 0x01
|
||||
#define SEW868_POWON 0x02
|
||||
#define SEW868_POWOFF 0x03
|
||||
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 rk30_sew868_data *gpdata = NULL;
|
||||
static int do_wakeup_irq = 0;
|
||||
|
||||
extern void rk28_send_wakeup_key(void);
|
||||
|
||||
static void do_wakeup(struct work_struct *work)
|
||||
{
|
||||
rk28_send_wakeup_key();
|
||||
}
|
||||
|
||||
static DECLARE_DELAYED_WORK(wakeup_work, do_wakeup);
|
||||
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
printk("%s\n", __FUNCTION__);
|
||||
if(do_wakeup_irq)
|
||||
{
|
||||
do_wakeup_irq = 0;
|
||||
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 rk30_sew868_data *pdata = gpdata;
|
||||
if(on_off)
|
||||
{
|
||||
gpio_direction_output(pdata->bp_sys, GPIO_HIGH);
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
msleep(200);//for charge
|
||||
gpio_set_value(pdata->bp_power, GPIO_HIGH);
|
||||
msleep(4000);
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
msleep(200);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_value(pdata->bp_power, GPIO_HIGH);
|
||||
msleep(4000);
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
gpio_set_value(pdata->bp_sys, GPIO_LOW);
|
||||
msleep(50);
|
||||
gpio_set_value(pdata->bp_power, GPIO_LOW);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int sew868_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sew868_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long sew868_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct rk30_sew868_data *pdata = gpdata;
|
||||
switch(cmd)
|
||||
{
|
||||
case SEW868_RESET:
|
||||
gpio_set_value(pdata->bp_reset, GPIO_HIGH);
|
||||
mdelay(100);
|
||||
gpio_set_value(pdata->bp_reset, GPIO_LOW);
|
||||
mdelay(200);
|
||||
modem_poweron_off(1);
|
||||
break;
|
||||
case SEW868_POWON:
|
||||
modem_poweron_off(1);
|
||||
break;
|
||||
case SEW868_POWOFF:
|
||||
modem_poweron_off(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations sew868_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = sew868_open,
|
||||
.release = sew868_release,
|
||||
.unlocked_ioctl = sew868_ioctl
|
||||
};
|
||||
|
||||
static struct miscdevice sew868_misc = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = MODEM_NAME,
|
||||
.fops = &sew868_fops
|
||||
};
|
||||
|
||||
static int sew868_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rk30_sew868_data *pdata = gpdata = pdev->dev.platform_data;
|
||||
struct modem_dev *sew868_data = NULL;
|
||||
int result, irq = 0;
|
||||
|
||||
if(pdata->io_init)
|
||||
pdata->io_init();
|
||||
|
||||
modem_poweron_off(1);
|
||||
sew868_data = kzalloc(sizeof(struct modem_dev), GFP_KERNEL);
|
||||
if(sew868_data == NULL)
|
||||
{
|
||||
printk("failed to request sew868_data\n");
|
||||
goto err1;
|
||||
}
|
||||
platform_set_drvdata(pdev, sew868_data);
|
||||
|
||||
irq = gpio_to_irq(pdata->bp_wakeup_ap);
|
||||
if(irq < 0)
|
||||
{
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
printk("failed to request bp_wakeup_ap\n");
|
||||
}
|
||||
|
||||
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, GPIONormal);
|
||||
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(&sew868_misc);
|
||||
if(result)
|
||||
{
|
||||
MODEMDBG("misc_register err\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
err0:
|
||||
cancel_work_sync(&sew868_data->work);
|
||||
err1:
|
||||
kfree(sew868_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sew868_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
do_wakeup_irq = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sew868_resume(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sew868_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rk30_sew868_data *pdata = pdev->dev.platform_data;
|
||||
struct modem_dev *sew868_data = platform_get_drvdata(pdev);
|
||||
modem_poweron_off(0);
|
||||
if(pdata->io_deinit)
|
||||
pdata->io_deinit();
|
||||
cancel_work_sync(&sew868_data->work);
|
||||
kfree(sew868_data);
|
||||
}
|
||||
|
||||
static struct platform_driver sew868_driver = {
|
||||
.probe = sew868_probe,
|
||||
.shutdown = sew868_shutdown,
|
||||
.suspend = sew868_suspend,
|
||||
.resume = sew868_resume,
|
||||
.driver = {
|
||||
.name = "sew868",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sew868_init(void)
|
||||
{
|
||||
return platform_driver_register(&sew868_driver);
|
||||
}
|
||||
|
||||
static void __exit sew868_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sew868_driver);
|
||||
}
|
||||
|
||||
module_init(sew868_init);
|
||||
|
||||
module_exit(sew868_exit);
|
||||
|
|
@ -566,5 +566,6 @@ source "drivers/misc/lis3lv02d/Kconfig"
|
|||
source "drivers/misc/carma/Kconfig"
|
||||
source "drivers/misc/bp/Kconfig"
|
||||
source "drivers/misc/rk2928_callpad_misc/Kconfig"
|
||||
source "drivers/misc/3g_module/Kconfig"
|
||||
|
||||
endif # MISC_DEVICES
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ obj-$(CONFIG_SENSORS_AK8963) += akm8963.o
|
|||
obj-$(CONFIG_MTK23D) += mtk23d.o
|
||||
obj-$(CONFIG_FM580X) += fm580x.o
|
||||
obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem/
|
||||
obj-$(CONFIG_3G_MODULE) += 3g_module/
|
||||
obj-$(CONFIG_BP_AUTO) += bp/
|
||||
obj-$(CONFIG_GPS_DEVICES) += gps/
|
||||
obj-y += inv_mpu/
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user