rk30_phonepad:add auto modem driver support
authorluowei <lw@rock-chips.com>
Wed, 24 Oct 2012 10:11:05 +0000 (18:11 +0800)
committerluowei <lw@rock-chips.com>
Wed, 24 Oct 2012 10:11:05 +0000 (18:11 +0800)
drivers/misc/bp/Kconfig [new file with mode: 0755]
drivers/misc/bp/Makefile [new file with mode: 0755]
drivers/misc/bp/bp-auto.c [new file with mode: 0755]
drivers/misc/bp/chips/Kconfig [new file with mode: 0644]
drivers/misc/bp/chips/Makefile [new file with mode: 0644]
drivers/misc/bp/chips/mt6229.c [new file with mode: 0755]
drivers/misc/bp/chips/mu509.c [new file with mode: 0755]
include/linux/bp-auto.h [new file with mode: 0644]

diff --git a/drivers/misc/bp/Kconfig b/drivers/misc/bp/Kconfig
new file mode 100755 (executable)
index 0000000..a3b8411
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# all auto modem control drivers configuration\r
+#
+
+menuconfig BP_AUTO\r
+       bool "auto modem control driver support"\r
+       default n       
+
+if BP_AUTO\r
+\r
+       source "drivers/misc/bp/chips/Kconfig"\r
+\r
+endif\r
diff --git a/drivers/misc/bp/Makefile b/drivers/misc/bp/Makefile
new file mode 100755 (executable)
index 0000000..d32f5e1
--- /dev/null
@@ -0,0 +1,3 @@
+# auto modem control drivers\r
+obj-$(CONFIG_BP_AUTO)                  += chips/\r
+obj-$(CONFIG_BP_AUTO)                  += bp-auto.o
\ No newline at end of file
diff --git a/drivers/misc/bp/bp-auto.c b/drivers/misc/bp/bp-auto.c
new file mode 100755 (executable)
index 0000000..16af64f
--- /dev/null
@@ -0,0 +1,665 @@
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/i2c.h>\r
+#include <linux/irq.h>\r
+#include <linux/gpio.h>\r
+#include <linux/input.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/fs.h>\r
+#include <linux/uaccess.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/miscdevice.h>\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <asm/gpio.h>\r
+#include <linux/delay.h>\r
+#include <linux/poll.h>\r
+#include <linux/wait.h>\r
+#include <linux/wakelock.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/slab.h>\r
+#include <linux/earlysuspend.h>\r
+\r
+#include <linux/bp-auto.h>\r
+\r
+#if 0\r
+#define DBG(x...)  printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+struct bp_private_data *g_bp;\r
+static struct class *g_bp_class;\r
+static struct bp_operate *g_bp_ops[BP_ID_NUM]; \r
+struct class *bp_class = NULL; \r
+\r
+static void ap_wakeup_bp(struct bp_private_data *bp, int wake)\r
+{\r
+       if(bp->ops->ap_wake_bp)\r
+               bp->ops->ap_wake_bp(bp, wake);  \r
+       \r
+}\r
+\r
+static int bp_request_gpio(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       \r
+       if(bp->pdata->gpio_valid)\r
+       {\r
+               if(bp->pdata->bp_power > 0)\r
+               {\r
+                       bp->ops->bp_power = bp->pdata->bp_power;\r
+               }\r
+\r
+               if(bp->pdata->bp_en > 0)\r
+               {\r
+                       bp->ops->bp_en = bp->pdata->bp_en;\r
+               }\r
+\r
+               if(bp->pdata->bp_reset > 0)\r
+               {\r
+                       bp->ops->bp_reset = bp->pdata->bp_reset;\r
+               }\r
+\r
+               if(bp->pdata->ap_ready > 0)\r
+               {\r
+                       bp->ops->ap_ready = bp->pdata->ap_ready;\r
+               }\r
+\r
+               if(bp->pdata->bp_ready > 0)\r
+               {\r
+                       bp->ops->bp_ready = bp->pdata->bp_ready;\r
+               }\r
+\r
+               if(bp->pdata->ap_wakeup_bp > 0)\r
+               {\r
+                       bp->ops->ap_wakeup_bp = bp->pdata->ap_wakeup_bp;\r
+               }\r
+\r
+               if(bp->pdata->bp_wakeup_ap > 0)\r
+               {\r
+                       bp->ops->bp_wakeup_ap = bp->pdata->bp_wakeup_ap;\r
+               }\r
+\r
+               if(bp->pdata->bp_usb_en > 0)\r
+               {\r
+                       bp->ops->bp_usb_en = bp->pdata->bp_usb_en;\r
+               }\r
+               \r
+               if(bp->pdata->bp_uart_en > 0)\r
+               {\r
+                       bp->ops->bp_uart_en = bp->pdata->bp_uart_en;\r
+               }\r
+\r
+       }\r
+       \r
+       if(bp->ops->bp_power != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->bp_power, "bp_power");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_power);\r
+                       //return -1;\r
+               }\r
+       }\r
+       \r
+       if(bp->ops->bp_en != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->bp_en, "bp_en");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_en);\r
+                       //return -1;\r
+               }\r
+       }\r
+\r
+\r
+       if(bp->ops->bp_reset != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->bp_reset, "bp_reset");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_reset);\r
+                       //return -1;\r
+               }\r
+       }\r
+\r
+\r
+       if(bp->ops->ap_ready != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->ap_ready, "ap_ready");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->ap_ready);\r
+                       //return -1;\r
+               }\r
+       }\r
+\r
+\r
+       if(bp->ops->bp_ready != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->bp_ready, "bp_ready");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_ready);\r
+                       //return -1;\r
+               }\r
+       }\r
+\r
+\r
+       if(bp->ops->ap_wakeup_bp != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->ap_wakeup_bp, "ap_wakeup_bp");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->ap_wakeup_bp);\r
+                       //return -1;\r
+               }\r
+       }\r
+\r
+       if(bp->ops->bp_wakeup_ap != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->bp_wakeup_ap, "bp_wakeup_ap");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_wakeup_ap);\r
+                       //return -1;\r
+               }\r
+       }\r
+\r
+       if(bp->ops->bp_usb_en != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->bp_usb_en, "bp_usb_en");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_usb_en);\r
+                       //return -1;\r
+               }\r
+       }\r
+\r
+       if(bp->ops->bp_uart_en != BP_UNKNOW_DATA)\r
+       {\r
+               result = gpio_request(bp->ops->bp_uart_en, "bp_uart_en");\r
+               if(result)\r
+               {\r
+                       printk("%s:fail to request gpio %d\n",__func__, bp->ops->bp_uart_en);\r
+                       //return -1;\r
+               }\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static irqreturn_t bp_wake_up_irq(int irq, void *dev_id)\r
+{\r
+       \r
+       struct bp_private_data *bp = dev_id;\r
+       if(bp->ops->bp_wake_ap)\r
+               bp->ops->bp_wake_ap(bp);\r
+       \r
+       return IRQ_HANDLED;\r
+}\r
+\r
+static int bp_id_open(struct inode *inode, struct file *file)\r
+{\r
+       struct bp_private_data *bp = g_bp;\r
+       \r
+       return 0;\r
+}\r
+\r
+static int bp_id_release(struct inode *inode, struct file *file)\r
+{\r
+\r
+       return 0;\r
+}\r
+\r
+static long bp_id_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
+{\r
+       struct bp_private_data *bp = g_bp;\r
+       void __user *argp = (void __user *)arg;\r
+       int result = 0;\r
+\r
+       switch(cmd)\r
+       {       \r
+               case BP_IOCTL_SET_PVID:\r
+                       \r
+                       break;\r
+       \r
+               case BP_IOCTL_GET_BPID:\r
+                       if (copy_to_user(argp, &bp->ops->bp_id, sizeof(bp->ops->bp_id)))\r
+                       {\r
+                               printk("%s:failed to copy status to user space.\n",__FUNCTION__);\r
+                               return -EFAULT;\r
+                       }\r
+                       \r
+                       break;\r
+                       \r
+               default:\r
+                       break;\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+static int bp_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       struct bp_private_data *bp = g_bp;\r
+       device_init_wakeup(bp->dev, 1);\r
+       return 0;\r
+}\r
+static ssize_t bp_dev_write(struct file *file, const char __user *buf,size_t len, loff_t *off)\r
+{      \r
+       static char cmd[2];\r
+       struct bp_private_data *bp = g_bp;\r
+       \r
+       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]);\r
+       switch(bp->ops->bp_id)\r
+       {\r
+               case BP_ID_MT6229:\r
+                       if (cmd[0] == '0')\r
+                       {\r
+                               gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);\r
+                       }       \r
+                       if (cmd[0] == '1')\r
+                       {\r
+                               gpio_direction_output(bp->ops->ap_ready, GPIO_HIGH);\r
+                       }\r
+                       if (cmd[0] == '2')\r
+                       {\r
+                               gpio_direction_output(bp->ops->bp_uart_en, GPIO_LOW);\r
+                       }\r
+                       if (cmd[0] == '3')\r
+                       {\r
+                               gpio_direction_output(bp->ops->bp_uart_en, GPIO_HIGH);\r
+                       }\r
+                       if (cmd[0] == '4')\r
+                       {\r
+                               gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);\r
+                       }if (cmd[0] == '5')\r
+                       {\r
+                               gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);\r
+                       }\r
+                       break;\r
+               \r
+               case BP_ID_MU509:\r
+                       break;\r
+\r
+               default:\r
+                       break;\r
+\r
+       }\r
+       return len;\r
+}\r
+static int bp_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       return 0;\r
+}\r
+\r
+static long bp_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\r
+{\r
+       struct bp_private_data *bp = g_bp;\r
+       void __user *argp = (void __user *)arg;\r
+       int result = 0;\r
+\r
+       switch(cmd)\r
+       {\r
+               case BP_IOCTL_RESET:    \r
+                       if(bp->ops->reset)\r
+                       {\r
+                               bp->ops->reset(bp);\r
+                       }\r
+                       else if(bp->ops->active)\r
+                       {\r
+                               bp->ops->active(bp, 0);\r
+                               msleep(100);\r
+                               bp->ops->active(bp, 1);\r
+                       }\r
+                       break;\r
+                       \r
+               case BP_IOCTL_POWON:\r
+                       if(bp->ops->active)\r
+                       bp->ops->active(bp, 1);\r
+                       break;\r
+                       \r
+               case BP_IOCTL_POWOFF:\r
+                       if(bp->ops->active)\r
+                       bp->ops->active(bp, 0);\r
+                       break;\r
+       \r
+               case BP_IOCTL_WRITE_STATUS:\r
+                       \r
+                       break;\r
+       \r
+               case BP_IOCTL_GET_STATUS:\r
+                       \r
+                       break;\r
+\r
+               case BP_IOCTL_SET_PVID:\r
+                       \r
+                       break;\r
+       \r
+               case BP_IOCTL_GET_BPID:\r
+                       if (copy_to_user(argp, &bp->ops->bp_id, sizeof(bp->ops->bp_id)))\r
+                       {\r
+                               printk("%s:failed to copy status to user space.\n",__FUNCTION__);\r
+                               return -EFAULT;\r
+                       }\r
+                       \r
+                       break;\r
+                       \r
+               default:\r
+                       break;\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+static ssize_t bp_status_read(struct class *cls, struct class_attribute *attr, char *_buf)\r
+{\r
+       struct bp_private_data *bp = g_bp;\r
+       \r
+       return sprintf(_buf, "%d\n", bp->status);\r
+       \r
+}\r
+\r
+static ssize_t bp_status_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count)\r
+{      \r
+       struct bp_private_data *bp = g_bp;\r
+       int result = 0;\r
+       int status = 0;\r
+       \r
+       status = simple_strtoul(_buf, NULL, 16);\r
+       if(status == bp->status) \r
+               return _count;\r
+       \r
+       bp->status = status;\r
+       \r
+       if(bp->ops->write_status)\r
+               result = bp->ops->write_status(bp);     \r
+          \r
+       return result; \r
+}\r
+static CLASS_ATTR(bp_status, 0777, bp_status_read, bp_status_write);\r
+static int bp_probe(struct platform_device *pdev)\r
+{\r
+       struct bp_platform_data *pdata = pdev->dev.platform_data;\r
+       struct bp_private_data *bp = NULL;\r
+       int i = 0, result;      \r
+\r
+       if(!pdata)\r
+               return -1;\r
+       \r
+       DBG("%s:init start\n",__func__);\r
+       \r
+       if(pdata->init_platform_hw)\r
+               pdata->init_platform_hw();\r
+       \r
+       bp = kzalloc(sizeof(struct bp_private_data), GFP_KERNEL);\r
+       if(bp == NULL)\r
+       {\r
+               printk("%s:fail malloc bp data\n",__func__);\r
+               return -1;\r
+       }\r
+\r
+       bp->pdata = pdata;\r
+       bp->dev = &pdev->dev;\r
+       \r
+       //select modem acccording to pdata defaultly\r
+       if((pdata->bp_id > BP_ID_INVALID) && (pdata->bp_id < BP_ID_NUM))\r
+       {\r
+               if(g_bp_ops[pdata->bp_id])\r
+               {\r
+                       bp->ops = g_bp_ops[pdata->bp_id];\r
+                       printk("%s:bp_id=%d\n",__func__,bp->ops->bp_id);\r
+               }\r
+               else\r
+               {\r
+                       printk("%s:error:g_bp_ops[%d] = 0x%p\n",__func__, pdata->bp_id, g_bp_ops[pdata->bp_id]);\r
+               }\r
+               \r
+       }\r
+       else\r
+       {\r
+               printk("%s:bp_id=%d is out of range\n",__func__, pdata->bp_id);\r
+       }\r
+       \r
+       bp_request_gpio(bp);\r
+       \r
+       if((bp->ops->bp_wakeup_ap) && (bp->ops->trig != BP_UNKNOW_DATA))\r
+       {\r
+               result = request_irq(bp->ops->bp_wakeup_ap, bp_wake_up_irq, bp->ops->trig, "bp_wakeup_ap", bp);\r
+               if (result < 0) {\r
+                       printk("%s: request_irq(%d) failed\n", __func__, bp->ops->bp_wakeup_ap);\r
+                       gpio_free(pdata->bp_wakeup_ap);\r
+                       return result;\r
+               }\r
+       }\r
+\r
+       if(bp->ops->init)\r
+               bp->ops->init(bp);\r
+       \r
+       enable_irq_wake(bp->ops->bp_wakeup_ap);\r
+       wake_lock_init(&bp->bp_wakelock, WAKE_LOCK_SUSPEND, "bp_wakelock");\r
+       \r
+       bp->status = BP_OFF;\r
+\r
+       if(!bp->ops->private_miscdev)\r
+       {\r
+               bp->fops.owner = THIS_MODULE;\r
+               bp->fops.open = bp_dev_open;\r
+               bp->fops.write = bp_dev_write;\r
+               bp->fops.release = bp_dev_release;      \r
+               bp->fops.unlocked_ioctl = bp_dev_ioctl;\r
+\r
+               bp->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+               if(bp->ops->misc_name)\r
+               bp->miscdev.name = bp->ops->misc_name;\r
+               else    \r
+               bp->miscdev.name = "bp-auto";\r
+               bp->miscdev.fops = &bp->fops;\r
+       }\r
+       else\r
+       {\r
+               memcpy(&bp->miscdev, bp->ops->private_miscdev, sizeof(*bp->ops->private_miscdev));\r
+\r
+       }\r
+       \r
+       result = misc_register(&bp->miscdev);\r
+       if (result < 0) {\r
+               printk("misc_register err\n");\r
+               return result;\r
+       }\r
+\r
+       bp->id_fops.owner = THIS_MODULE;\r
+       bp->id_fops.open = bp_id_open;\r
+       bp->id_fops.release = bp_id_release;    \r
+       bp->id_fops.unlocked_ioctl = bp_id_ioctl;\r
+\r
+       bp->id_miscdev.minor = MISC_DYNAMIC_MINOR;\r
+       bp->id_miscdev.name = "bp_id";\r
+       bp->id_miscdev.fops = &bp->id_fops;\r
+       result = misc_register(&bp->id_miscdev);\r
+       if (result < 0) {\r
+               printk("misc_register err\n");\r
+               return result;\r
+       }\r
+       \r
+       g_bp = bp;\r
+\r
+       platform_set_drvdata(pdev, bp); \r
+       \r
+       printk("%s:init success\n",__func__);\r
+       return result;\r
+\r
+}\r
+\r
+int bp_suspend(struct platform_device *pdev, pm_message_t state)\r
+{\r
+       struct bp_private_data *bp = platform_get_drvdata(pdev);\r
+       \r
+       if(bp->ops->suspend)\r
+               bp->ops->suspend(bp);\r
+       \r
+       return 0;\r
+}\r
+\r
+int bp_resume(struct platform_device *pdev)\r
+{\r
+       struct bp_private_data *bp = platform_get_drvdata(pdev);\r
+       \r
+       if(bp->ops->resume)\r
+               bp->ops->resume(bp);\r
+\r
+       return 0;\r
+}\r
+\r
+void bp_shutdown(struct platform_device *pdev)\r
+{\r
+       struct bp_private_data *bp = platform_get_drvdata(pdev);\r
+\r
+       if(bp->ops->shutdown)\r
+               bp->ops->shutdown(bp);\r
+       \r
+       if(bp->ops->bp_power != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->bp_power);   \r
+       }\r
+       \r
+       if(bp->ops->bp_en != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->bp_en);\r
+               \r
+       }\r
+\r
+       if(bp->ops->bp_reset != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->bp_reset);   \r
+       }\r
+       \r
+       if(bp->ops->ap_ready != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->ap_ready);\r
+               \r
+       }\r
+       \r
+       if(bp->ops->bp_ready != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->bp_ready);\r
+               \r
+       }\r
+       \r
+       if(bp->ops->ap_wakeup_bp != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->ap_wakeup_bp);\r
+               \r
+       }\r
+       \r
+       if(bp->ops->bp_wakeup_ap != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->bp_wakeup_ap);\r
+               \r
+       }\r
+       \r
+       if(bp->ops->bp_usb_en != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->bp_usb_en);\r
+               \r
+       }\r
+       \r
+       if(bp->ops->bp_uart_en != BP_UNKNOW_DATA)\r
+       {\r
+               gpio_free(bp->ops->bp_uart_en);\r
+               \r
+       }\r
+       \r
+       if(bp->pdata->exit_platform_hw)\r
+               bp->pdata->exit_platform_hw();\r
+       \r
+       kfree(bp);\r
+       \r
+}\r
+\r
+\r
+int bp_register_slave(struct bp_private_data *bp,\r
+                       struct bp_platform_data *slave_pdata,\r
+                       struct bp_operate *(*get_bp_ops)(void))\r
+{\r
+       int result = 0;\r
+       struct bp_operate *ops = get_bp_ops();\r
+       if((ops->bp_id >= BP_ID_NUM) || (ops->bp_id <= BP_ID_INVALID))\r
+       {       \r
+               printk("%s:%s id is error %d\n", __func__, ops->name, ops->bp_id);\r
+               return -1;      \r
+       }\r
+       g_bp_ops[ops->bp_id] = ops;\r
+       printk("%s:%s,id=%d\n",__func__,g_bp_ops[ops->bp_id]->name, ops->bp_id);\r
+       return result;\r
+}\r
+\r
+\r
+int bp_unregister_slave(struct bp_private_data *bp,\r
+                       struct bp_platform_data *slave_pdata,\r
+                       struct bp_operate *(*get_bp_ops)(void))\r
+{\r
+       int result = 0;\r
+       struct bp_operate *ops = get_bp_ops();\r
+       if((ops->bp_id >= BP_ID_NUM) || (ops->bp_id <= BP_ID_INVALID))\r
+       {       \r
+               printk("%s:%s id is error %d\n", __func__, ops->name, ops->bp_id);\r
+               return -1;      \r
+       }\r
+       printk("%s:%s,id=%d\n",__func__,g_bp_ops[ops->bp_id]->name, ops->bp_id);\r
+       g_bp_ops[ops->bp_id] = NULL;    \r
+       return result;\r
+}\r
+\r
+\r
+static struct platform_driver bp_driver = {\r
+       .probe          = bp_probe,\r
+       .shutdown       = bp_shutdown,\r
+       .suspend        = bp_suspend,\r
+       .resume         = bp_resume,\r
+       .driver = {\r
+               .name   = "bp-auto",\r
+               .owner  = THIS_MODULE,\r
+       },\r
+};\r
+\r
+static int __init bp_init(void)\r
+{\r
+       int ret ;\r
+       bp_class = class_create(THIS_MODULE, "bp-auto");\r
+       ret =  class_create_file(bp_class, &class_attr_bp_status);\r
+       if (ret)\r
+       {\r
+               printk("Fail to create class bp-auto\n");\r
+       }\r
+       return platform_driver_register(&bp_driver);\r
+}\r
+\r
+static void __exit bp_exit(void)\r
+{\r
+       platform_driver_unregister(&bp_driver);\r
+       class_remove_file(bp_class, &class_attr_bp_status);\r
+}\r
+\r
+module_init(bp_init);\r
+module_exit(bp_exit);\r
+\r
+MODULE_AUTHOR("ROCKCHIP Corporation:lw@rock-chips.com");\r
+MODULE_DESCRIPTION("device interface for auto modem driver");\r
+MODULE_LICENSE("GPL");\r
+\r
diff --git a/drivers/misc/bp/chips/Kconfig b/drivers/misc/bp/chips/Kconfig
new file mode 100644 (file)
index 0000000..70db74d
--- /dev/null
@@ -0,0 +1,7 @@
+config BP_AUTO_MT6229\r
+bool "modem mt6229"\r
+       default n\r
\r
+config BP_AUTO_MU509\r
+bool "modem mu509"\r
+       default n
\ No newline at end of file
diff --git a/drivers/misc/bp/chips/Makefile b/drivers/misc/bp/chips/Makefile
new file mode 100644 (file)
index 0000000..0f62417
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_BP_AUTO_MT6229)                   += mt6229.o\r
+obj-$(CONFIG_BP_AUTO_MU509)                            += mu509.o
\ No newline at end of file
diff --git a/drivers/misc/bp/chips/mt6229.c b/drivers/misc/bp/chips/mt6229.c
new file mode 100755 (executable)
index 0000000..4e9a9f1
--- /dev/null
@@ -0,0 +1,282 @@
+/* drivers/misc/bp/chips/mt6229.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/i2c.h>\r
+#include <linux/irq.h>\r
+#include <linux/gpio.h>\r
+#include <linux/input.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/fs.h>\r
+#include <linux/uaccess.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/miscdevice.h>\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <asm/gpio.h>\r
+#include <linux/delay.h>\r
+#include <linux/poll.h>\r
+#include <linux/wait.h>\r
+#include <linux/wakelock.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/slab.h>\r
+#include <linux/earlysuspend.h>\r
+\r
+#include <linux/bp-auto.h>\r
+        \r
+        \r
+#if 0\r
+#define DBG(x...)  printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+/****************operate according to bp chip:start************/\r
+static int bp_active(struct bp_private_data *bp, int enable)\r
+{      \r
+       int result = 0;\r
+       if(enable)\r
+       {\r
+               gpio_direction_output(bp->ops->bp_en, GPIO_LOW);\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);\r
+               gpio_direction_output(bp->ops->bp_uart_en, GPIO_LOW);\r
+               \r
+               gpio_direction_output(bp->ops->ap_ready, GPIO_HIGH);\r
+       }\r
+       else\r
+       {\r
+               gpio_direction_output(bp->ops->bp_en, GPIO_HIGH);\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);\r
+               gpio_direction_output(bp->ops->bp_uart_en, GPIO_HIGH);\r
+               gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+static int ap_wake_bp(struct bp_private_data *bp, int wake)\r
+{\r
+       int result = 0;\r
+       if(wake)\r
+       {\r
+               gpio_direction_output(bp->ops->bp_uart_en,  GPIO_LOW);\r
+               msleep(2000);\r
+               gpio_direction_output(bp->ops->ap_ready, GPIO_HIGH);\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);\r
+       }\r
+       else\r
+       {\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);\r
+               gpio_direction_output(bp->ops->bp_uart_en, GPIO_HIGH);  \r
+               gpio_direction_output(bp->ops->ap_ready, GPIO_LOW);\r
+       }\r
+       \r
+       return result;\r
+\r
+}\r
+\r
+static void  ap_wake_bp_work(struct work_struct *work)\r
+{\r
+       struct delayed_work *wakeup_work = container_of(work, struct delayed_work, work);\r
+       struct bp_private_data *bp = container_of(wakeup_work, struct bp_private_data, wakeup_work);\r
+\r
+       if(bp->suspend_status)\r
+       {\r
+               if(bp->ops->ap_wake_bp)\r
+               bp->ops->ap_wake_bp(bp, 0);\r
+       }\r
+       else    \r
+       {\r
+               if(bp->ops->ap_wake_bp)\r
+               bp->ops->ap_wake_bp(bp, 1);\r
+       }\r
+}\r
+\r
+\r
+static int bp_init(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
+       msleep(1000);\r
+       if(bp->ops->active)\r
+               bp->ops->active(bp, 1);\r
+\r
+       INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);\r
+       return result;\r
+}\r
+\r
+static int bp_wake_ap(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       \r
+       if(bp->suspend_status)\r
+       {\r
+               bp->suspend_status = 0;\r
+               wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int bp_shutdown(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       \r
+       if(bp->ops->active)\r
+               bp->ops->active(bp, 0);\r
+       \r
+       cancel_delayed_work_sync(&bp->wakeup_work);     \r
+               \r
+       return result;\r
+}\r
+\r
+\r
+static int read_status(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int write_status(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+\r
+       if (bp->status == BP_ON)\r
+       {\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);\r
+               gpio_direction_output(bp->ops->bp_uart_en,GPIO_LOW);\r
+       }\r
+       else if(bp->status == BP_OFF)\r
+       {\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);\r
+               gpio_direction_output(bp->ops->bp_uart_en,GPIO_HIGH);\r
+       }\r
+       else\r
+       {\r
+               printk("%s, invalid parameter \n", __FUNCTION__);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int bp_suspend(struct bp_private_data *bp)\r
+{      \r
+       int result = 0;\r
+       \r
+       if(!bp->suspend_status)\r
+       {\r
+               bp->suspend_status = 1; \r
+               if(bp->ops->ap_wake_bp)\r
+                       bp->ops->ap_wake_bp(bp, 0);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+\r
+\r
+static int bp_resume(struct bp_private_data *bp)\r
+{\r
+       if(bp->suspend_status)\r
+       {\r
+               bp->suspend_status = 0;\r
+               PREPARE_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);\r
+               schedule_delayed_work(&bp->wakeup_work, 0);\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+struct bp_operate bp_mt6229_ops = {\r
+       .name                   = "mt6229",\r
+       .bp_id                  = BP_ID_MT6229,\r
+       .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
+       .bp_pid                 = 0,    \r
+       .bp_vid                 = 0,    \r
+       .bp_power               = RK30_PIN6_PB2,        // 3g_power\r
+       .bp_en                  = RK30_PIN2_PB6,        // 3g_en\r
+       .bp_reset               = BP_UNKNOW_DATA,\r
+       .ap_ready               = RK30_PIN2_PB7,        //\r
+       .bp_ready               = BP_UNKNOW_DATA,\r
+       .ap_wakeup_bp           = BP_UNKNOW_DATA,\r
+       .bp_wakeup_ap           = RK30_PIN6_PA1,        //\r
+       .bp_uart_en             = RK30_PIN2_PC1,        //EINT9\r
+       .bp_usb_en              = RK30_PIN2_PC0,        //W_disable\r
+       .trig                   = IRQF_TRIGGER_RISING,\r
+\r
+       .active                 = bp_active,\r
+       .init                   = bp_init,\r
+       .ap_wake_bp             = ap_wake_bp,\r
+       .bp_wake_ap             = bp_wake_ap,\r
+       .shutdown               = bp_shutdown,\r
+       .read_status            = read_status,\r
+       .write_status           = write_status,\r
+       .suspend                = bp_suspend,\r
+       .resume                 = bp_resume,\r
+       .misc_name              = "mt6229",\r
+       .private_miscdev        = NULL,\r
+};\r
+\r
+/****************operate according to bp chip:end************/\r
+\r
+//function name should not be changed\r
+static struct bp_operate *bp_get_ops(void)\r
+{\r
+       return &bp_mt6229_ops;\r
+}\r
+\r
+static int __init bp_mt6229_init(void)\r
+{\r
+       struct bp_operate *ops = bp_get_ops();\r
+       int result = 0;\r
+       result = bp_register_slave(NULL, NULL, bp_get_ops);\r
+       if(result)\r
+       {       \r
+               return result;\r
+       }\r
+       \r
+       if(ops->private_miscdev)\r
+       {\r
+               result = misc_register(ops->private_miscdev);\r
+               if (result < 0) {\r
+                       printk("%s:misc_register err\n",__func__);\r
+                       return result;\r
+               }\r
+       }\r
+       \r
+       DBG("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit bp_mt6229_exit(void)\r
+{\r
+       //struct bp_operate *ops = bp_get_ops();\r
+       bp_unregister_slave(NULL, NULL, bp_get_ops);\r
+}\r
+\r
+\r
+subsys_initcall(bp_mt6229_init);\r
+module_exit(bp_mt6229_exit);\r
+\r
diff --git a/drivers/misc/bp/chips/mu509.c b/drivers/misc/bp/chips/mu509.c
new file mode 100755 (executable)
index 0000000..f4228e7
--- /dev/null
@@ -0,0 +1,281 @@
+/* drivers/misc/bp/chips/mu509.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/i2c.h>\r
+#include <linux/irq.h>\r
+#include <linux/gpio.h>\r
+#include <linux/input.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/fs.h>\r
+#include <linux/uaccess.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/circ_buf.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/miscdevice.h>\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <asm/gpio.h>\r
+#include <linux/delay.h>\r
+#include <linux/poll.h>\r
+#include <linux/wait.h>\r
+#include <linux/wakelock.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/slab.h>\r
+#include <linux/earlysuspend.h>\r
+\r
+#include <linux/bp-auto.h>\r
+        \r
+        \r
+#if 0\r
+#define DBG(x...)  printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+\r
+/****************operate according to bp chip:start************/\r
+static int bp_active(struct bp_private_data *bp, int enable)\r
+{      \r
+       int result = 0;\r
+       if(enable)\r
+       {\r
+               gpio_direction_output(bp->ops->bp_reset, GPIO_HIGH);\r
+               msleep(100);\r
+               gpio_direction_output(bp->ops->bp_reset, GPIO_LOW);\r
+               gpio_direction_output(bp->ops->bp_en, GPIO_LOW);\r
+               msleep(1000);\r
+               gpio_direction_output(bp->ops->bp_en, GPIO_HIGH);\r
+               msleep(700);\r
+               gpio_direction_output(bp->ops->bp_en, GPIO_LOW);\r
+               gpio_direction_output(bp->ops->ap_wakeup_bp, GPIO_LOW);\r
+       }\r
+       else\r
+       {\r
+               gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
+               gpio_set_value(bp->ops->bp_en, GPIO_HIGH);\r
+               msleep(2500);\r
+               gpio_set_value(bp->ops->bp_en, GPIO_LOW);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+static int ap_wake_bp(struct bp_private_data *bp, int wake)\r
+{\r
+       int result = 0;\r
+       \r
+       gpio_direction_output(bp->ops->ap_wakeup_bp, wake);  \r
+       \r
+       return result;\r
+\r
+}\r
+\r
+static void  ap_wake_bp_work(struct work_struct *work)\r
+{\r
+       struct delayed_work *wakeup_work = container_of(work, struct delayed_work, work);\r
+       struct bp_private_data *bp = container_of(wakeup_work, struct bp_private_data, wakeup_work);\r
+\r
+       if(bp->suspend_status)\r
+       {\r
+               if(bp->ops->ap_wake_bp)\r
+               bp->ops->ap_wake_bp(bp, 0);\r
+       }\r
+       else    \r
+       {\r
+               if(bp->ops->ap_wake_bp)\r
+               bp->ops->ap_wake_bp(bp, 1);\r
+       }\r
+}\r
+\r
+\r
+static int bp_init(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
+       msleep(1000);\r
+       if(bp->ops->active)\r
+               bp->ops->active(bp, 1);\r
+\r
+       INIT_DELAYED_WORK(&bp->wakeup_work, ap_wake_bp_work);\r
+       return result;\r
+}\r
+\r
+static int bp_reset(struct bp_private_data *bp)\r
+{\r
+       gpio_direction_output(bp->ops->bp_power, GPIO_HIGH);\r
+       msleep(100);\r
+       gpio_direction_output(bp->ops->bp_power, GPIO_LOW);\r
+\r
+       return 0;\r
+}\r
+\r
+static int bp_wake_ap(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       \r
+       if(bp->suspend_status)\r
+       {\r
+               bp->suspend_status = 0;\r
+               wake_lock_timeout(&bp->bp_wakelock, 10 * HZ);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int bp_shutdown(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       \r
+       if(bp->ops->active)\r
+               bp->ops->active(bp, 0);\r
+       \r
+       cancel_delayed_work_sync(&bp->wakeup_work);     \r
+               \r
+       return result;\r
+}\r
+\r
+\r
+static int read_status(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+static int write_status(struct bp_private_data *bp)\r
+{\r
+       int result = 0;\r
+\r
+       if (bp->status == BP_ON)\r
+       {\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_HIGH);\r
+               gpio_direction_output(bp->ops->bp_uart_en,GPIO_LOW);\r
+       }\r
+       else if(bp->status == BP_OFF)\r
+       {\r
+               gpio_direction_output(bp->ops->bp_usb_en, GPIO_LOW);\r
+               gpio_direction_output(bp->ops->bp_uart_en,GPIO_HIGH);\r
+       }\r
+       else\r
+       {\r
+               printk("%s, invalid parameter \n", __FUNCTION__);\r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+static int bp_suspend(struct bp_private_data *bp)\r
+{      \r
+       int result = 0;\r
+       \r
+       if(!bp->suspend_status)\r
+       {\r
+               bp->suspend_status = 1; \r
+       }\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+\r
+\r
+static int bp_resume(struct bp_private_data *bp)\r
+{\r
+       if(bp->suspend_status)\r
+       {\r
+               bp->suspend_status = 0; \r
+               gpio_set_value(bp->ops->ap_wakeup_bp, GPIO_LOW);        \r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+struct bp_operate bp_mu509_ops = {\r
+       .name                   = "mu509",\r
+       .bp_id                  = BP_ID_MU509,\r
+       .bp_bus                 = BP_BUS_TYPE_USB_UART,         \r
+       .bp_pid                 = 0,    \r
+       .bp_vid                 = 0,    \r
+       .bp_power               = RK30_PIN6_PB2,        // 3g_power\r
+       .bp_en                  = RK30_PIN2_PB6,        // 3g_en\r
+       .bp_reset               = RK30_PIN2_PC1,\r
+       .ap_ready               = BP_UNKNOW_DATA,       //\r
+       .bp_ready               = BP_UNKNOW_DATA,\r
+       .ap_wakeup_bp           = RK30_PIN2_PB7,\r
+       .bp_wakeup_ap           = RK30_PIN6_PA1,        //\r
+       .bp_uart_en             = BP_UNKNOW_DATA,       //EINT9\r
+       .bp_usb_en              = BP_UNKNOW_DATA,       //W_disable\r
+       .trig                   = IRQF_TRIGGER_FALLING,\r
+\r
+       .active                 = bp_active,\r
+       .init                   = bp_init,\r
+       .reset                  = bp_reset,\r
+       .ap_wake_bp             = ap_wake_bp,\r
+       .bp_wake_ap             = bp_wake_ap,\r
+       .shutdown               = bp_shutdown,\r
+       .read_status            = read_status,\r
+       .write_status           = write_status,\r
+       .suspend                = bp_suspend,\r
+       .resume                 = bp_resume,\r
+       .misc_name              = "mu509",\r
+       .private_miscdev        = NULL,\r
+};\r
+\r
+/****************operate according to bp chip:end************/\r
+\r
+//function name should not be changed\r
+static struct bp_operate *bp_get_ops(void)\r
+{\r
+       return &bp_mu509_ops;\r
+}\r
+\r
+static int __init bp_mu509_init(void)\r
+{\r
+       struct bp_operate *ops = bp_get_ops();\r
+       int result = 0;\r
+       result = bp_register_slave(NULL, NULL, bp_get_ops);\r
+       if(result)\r
+       {       \r
+               return result;\r
+       }\r
+       \r
+       if(ops->private_miscdev)\r
+       {\r
+               result = misc_register(ops->private_miscdev);\r
+               if (result < 0) {\r
+                       printk("%s:misc_register err\n",__func__);\r
+                       return result;\r
+               }\r
+       }\r
+       \r
+       DBG("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit bp_mu509_exit(void)\r
+{\r
+       //struct bp_operate *ops = bp_get_ops();\r
+       bp_unregister_slave(NULL, NULL, bp_get_ops);\r
+}\r
+\r
+\r
+subsys_initcall(bp_mu509_init);\r
+module_exit(bp_mu509_exit);\r
+\r
diff --git a/include/linux/bp-auto.h b/include/linux/bp-auto.h
new file mode 100644 (file)
index 0000000..a2b0a89
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef _BP_AUTO_H\r
+#define _BP_AUTO_H\r
+#include <linux/miscdevice.h>\r
+#include <linux/wakelock.h>\r
+\r
+struct bp_private_data;\r
+\r
+#define BP_UNKNOW_DATA -1\r
+#define BP_OFF         0\r
+#define BP_ON          1\r
+#define BP_SUSPEND     2\r
+#define BP_WAKE                3\r
+\r
+#define BP_IOCTL_BASE 'm'\r
+\r
+#define BP_IOCTL_RESET                 _IOW(BP_IOCTL_BASE, 0x00, int)\r
+#define BP_IOCTL_POWON                 _IOW(BP_IOCTL_BASE, 0x01, int)\r
+#define BP_IOCTL_POWOFF        _IOW(BP_IOCTL_BASE, 0x02, int)\r
+#define BP_IOCTL_WRITE_STATUS  _IOW(BP_IOCTL_BASE, 0x03, int)\r
+#define BP_IOCTL_GET_STATUS    _IOR(BP_IOCTL_BASE, 0x04, int)\r
+#define BP_IOCTL_SET_PVID      _IOW(BP_IOCTL_BASE, 0x05, int)\r
+#define BP_IOCTL_GET_BPID      _IOR(BP_IOCTL_BASE, 0x06, int)\r
+\r
+enum bp_id{\r
+       BP_ID_INVALID = 0,\r
+               \r
+       BP_ID_MT6229,\r
+       BP_ID_MU509,\r
+       BP_ID_MI700,\r
+       BP_ID_MW100,\r
+       BP_ID_TD8801,\r
+       \r
+       BP_ID_NUM,\r
+};\r
+\r
+\r
+\r
+enum bp_bus_type{\r
+       BP_BUS_TYPE_INVALID = 0,\r
+               \r
+       BP_BUS_TYPE_UART,\r
+       BP_BUS_TYPE_SPI,\r
+       BP_BUS_TYPE_USB,\r
+       BP_BUS_TYPE_SDIO,\r
+       BP_BUS_TYPE_USB_UART,\r
+       BP_BUS_TYPE_SPI_UART,\r
+       BP_BUS_TYPE_SDIO_UART,\r
+       \r
+       BP_BUS_TYPE_NUM_ID,\r
+};\r
+\r
+struct bp_platform_data {      \r
+       int board_id;\r
+       int bp_id;\r
+       int (*init_platform_hw)(void);          \r
+       int (*exit_platform_hw)(void);  \r
+\r
+       int bp_power;\r
+       int bp_en;\r
+       int bp_reset;\r
+       int ap_ready;\r
+       int bp_ready;\r
+       int ap_wakeup_bp;\r
+       int bp_wakeup_ap;       \r
+       int bp_usb_en;\r
+       int bp_uart_en;\r
+       \r
+       int gpio_valid;\r
+};\r
+\r
+\r
+struct bp_operate {\r
+       char *name;\r
+       int bp_id;\r
+       int bp_bus;\r
+       \r
+       int bp_pid;     \r
+       int bp_vid;\r
+       int bp_power;\r
+       int bp_en;\r
+       int bp_reset;\r
+       int ap_ready;\r
+       int bp_ready;\r
+       int ap_wakeup_bp;\r
+       int bp_wakeup_ap;       \r
+       int bp_usb_en;\r
+       int bp_uart_en;\r
+       int trig;\r
+       \r
+       int (*active)(struct bp_private_data *bp, int enable);\r
+       int (*init)(struct bp_private_data *bp);\r
+       int (*reset)(struct bp_private_data *bp);\r
+       int (*ap_wake_bp)(struct bp_private_data *bp, int wake);\r
+       int (*bp_wake_ap)(struct bp_private_data *bp);\r
+       int (*shutdown)(struct bp_private_data *bp);\r
+       int (*read_status)(struct bp_private_data *bp);\r
+       int (*write_status)(struct bp_private_data *bp);\r
+       int (*suspend)(struct bp_private_data *bp);\r
+       int (*resume)(struct bp_private_data *bp);      \r
+       \r
+       char *misc_name;\r
+       struct miscdevice *private_miscdev;\r
+       \r
+};\r
+\r
+\r
+struct bp_private_data {       \r
+       struct device *dev;\r
+       int status;\r
+       int suspend_status;\r
+       struct wake_lock bp_wakelock;\r
+       struct delayed_work wakeup_work;        /*report second event*/\r
+       struct bp_platform_data *pdata;\r
+       struct bp_operate *ops; \r
+       struct file_operations fops;\r
+       struct miscdevice miscdev;\r
+       struct file_operations id_fops;\r
+       struct miscdevice id_miscdev;\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+       struct  early_suspend early_suspend;\r
+#endif\r
+};\r
+\r
+extern int bp_register_slave(struct bp_private_data *bp,\r
+                       struct bp_platform_data *slave_pdata,\r
+                       struct bp_operate *(*get_bp_ops)(void));\r
+\r
+\r
+extern int bp_unregister_slave(struct bp_private_data *bp,\r
+                       struct bp_platform_data *slave_pdata,\r
+                       struct bp_operate *(*get_bp_ops)(void));\r
+\r
+\r
+#endif\r
+\r