From 13ae592853501640640c5160b491ffddd1fafb86 Mon Sep 17 00:00:00 2001 From: wdc Date: Tue, 23 Apr 2013 18:13:44 +0800 Subject: [PATCH] rda5876BT: add tcc_bt_drv for android4.2 --- .../arm/configs/rk2928_phonepad_760_defconfig | 1 + .../configs/rk2928_phonepad_760_hd_defconfig | 1 + drivers/misc/Kconfig | 16 +- drivers/misc/Makefile | 2 +- drivers/misc/tcc_bt_dev.c | 275 ++++++++++++++++++ 5 files changed, 283 insertions(+), 12 deletions(-) mode change 100644 => 100755 arch/arm/configs/rk2928_phonepad_760_hd_defconfig mode change 100755 => 100644 drivers/misc/Makefile create mode 100755 drivers/misc/tcc_bt_dev.c diff --git a/arch/arm/configs/rk2928_phonepad_760_defconfig b/arch/arm/configs/rk2928_phonepad_760_defconfig index 5303698cf7f3..3b88bb7b5bc7 100755 --- a/arch/arm/configs/rk2928_phonepad_760_defconfig +++ b/arch/arm/configs/rk2928_phonepad_760_defconfig @@ -194,6 +194,7 @@ CONFIG_MISC_DEVICES=y CONFIG_UID_STAT=y CONFIG_APANIC=y CONFIG_MODEM_SOUND=y +CONFIG_TCC_BT_DEV=y CONFIG_BP_AUTO=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y diff --git a/arch/arm/configs/rk2928_phonepad_760_hd_defconfig b/arch/arm/configs/rk2928_phonepad_760_hd_defconfig old mode 100644 new mode 100755 index 5d02763c9dfa..d0d7aa0aa828 --- a/arch/arm/configs/rk2928_phonepad_760_hd_defconfig +++ b/arch/arm/configs/rk2928_phonepad_760_hd_defconfig @@ -194,6 +194,7 @@ CONFIG_MISC_DEVICES=y CONFIG_UID_STAT=y CONFIG_APANIC=y CONFIG_MODEM_SOUND=y +CONFIG_TCC_BT_DEV=y CONFIG_BP_AUTO=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 683616d3abfb..2e2f2472f813 100755 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -399,15 +399,6 @@ config SENSORS_AK8975 If you say yes here you get support for Asahi Kasei's orientation sensor AK8975. -config SENSORS_AK8963 - tristate "AK8963 compass support" - default n - depends on I2C - help - If you say yes here you get support for Asahi Kasei's - orientation sensor AK8963. - - config EP93XX_PWM tristate "EP93xx PWM support" depends on ARCH_EP93XX @@ -552,7 +543,11 @@ config MODEM_SOUND bool "modem sound control driver" default n - +config TCC_BT_DEV + tristate "TCC Bluetooth dev Control power" + default n + help + If you say Y here, you can contorl the power of the BT H/W Module source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" @@ -566,6 +561,5 @@ 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 diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile old mode 100755 new mode 100644 index 22cca16c75f8..79aaca45e2b5 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -50,7 +50,6 @@ obj-y += carma/ obj-$(CONFIG_WL127X_RFKILL) += wl127x-rfkill.o obj-$(CONFIG_APANIC) += apanic.o obj-$(CONFIG_SENSORS_AK8975) += akm8975.o -obj-$(CONFIG_SENSORS_AK8963) += akm8963.o obj-$(CONFIG_MTK23D) += mtk23d.o obj-$(CONFIG_FM580X) += fm580x.o obj-$(CONFIG_RK29_SUPPORT_MODEM) += rk29_modem/ @@ -62,3 +61,4 @@ obj-$(CONFIG_TDSC8800) += tdsc8800.o obj-$(CONFIG_RK29_SC8800) += sc8800.o obj-y += rk2928_callpad_misc/ obj-$(CONFIG_MODEM_SOUND) += modem_sound.o +obj-$(CONFIG_TCC_BT_DEV) += tcc_bt_dev.o diff --git a/drivers/misc/tcc_bt_dev.c b/drivers/misc/tcc_bt_dev.c new file mode 100755 index 000000000000..7f9d03c0b6f9 --- /dev/null +++ b/drivers/misc/tcc_bt_dev.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2010-2011 RDA Micro + * This file belong to RDA micro + * File: drivers/char/tcc_bt_dev.c + */ + +#include +#include +#include +#include +#include +#include + +//#include +#include +#include + +//#include +//#include + +#include +#include +#include + +#include +#include +#include +#include + +#ifndef ON +#define ON 1 +#endif + +#ifndef OFF +#define OFF 0 +#endif + +#define LDO_ON_PIN RK2928_PIN3_PC0 +#define RDA_BT_HOST_WAKE_PIN RK2928_PIN0_PC5 + +#define BT_DEV_ON 1 +#define BT_DEV_OFF 0 + +#define BT_DEV_MAJOR_NUM 234 +#define BT_DEV_MINOR_NUM 0 + +//#define IOCTL_BT_DEV_POWER _IO(BT_DEV_MAJOR_NUM, 100) +//#define IOCTL_BT_DEV_SPECIFIC _IO(BT_DEV_MAJOR_NUM, 101) +//#define IOCTL_BT_DEV_IS_POWER _IO(BT_DEV_MAJOR_NUM, 102) + + +#define IOCTL_BT_DEV_POWER _IO(BT_DEV_MAJOR_NUM, 100) +#define IOCTL_BT_DEV_CTRL _IO(BT_DEV_MAJOR_NUM, 101) +#define IOCTL_BT_SET_EINT _IO(BT_DEV_MAJOR_NUM, 102) +#define IOCTL_BT_DEV_SPECIFIC _IO(BT_DEV_MAJOR_NUM, 103) + + +static int bt_is_power = 0; +static int rda_bt_irq = 0; +static int irq_mask = 0; +extern void export_bt_hci_wakeup_chip(void); + +#define DEV_NAME "tcc_bt_dev" +static struct class *bt_dev_class; + +typedef struct { + int module; // 0x12:CSR, 0x34:Broadcom + int TMP1; + int TMP2; +} tcc_bt_info_t; + +static int tcc_bt_dev_open(struct inode *inode, struct file *file) +{ + printk("[## BT ##] tcc_bt_dev_open\n"); + return 0; +} + +static int tcc_bt_dev_release(struct inode *inode, struct file *file) +{ + printk("[## BT ##] tcc_bt_dev_release\n"); + return 0; +} + +int tcc_bt_power_control(int on_off) +{ +// volatile PGPIO pGPIO = (volatile PGPIO)tcc_p2v(HwGPIO_BASE); + + printk("[## BT ##] tcc_bt_power_control input[%d]\n", on_off); + + if(on_off == BT_DEV_ON) + { + gpio_direction_output(LDO_ON_PIN, GPIO_HIGH); + bt_is_power = on_off; + msleep(500); + } + else if(on_off == BT_DEV_OFF) + { + gpio_direction_output(LDO_ON_PIN, GPIO_LOW); + bt_is_power = BT_DEV_OFF; + msleep(500); + } + else + { + printk("[## BT_ERR ##] input_error On[%d] Off[%d]\n", BT_DEV_ON, BT_DEV_OFF); + } + + return 0; +} + + +static int tcc_bt_get_info(tcc_bt_info_t* arg) +{ + tcc_bt_info_t *info_t; + int module_t; + + info_t = (tcc_bt_info_t *)arg; + copy_from_user(info_t, (tcc_bt_info_t *)arg, sizeof(tcc_bt_info_t)); + + module_t = 0x56; + + printk("[## BT ##] module[0x%x]\n", module_t); + + info_t->module = module_t; + + copy_to_user((tcc_bt_info_t *)arg, info_t, sizeof(tcc_bt_info_t)); + + return 0; +} + +static long tcc_bt_dev_ioctl(struct file *file, unsigned int cmd,unsigned long arg) +{ + void __user *argp = (void __user *)arg; + char msg[14]; + int ret = -1; + char rate; + //printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d] arg[%d]\n", cmd, arg); + switch(cmd) + { + case IOCTL_BT_DEV_POWER: + if (copy_from_user(&rate, argp, sizeof(rate))) + return -EFAULT; + printk("[## BT ##] IOCTL_BT_DEV_POWER cmd[%d] parm1[%d]\n", cmd, rate); + tcc_bt_power_control(rate); + // GPIO Control + break; + + case IOCTL_BT_DEV_SPECIFIC: + printk("[## BT ##] IOCTL_BT_DEV_SPECIFIC cmd[%d]\n", cmd); + tcc_bt_get_info((tcc_bt_info_t*)arg); + break; + + //case IOCTL_BT_DEV_IS_POWER: + //if (copy_to_user(argp, &bt_is_power, sizeof(bt_is_power))) + //return -EFAULT; + case IOCTL_BT_SET_EINT: + printk("[## BT ##] IOCTL_BT_SET_EINT cmd[%d]\n", cmd); + if (irq_mask) + { + irq_mask = 0; + enable_irq(rda_bt_irq); + } + break; + default : + printk("[## BT ##] tcc_bt_dev_ioctl cmd[%d]\n", cmd); + break; + } + + return 0; +} + + +struct file_operations tcc_bt_dev_ops = { + .owner = THIS_MODULE, + .unlocked_ioctl = tcc_bt_dev_ioctl, + .open = tcc_bt_dev_open, + .release = tcc_bt_dev_release, +}; + +struct wake_lock rda_bt_wakelock; +static irqreturn_t rda_5876_host_wake_irq(int irq, void *dev) +{ + printk("rda_5876_host_wake_irq\n"); + //export_bt_hci_wakeup_chip(); + wake_lock_timeout(&rda_bt_wakelock, 3 * HZ); + disable_irq(rda_bt_irq); + irq_mask = 1; + return IRQ_HANDLED; +} + +int init_module(void) +{ + int ret; + + wake_lock_init(&rda_bt_wakelock, WAKE_LOCK_SUSPEND, "rda_bt_wake"); + ret=gpio_request(LDO_ON_PIN, "ldoonpin"); + if(ret < 0) { + printk("%s:fail to request gpio %d\n",__func__,LDO_ON_PIN); + return ret; + } + gpio_set_value(LDO_ON_PIN, GPIO_LOW);//GPIO_LOW + gpio_direction_output(LDO_ON_PIN, GPIO_LOW);//GPIO_LOW + + if(rda_bt_irq == 0){ + if(gpio_request(RDA_BT_HOST_WAKE_PIN, "bt_wake") != 0){ + printk("RDA_BT_HOST_WAKE_PIN request fail!\n"); + return -EIO; + } + gpio_direction_input(RDA_BT_HOST_WAKE_PIN); + + rda_bt_irq = gpio_to_irq(RDA_BT_HOST_WAKE_PIN); + ret = request_irq(rda_bt_irq, rda_5876_host_wake_irq, IRQF_TRIGGER_RISING, "bt_host_wake",NULL); + if(ret){ + printk("bt_host_wake irq request fail\n"); + rda_bt_irq = 0; + gpio_free(RDA_BT_HOST_WAKE_PIN); + return -EIO; + } + enable_irq_wake(rda_bt_irq); //bt irq can wakeup host when host sleep + disable_irq(rda_bt_irq); + irq_mask = 1; + printk("request_irq bt_host_wake\n"); + } + + + printk("[## BT ##] init_module\n"); + ret = register_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME, &tcc_bt_dev_ops); + + bt_dev_class = class_create(THIS_MODULE, DEV_NAME); + device_create(bt_dev_class, NULL, MKDEV(BT_DEV_MAJOR_NUM, BT_DEV_MINOR_NUM), NULL, DEV_NAME); +#if 0 + if(machine_is_tcc8900()){ + gpio_request(TCC_GPB(25), "bt_power"); + gpio_request(TCC_GPEXT2(9), "bt_reset"); + gpio_direction_output(TCC_GPB(25), 0); // output + gpio_direction_output(TCC_GPEXT2(9), 0); + }else if(machine_is_tcc9300() || machine_is_tcc8800()) { // #elif defined (CONFIG_MACH_TCC9300) + //gpio_set_value(TCC_GPEXT1(7), 0); /* BT-ON Disable */ + gpio_request(TCC_GPEXT3(2), "bt_wake"); + gpio_request(TCC_GPEXT2(4), "bt_reset"); + gpio_direction_output(TCC_GPEXT3(2), 0); // output + gpio_direction_output(TCC_GPEXT2(4), 0); + } + else if(machine_is_m801_88()) + { + gpio_request(TCC_GPA(13), "bt_reset"); + gpio_request(TCC_GPB(22), "BT WAKE"); + gpio_direction_output(TCC_GPA(13), 0); // output + gpio_direction_output(TCC_GPB(22), 0); // output + } +#endif + if(ret < 0){ + printk("[## BT ##] [%d]fail to register the character device\n", ret); + return ret; + } + + return 0; +} + +void cleanup_module(void) +{ + printk("[## BT ##] cleanup_module\n"); + unregister_chrdev(BT_DEV_MAJOR_NUM, DEV_NAME); + wake_lock_destroy(&rda_bt_wakelock); +} + + +late_initcall(init_module); +module_exit(cleanup_module); + + +MODULE_AUTHOR("Telechips Inc. linux@telechips.com"); +MODULE_DESCRIPTION("TCC_BT_DEV"); +MODULE_LICENSE("GPL"); + + -- 2.34.1