mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
rk30_phonepad:add auto modem driver support
This commit is contained in:
parent
d5551f9e90
commit
534cc41268
13
drivers/misc/bp/Kconfig
Executable file
13
drivers/misc/bp/Kconfig
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# all auto modem control drivers configuration
|
||||
#
|
||||
|
||||
menuconfig BP_AUTO
|
||||
bool "auto modem control driver support"
|
||||
default n
|
||||
|
||||
if BP_AUTO
|
||||
|
||||
source "drivers/misc/bp/chips/Kconfig"
|
||||
|
||||
endif
|
||||
3
drivers/misc/bp/Makefile
Executable file
3
drivers/misc/bp/Makefile
Executable file
|
|
@ -0,0 +1,3 @@
|
|||
# auto modem control drivers
|
||||
obj-$(CONFIG_BP_AUTO) += chips/
|
||||
obj-$(CONFIG_BP_AUTO) += bp-auto.o
|
||||
665
drivers/misc/bp/bp-auto.c
Executable file
665
drivers/misc/bp/bp-auto.c
Executable file
|
|
@ -0,0 +1,665 @@
|
|||
#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
|
||||
|
||||
struct bp_private_data *g_bp;
|
||||
static struct class *g_bp_class;
|
||||
static struct bp_operate *g_bp_ops[BP_ID_NUM];
|
||||
struct class *bp_class = NULL;
|
||||
|
||||
static void ap_wakeup_bp(struct bp_private_data *bp, int wake)
|
||||
{
|
||||
if(bp->ops->ap_wake_bp)
|
||||
bp->ops->ap_wake_bp(bp, wake);
|
||||
|
||||
}
|
||||
|
||||
static int bp_request_gpio(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(bp->pdata->gpio_valid)
|
||||
{
|
||||
if(bp->pdata->bp_power > 0)
|
||||
{
|
||||
bp->ops->bp_power = bp->pdata->bp_power;
|
||||
}
|
||||
|
||||
if(bp->pdata->bp_en > 0)
|
||||
{
|
||||
bp->ops->bp_en = bp->pdata->bp_en;
|
||||
}
|
||||
|
||||
if(bp->pdata->bp_reset > 0)
|
||||
{
|
||||
bp->ops->bp_reset = bp->pdata->bp_reset;
|
||||
}
|
||||
|
||||
if(bp->pdata->ap_ready > 0)
|
||||
{
|
||||
bp->ops->ap_ready = bp->pdata->ap_ready;
|
||||
}
|
||||
|
||||
if(bp->pdata->bp_ready > 0)
|
||||
{
|
||||
bp->ops->bp_ready = bp->pdata->bp_ready;
|
||||
}
|
||||
|
||||
if(bp->pdata->ap_wakeup_bp > 0)
|
||||
{
|
||||
bp->ops->ap_wakeup_bp = bp->pdata->ap_wakeup_bp;
|
||||
}
|
||||
|
||||
if(bp->pdata->bp_wakeup_ap > 0)
|
||||
{
|
||||
bp->ops->bp_wakeup_ap = bp->pdata->bp_wakeup_ap;
|
||||
}
|
||||
|
||||
if(bp->pdata->bp_usb_en > 0)
|
||||
{
|
||||
bp->ops->bp_usb_en = bp->pdata->bp_usb_en;
|
||||
}
|
||||
|
||||
if(bp->pdata->bp_uart_en > 0)
|
||||
{
|
||||
bp->ops->bp_uart_en = bp->pdata->bp_uart_en;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(bp->ops->bp_power != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->bp_power, "bp_power");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_power);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(bp->ops->bp_en != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->bp_en, "bp_en");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_en);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(bp->ops->bp_reset != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->bp_reset, "bp_reset");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_reset);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(bp->ops->ap_ready != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->ap_ready, "ap_ready");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->ap_ready);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(bp->ops->bp_ready != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->bp_ready, "bp_ready");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_ready);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(bp->ops->ap_wakeup_bp != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->ap_wakeup_bp, "ap_wakeup_bp");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->ap_wakeup_bp);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(bp->ops->bp_wakeup_ap != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->bp_wakeup_ap, "bp_wakeup_ap");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_wakeup_ap);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(bp->ops->bp_usb_en != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->bp_usb_en, "bp_usb_en");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_usb_en);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(bp->ops->bp_uart_en != BP_UNKNOW_DATA)
|
||||
{
|
||||
result = gpio_request(bp->ops->bp_uart_en, "bp_uart_en");
|
||||
if(result)
|
||||
{
|
||||
printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_uart_en);
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t bp_wake_up_irq(int irq, void *dev_id)
|
||||
{
|
||||
|
||||
struct bp_private_data *bp = dev_id;
|
||||
if(bp->ops->bp_wake_ap)
|
||||
bp->ops->bp_wake_ap(bp);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int bp_id_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct bp_private_data *bp = g_bp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bp_id_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long bp_id_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct bp_private_data *bp = g_bp;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int result = 0;
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case BP_IOCTL_SET_PVID:
|
||||
|
||||
break;
|
||||
|
||||
case BP_IOCTL_GET_BPID:
|
||||
if (copy_to_user(argp, &bp->ops->bp_id, sizeof(bp->ops->bp_id)))
|
||||
{
|
||||
printk("%s:failed to copy status to user space.\n",__FUNCTION__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int bp_dev_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct bp_private_data *bp = g_bp;
|
||||
device_init_wakeup(bp->dev, 1);
|
||||
return 0;
|
||||
}
|
||||
static ssize_t bp_dev_write(struct file *file, const char __user *buf,size_t len, loff_t *off)
|
||||
{
|
||||
static char cmd[2];
|
||||
struct bp_private_data *bp = g_bp;
|
||||
|
||||
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]);
|
||||
switch(bp->ops->bp_id)
|
||||
{
|
||||
case BP_ID_MT6229:
|
||||
if (cmd[0] == '0')
|
||||
{
|
||||
gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);
|
||||
}
|
||||
if (cmd[0] == '1')
|
||||
{
|
||||
gpio_direction_output(bp->ops->ap_ready, GPIO_HIGH);
|
||||
}
|
||||
if (cmd[0] == '2')
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_uart_en, GPIO_LOW);
|
||||
}
|
||||
if (cmd[0] == '3')
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_uart_en, GPIO_HIGH);
|
||||
}
|
||||
if (cmd[0] == '4')
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
|
||||
}if (cmd[0] == '5')
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);
|
||||
}
|
||||
break;
|
||||
|
||||
case BP_ID_MU509:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static int bp_dev_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long bp_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct bp_private_data *bp = g_bp;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int result = 0;
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case BP_IOCTL_RESET:
|
||||
if(bp->ops->reset)
|
||||
{
|
||||
bp->ops->reset(bp);
|
||||
}
|
||||
else if(bp->ops->active)
|
||||
{
|
||||
bp->ops->active(bp, 0);
|
||||
msleep(100);
|
||||
bp->ops->active(bp, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case BP_IOCTL_POWON:
|
||||
if(bp->ops->active)
|
||||
bp->ops->active(bp, 1);
|
||||
break;
|
||||
|
||||
case BP_IOCTL_POWOFF:
|
||||
if(bp->ops->active)
|
||||
bp->ops->active(bp, 0);
|
||||
break;
|
||||
|
||||
case BP_IOCTL_WRITE_STATUS:
|
||||
|
||||
break;
|
||||
|
||||
case BP_IOCTL_GET_STATUS:
|
||||
|
||||
break;
|
||||
|
||||
case BP_IOCTL_SET_PVID:
|
||||
|
||||
break;
|
||||
|
||||
case BP_IOCTL_GET_BPID:
|
||||
if (copy_to_user(argp, &bp->ops->bp_id, sizeof(bp->ops->bp_id)))
|
||||
{
|
||||
printk("%s:failed to copy status to user space.\n",__FUNCTION__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t bp_status_read(struct class *cls, struct class_attribute *attr, char *_buf)
|
||||
{
|
||||
struct bp_private_data *bp = g_bp;
|
||||
|
||||
return sprintf(_buf, "%d\n", bp->status);
|
||||
|
||||
}
|
||||
|
||||
static ssize_t bp_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)
|
||||
{
|
||||
struct bp_private_data *bp = g_bp;
|
||||
int result = 0;
|
||||
int status = 0;
|
||||
|
||||
status = simple_strtoul(_buf, NULL, 16);
|
||||
if(status == bp->status)
|
||||
return _count;
|
||||
|
||||
bp->status = status;
|
||||
|
||||
if(bp->ops->write_status)
|
||||
result = bp->ops->write_status(bp);
|
||||
|
||||
return result;
|
||||
}
|
||||
static CLASS_ATTR(bp_status, 0777, bp_status_read, bp_status_write);
|
||||
static int bp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct bp_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct bp_private_data *bp = NULL;
|
||||
int i = 0, result;
|
||||
|
||||
if(!pdata)
|
||||
return -1;
|
||||
|
||||
DBG("%s:init start\n",__func__);
|
||||
|
||||
if(pdata->init_platform_hw)
|
||||
pdata->init_platform_hw();
|
||||
|
||||
bp = kzalloc(sizeof(struct bp_private_data), GFP_KERNEL);
|
||||
if(bp == NULL)
|
||||
{
|
||||
printk("%s:fail malloc bp data\n",__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bp->pdata = pdata;
|
||||
bp->dev = &pdev->dev;
|
||||
|
||||
//select modem acccording to pdata defaultly
|
||||
if((pdata->bp_id > BP_ID_INVALID) && (pdata->bp_id < BP_ID_NUM))
|
||||
{
|
||||
if(g_bp_ops[pdata->bp_id])
|
||||
{
|
||||
bp->ops = g_bp_ops[pdata->bp_id];
|
||||
printk("%s:bp_id=%d\n",__func__,bp->ops->bp_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("%s:error:g_bp_ops[%d] = 0x%p\n",__func__, pdata->bp_id, g_bp_ops[pdata->bp_id]);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("%s:bp_id=%d is out of range\n",__func__, pdata->bp_id);
|
||||
}
|
||||
|
||||
bp_request_gpio(bp);
|
||||
|
||||
if((bp->ops->bp_wakeup_ap) && (bp->ops->trig != BP_UNKNOW_DATA))
|
||||
{
|
||||
result = request_irq(bp->ops->bp_wakeup_ap, bp_wake_up_irq, bp->ops->trig, "bp_wakeup_ap", bp);
|
||||
if (result < 0) {
|
||||
printk("%s: request_irq(%d) failed\n", __func__, bp->ops->bp_wakeup_ap);
|
||||
gpio_free(pdata->bp_wakeup_ap);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(bp->ops->init)
|
||||
bp->ops->init(bp);
|
||||
|
||||
enable_irq_wake(bp->ops->bp_wakeup_ap);
|
||||
wake_lock_init(&bp->bp_wakelock, WAKE_LOCK_SUSPEND, "bp_wakelock");
|
||||
|
||||
bp->status = BP_OFF;
|
||||
|
||||
if(!bp->ops->private_miscdev)
|
||||
{
|
||||
bp->fops.owner = THIS_MODULE;
|
||||
bp->fops.open = bp_dev_open;
|
||||
bp->fops.write = bp_dev_write;
|
||||
bp->fops.release = bp_dev_release;
|
||||
bp->fops.unlocked_ioctl = bp_dev_ioctl;
|
||||
|
||||
bp->miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
if(bp->ops->misc_name)
|
||||
bp->miscdev.name = bp->ops->misc_name;
|
||||
else
|
||||
bp->miscdev.name = "bp-auto";
|
||||
bp->miscdev.fops = &bp->fops;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&bp->miscdev, bp->ops->private_miscdev, sizeof(*bp->ops->private_miscdev));
|
||||
|
||||
}
|
||||
|
||||
result = misc_register(&bp->miscdev);
|
||||
if (result < 0) {
|
||||
printk("misc_register err\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
bp->id_fops.owner = THIS_MODULE;
|
||||
bp->id_fops.open = bp_id_open;
|
||||
bp->id_fops.release = bp_id_release;
|
||||
bp->id_fops.unlocked_ioctl = bp_id_ioctl;
|
||||
|
||||
bp->id_miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
bp->id_miscdev.name = "bp_id";
|
||||
bp->id_miscdev.fops = &bp->id_fops;
|
||||
result = misc_register(&bp->id_miscdev);
|
||||
if (result < 0) {
|
||||
printk("misc_register err\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
g_bp = bp;
|
||||
|
||||
platform_set_drvdata(pdev, bp);
|
||||
|
||||
printk("%s:init success\n",__func__);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int bp_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct bp_private_data *bp = platform_get_drvdata(pdev);
|
||||
|
||||
if(bp->ops->suspend)
|
||||
bp->ops->suspend(bp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bp_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct bp_private_data *bp = platform_get_drvdata(pdev);
|
||||
|
||||
if(bp->ops->resume)
|
||||
bp->ops->resume(bp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bp_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct bp_private_data *bp = platform_get_drvdata(pdev);
|
||||
|
||||
if(bp->ops->shutdown)
|
||||
bp->ops->shutdown(bp);
|
||||
|
||||
if(bp->ops->bp_power != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->bp_power);
|
||||
}
|
||||
|
||||
if(bp->ops->bp_en != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->bp_en);
|
||||
|
||||
}
|
||||
|
||||
if(bp->ops->bp_reset != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->bp_reset);
|
||||
}
|
||||
|
||||
if(bp->ops->ap_ready != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->ap_ready);
|
||||
|
||||
}
|
||||
|
||||
if(bp->ops->bp_ready != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->bp_ready);
|
||||
|
||||
}
|
||||
|
||||
if(bp->ops->ap_wakeup_bp != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->ap_wakeup_bp);
|
||||
|
||||
}
|
||||
|
||||
if(bp->ops->bp_wakeup_ap != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->bp_wakeup_ap);
|
||||
|
||||
}
|
||||
|
||||
if(bp->ops->bp_usb_en != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->bp_usb_en);
|
||||
|
||||
}
|
||||
|
||||
if(bp->ops->bp_uart_en != BP_UNKNOW_DATA)
|
||||
{
|
||||
gpio_free(bp->ops->bp_uart_en);
|
||||
|
||||
}
|
||||
|
||||
if(bp->pdata->exit_platform_hw)
|
||||
bp->pdata->exit_platform_hw();
|
||||
|
||||
kfree(bp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int bp_register_slave(struct bp_private_data *bp,
|
||||
struct bp_platform_data *slave_pdata,
|
||||
struct bp_operate *(*get_bp_ops)(void))
|
||||
{
|
||||
int result = 0;
|
||||
struct bp_operate *ops = get_bp_ops();
|
||||
if((ops->bp_id >= BP_ID_NUM) || (ops->bp_id <= BP_ID_INVALID))
|
||||
{
|
||||
printk("%s:%s id is error %d\n", __func__, ops->name, ops->bp_id);
|
||||
return -1;
|
||||
}
|
||||
g_bp_ops[ops->bp_id] = ops;
|
||||
printk("%s:%s,id=%d\n",__func__,g_bp_ops[ops->bp_id]->name, ops->bp_id);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int bp_unregister_slave(struct bp_private_data *bp,
|
||||
struct bp_platform_data *slave_pdata,
|
||||
struct bp_operate *(*get_bp_ops)(void))
|
||||
{
|
||||
int result = 0;
|
||||
struct bp_operate *ops = get_bp_ops();
|
||||
if((ops->bp_id >= BP_ID_NUM) || (ops->bp_id <= BP_ID_INVALID))
|
||||
{
|
||||
printk("%s:%s id is error %d\n", __func__, ops->name, ops->bp_id);
|
||||
return -1;
|
||||
}
|
||||
printk("%s:%s,id=%d\n",__func__,g_bp_ops[ops->bp_id]->name, ops->bp_id);
|
||||
g_bp_ops[ops->bp_id] = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static struct platform_driver bp_driver = {
|
||||
.probe = bp_probe,
|
||||
.shutdown = bp_shutdown,
|
||||
.suspend = bp_suspend,
|
||||
.resume = bp_resume,
|
||||
.driver = {
|
||||
.name = "bp-auto",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init bp_init(void)
|
||||
{
|
||||
int ret ;
|
||||
bp_class = class_create(THIS_MODULE, "bp-auto");
|
||||
ret = class_create_file(bp_class, &class_attr_bp_status);
|
||||
if (ret)
|
||||
{
|
||||
printk("Fail to create class bp-auto\n");
|
||||
}
|
||||
return platform_driver_register(&bp_driver);
|
||||
}
|
||||
|
||||
static void __exit bp_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&bp_driver);
|
||||
class_remove_file(bp_class, &class_attr_bp_status);
|
||||
}
|
||||
|
||||
module_init(bp_init);
|
||||
module_exit(bp_exit);
|
||||
|
||||
MODULE_AUTHOR("ROCKCHIP Corporation:lw@rock-chips.com");
|
||||
MODULE_DESCRIPTION("device interface for auto modem driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
7
drivers/misc/bp/chips/Kconfig
Normal file
7
drivers/misc/bp/chips/Kconfig
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
config BP_AUTO_MT6229
|
||||
bool "modem mt6229"
|
||||
default n
|
||||
|
||||
config BP_AUTO_MU509
|
||||
bool "modem mu509"
|
||||
default n
|
||||
2
drivers/misc/bp/chips/Makefile
Normal file
2
drivers/misc/bp/chips/Makefile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
obj-$(CONFIG_BP_AUTO_MT6229) += mt6229.o
|
||||
obj-$(CONFIG_BP_AUTO_MU509) += mu509.o
|
||||
282
drivers/misc/bp/chips/mt6229.c
Executable file
282
drivers/misc/bp/chips/mt6229.c
Executable file
|
|
@ -0,0 +1,282 @@
|
|||
/* drivers/misc/bp/chips/mt6229.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)
|
||||
{
|
||||
int result = 0;
|
||||
if(enable)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->bp_uart_en, GPIO_LOW);
|
||||
|
||||
gpio_direction_output(bp->ops->ap_ready, GPIO_HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_en, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);
|
||||
gpio_direction_output(bp->ops->bp_uart_en, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ap_wake_bp(struct bp_private_data *bp, int wake)
|
||||
{
|
||||
int result = 0;
|
||||
if(wake)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_uart_en, GPIO_LOW);
|
||||
msleep(2000);
|
||||
gpio_direction_output(bp->ops->ap_ready, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->bp_uart_en, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int result = 0;
|
||||
gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
|
||||
msleep(1000);
|
||||
if(bp->ops->active)
|
||||
bp->ops->active(bp, 1);
|
||||
|
||||
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int bp_wake_ap(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(bp->suspend_status)
|
||||
{
|
||||
bp->suspend_status = 0;
|
||||
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int bp_shutdown(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(bp->ops->active)
|
||||
bp->ops->active(bp, 0);
|
||||
|
||||
cancel_delayed_work_sync(&bp->wakeup_work);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int read_status(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int write_status(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (bp->status == BP_ON)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->bp_uart_en,GPIO_LOW);
|
||||
}
|
||||
else if(bp->status == BP_OFF)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);
|
||||
gpio_direction_output(bp->ops->bp_uart_en,GPIO_HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("%s, invalid parameter \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int bp_suspend(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(!bp->suspend_status)
|
||||
{
|
||||
bp->suspend_status = 1;
|
||||
if(bp->ops->ap_wake_bp)
|
||||
bp->ops->ap_wake_bp(bp, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int bp_resume(struct bp_private_data *bp)
|
||||
{
|
||||
if(bp->suspend_status)
|
||||
{
|
||||
bp->suspend_status = 0;
|
||||
PREPARE_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
|
||||
schedule_delayed_work(&bp->wakeup_work, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct bp_operate bp_mt6229_ops = {
|
||||
.name = "mt6229",
|
||||
.bp_id = BP_ID_MT6229,
|
||||
.bp_bus = BP_BUS_TYPE_USB_UART,
|
||||
.bp_pid = 0,
|
||||
.bp_vid = 0,
|
||||
.bp_power = RK30_PIN6_PB2, // 3g_power
|
||||
.bp_en = RK30_PIN2_PB6, // 3g_en
|
||||
.bp_reset = BP_UNKNOW_DATA,
|
||||
.ap_ready = RK30_PIN2_PB7, //
|
||||
.bp_ready = BP_UNKNOW_DATA,
|
||||
.ap_wakeup_bp = BP_UNKNOW_DATA,
|
||||
.bp_wakeup_ap = RK30_PIN6_PA1, //
|
||||
.bp_uart_en = RK30_PIN2_PC1, //EINT9
|
||||
.bp_usb_en = RK30_PIN2_PC0, //W_disable
|
||||
.trig = IRQF_TRIGGER_RISING,
|
||||
|
||||
.active = bp_active,
|
||||
.init = bp_init,
|
||||
.ap_wake_bp = ap_wake_bp,
|
||||
.bp_wake_ap = bp_wake_ap,
|
||||
.shutdown = bp_shutdown,
|
||||
.read_status = read_status,
|
||||
.write_status = write_status,
|
||||
.suspend = bp_suspend,
|
||||
.resume = bp_resume,
|
||||
.misc_name = "mt6229",
|
||||
.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_mt6229_ops;
|
||||
}
|
||||
|
||||
static int __init bp_mt6229_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_mt6229_exit(void)
|
||||
{
|
||||
//struct bp_operate *ops = bp_get_ops();
|
||||
bp_unregister_slave(NULL, NULL, bp_get_ops);
|
||||
}
|
||||
|
||||
|
||||
subsys_initcall(bp_mt6229_init);
|
||||
module_exit(bp_mt6229_exit);
|
||||
|
||||
281
drivers/misc/bp/chips/mu509.c
Executable file
281
drivers/misc/bp/chips/mu509.c
Executable file
|
|
@ -0,0 +1,281 @@
|
|||
/* drivers/misc/bp/chips/mu509.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)
|
||||
{
|
||||
int result = 0;
|
||||
if(enable)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_reset, GPIO_HIGH);
|
||||
msleep(100);
|
||||
gpio_direction_output(bp->ops->bp_reset, GPIO_LOW);
|
||||
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
|
||||
msleep(1000);
|
||||
gpio_direction_output(bp->ops->bp_en, GPIO_HIGH);
|
||||
msleep(700);
|
||||
gpio_direction_output(bp->ops->bp_en, GPIO_LOW);
|
||||
gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
|
||||
gpio_set_value(bp->ops->bp_en, GPIO_HIGH);
|
||||
msleep(2500);
|
||||
gpio_set_value(bp->ops->bp_en, GPIO_LOW);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ap_wake_bp(struct bp_private_data *bp, int wake)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
gpio_direction_output(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)
|
||||
{
|
||||
int result = 0;
|
||||
gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
|
||||
msleep(1000);
|
||||
if(bp->ops->active)
|
||||
bp->ops->active(bp, 1);
|
||||
|
||||
INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int bp_reset(struct bp_private_data *bp)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);
|
||||
msleep(100);
|
||||
gpio_direction_output(bp->ops->bp_power, GPIO_LOW);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bp_wake_ap(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(bp->suspend_status)
|
||||
{
|
||||
bp->suspend_status = 0;
|
||||
wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int bp_shutdown(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(bp->ops->active)
|
||||
bp->ops->active(bp, 0);
|
||||
|
||||
cancel_delayed_work_sync(&bp->wakeup_work);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int read_status(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int write_status(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (bp->status == BP_ON)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);
|
||||
gpio_direction_output(bp->ops->bp_uart_en,GPIO_LOW);
|
||||
}
|
||||
else if(bp->status == BP_OFF)
|
||||
{
|
||||
gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);
|
||||
gpio_direction_output(bp->ops->bp_uart_en,GPIO_HIGH);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("%s, invalid parameter \n", __FUNCTION__);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int bp_suspend(struct bp_private_data *bp)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if(!bp->suspend_status)
|
||||
{
|
||||
bp->suspend_status = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int bp_resume(struct bp_private_data *bp)
|
||||
{
|
||||
if(bp->suspend_status)
|
||||
{
|
||||
bp->suspend_status = 0;
|
||||
gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct bp_operate bp_mu509_ops = {
|
||||
.name = "mu509",
|
||||
.bp_id = BP_ID_MU509,
|
||||
.bp_bus = BP_BUS_TYPE_USB_UART,
|
||||
.bp_pid = 0,
|
||||
.bp_vid = 0,
|
||||
.bp_power = RK30_PIN6_PB2, // 3g_power
|
||||
.bp_en = RK30_PIN2_PB6, // 3g_en
|
||||
.bp_reset = RK30_PIN2_PC1,
|
||||
.ap_ready = BP_UNKNOW_DATA, //
|
||||
.bp_ready = BP_UNKNOW_DATA,
|
||||
.ap_wakeup_bp = RK30_PIN2_PB7,
|
||||
.bp_wakeup_ap = RK30_PIN6_PA1, //
|
||||
.bp_uart_en = BP_UNKNOW_DATA, //EINT9
|
||||
.bp_usb_en = BP_UNKNOW_DATA, //W_disable
|
||||
.trig = IRQF_TRIGGER_FALLING,
|
||||
|
||||
.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 = read_status,
|
||||
.write_status = write_status,
|
||||
.suspend = bp_suspend,
|
||||
.resume = bp_resume,
|
||||
.misc_name = "mu509",
|
||||
.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_mu509_ops;
|
||||
}
|
||||
|
||||
static int __init bp_mu509_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_mu509_exit(void)
|
||||
{
|
||||
//struct bp_operate *ops = bp_get_ops();
|
||||
bp_unregister_slave(NULL, NULL, bp_get_ops);
|
||||
}
|
||||
|
||||
|
||||
subsys_initcall(bp_mu509_init);
|
||||
module_exit(bp_mu509_exit);
|
||||
|
||||
135
include/linux/bp-auto.h
Normal file
135
include/linux/bp-auto.h
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
#ifndef _BP_AUTO_H
|
||||
#define _BP_AUTO_H
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
struct bp_private_data;
|
||||
|
||||
#define BP_UNKNOW_DATA -1
|
||||
#define BP_OFF 0
|
||||
#define BP_ON 1
|
||||
#define BP_SUSPEND 2
|
||||
#define BP_WAKE 3
|
||||
|
||||
#define BP_IOCTL_BASE 'm'
|
||||
|
||||
#define BP_IOCTL_RESET _IOW(BP_IOCTL_BASE, 0x00, int)
|
||||
#define BP_IOCTL_POWON _IOW(BP_IOCTL_BASE, 0x01, int)
|
||||
#define BP_IOCTL_POWOFF _IOW(BP_IOCTL_BASE, 0x02, int)
|
||||
#define BP_IOCTL_WRITE_STATUS _IOW(BP_IOCTL_BASE, 0x03, int)
|
||||
#define BP_IOCTL_GET_STATUS _IOR(BP_IOCTL_BASE, 0x04, int)
|
||||
#define BP_IOCTL_SET_PVID _IOW(BP_IOCTL_BASE, 0x05, int)
|
||||
#define BP_IOCTL_GET_BPID _IOR(BP_IOCTL_BASE, 0x06, int)
|
||||
|
||||
enum bp_id{
|
||||
BP_ID_INVALID = 0,
|
||||
|
||||
BP_ID_MT6229,
|
||||
BP_ID_MU509,
|
||||
BP_ID_MI700,
|
||||
BP_ID_MW100,
|
||||
BP_ID_TD8801,
|
||||
|
||||
BP_ID_NUM,
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum bp_bus_type{
|
||||
BP_BUS_TYPE_INVALID = 0,
|
||||
|
||||
BP_BUS_TYPE_UART,
|
||||
BP_BUS_TYPE_SPI,
|
||||
BP_BUS_TYPE_USB,
|
||||
BP_BUS_TYPE_SDIO,
|
||||
BP_BUS_TYPE_USB_UART,
|
||||
BP_BUS_TYPE_SPI_UART,
|
||||
BP_BUS_TYPE_SDIO_UART,
|
||||
|
||||
BP_BUS_TYPE_NUM_ID,
|
||||
};
|
||||
|
||||
struct bp_platform_data {
|
||||
int board_id;
|
||||
int bp_id;
|
||||
int (*init_platform_hw)(void);
|
||||
int (*exit_platform_hw)(void);
|
||||
|
||||
int bp_power;
|
||||
int bp_en;
|
||||
int bp_reset;
|
||||
int ap_ready;
|
||||
int bp_ready;
|
||||
int ap_wakeup_bp;
|
||||
int bp_wakeup_ap;
|
||||
int bp_usb_en;
|
||||
int bp_uart_en;
|
||||
|
||||
int gpio_valid;
|
||||
};
|
||||
|
||||
|
||||
struct bp_operate {
|
||||
char *name;
|
||||
int bp_id;
|
||||
int bp_bus;
|
||||
|
||||
int bp_pid;
|
||||
int bp_vid;
|
||||
int bp_power;
|
||||
int bp_en;
|
||||
int bp_reset;
|
||||
int ap_ready;
|
||||
int bp_ready;
|
||||
int ap_wakeup_bp;
|
||||
int bp_wakeup_ap;
|
||||
int bp_usb_en;
|
||||
int bp_uart_en;
|
||||
int trig;
|
||||
|
||||
int (*active)(struct bp_private_data *bp, int enable);
|
||||
int (*init)(struct bp_private_data *bp);
|
||||
int (*reset)(struct bp_private_data *bp);
|
||||
int (*ap_wake_bp)(struct bp_private_data *bp, int wake);
|
||||
int (*bp_wake_ap)(struct bp_private_data *bp);
|
||||
int (*shutdown)(struct bp_private_data *bp);
|
||||
int (*read_status)(struct bp_private_data *bp);
|
||||
int (*write_status)(struct bp_private_data *bp);
|
||||
int (*suspend)(struct bp_private_data *bp);
|
||||
int (*resume)(struct bp_private_data *bp);
|
||||
|
||||
char *misc_name;
|
||||
struct miscdevice *private_miscdev;
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct bp_private_data {
|
||||
struct device *dev;
|
||||
int status;
|
||||
int suspend_status;
|
||||
struct wake_lock bp_wakelock;
|
||||
struct delayed_work wakeup_work; /*report second event*/
|
||||
struct bp_platform_data *pdata;
|
||||
struct bp_operate *ops;
|
||||
struct file_operations fops;
|
||||
struct miscdevice miscdev;
|
||||
struct file_operations id_fops;
|
||||
struct miscdevice id_miscdev;
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
struct early_suspend early_suspend;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int bp_register_slave(struct bp_private_data *bp,
|
||||
struct bp_platform_data *slave_pdata,
|
||||
struct bp_operate *(*get_bp_ops)(void));
|
||||
|
||||
|
||||
extern int bp_unregister_slave(struct bp_private_data *bp,
|
||||
struct bp_platform_data *slave_pdata,
|
||||
struct bp_operate *(*get_bp_ops)(void));
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user