From ba7b696b1a7f8c72f94f40bca364df5159772a97 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=99=88=E6=99=BA?= Date: Mon, 20 Dec 2010 21:45:12 +0800 Subject: [PATCH] BT: add bluetooth bcm4329 driver --- arch/arm/configs/rk29_sdk_defconfig | 24 +- arch/arm/mach-rk29/Makefile | 2 +- arch/arm/mach-rk29/board-rk29sdk-rfkill.c | 292 ++++++++++++++++++++++ arch/arm/mach-rk29/board-rk29sdk.c | 20 ++ drivers/serial/rk29_serial.c | 49 +++- net/bluetooth/rfcomm/core.c | 8 +- 6 files changed, 366 insertions(+), 29 deletions(-) mode change 100644 => 100755 arch/arm/mach-rk29/Makefile create mode 100755 arch/arm/mach-rk29/board-rk29sdk-rfkill.c mode change 100644 => 100755 drivers/serial/rk29_serial.c mode change 100644 => 100755 net/bluetooth/rfcomm/core.c diff --git a/arch/arm/configs/rk29_sdk_defconfig b/arch/arm/configs/rk29_sdk_defconfig index 540c54a40fd4..839a760cbc0a 100755 --- a/arch/arm/configs/rk29_sdk_defconfig +++ b/arch/arm/configs/rk29_sdk_defconfig @@ -197,7 +197,7 @@ CONFIG_MMU=y CONFIG_ARCH_RK29=y CONFIG_WIFI_CONTROL_FUNC=y CONFIG_MACH_RK29SDK=y -CONFIG_RK29_MEM_SIZE_M=512 +CONFIG_MACH_RK29SDK_MEM_SIZE_M=512 # # RK29 VPU (Video Processing Unit) support @@ -1652,27 +1652,7 @@ CONFIG_CRAMFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFS_V4_1=y -CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_NFS_ACL_SUPPORT=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -CONFIG_SUNRPC_GSS=y -CONFIG_RPCSEC_GSS_KRB5=y -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set # # Partition Types diff --git a/arch/arm/mach-rk29/Makefile b/arch/arm/mach-rk29/Makefile old mode 100644 new mode 100755 index 1ed0be1ef425..4ebbd8fca798 --- a/arch/arm/mach-rk29/Makefile +++ b/arch/arm/mach-rk29/Makefile @@ -1,4 +1,4 @@ obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o gpio.o obj-$(CONFIG_RK29_VPU) += vpu.o vpu_mem.o -obj-$(CONFIG_MACH_RK29SDK) += board-rk29sdk.o board-rk29sdk-key.o +obj-$(CONFIG_MACH_RK29SDK) += board-rk29sdk.o board-rk29sdk-key.o board-rk29sdk-rfkill.o obj-$(CONFIG_MACH_RK29WINACCORD) += board-rk29-winaccord.o board-rk29sdk-key.o diff --git a/arch/arm/mach-rk29/board-rk29sdk-rfkill.c b/arch/arm/mach-rk29/board-rk29sdk-rfkill.c new file mode 100755 index 000000000000..604ea9f77551 --- /dev/null +++ b/arch/arm/mach-rk29/board-rk29sdk-rfkill.c @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2010 ROCKCHIP, Inc. + * Author: roger_chen + * + * This program is the bluetooth device bcm4329's driver, + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) +#endif + +#define BT_WAKE_HOST_SUPPORT 0 + +struct bt_ctrl +{ + struct rfkill *bt_rfk; +#if BT_WAKE_HOST_SUPPORT + struct timer_list tl; + bool b_HostWake; + struct wake_lock bt_wakelock; +#endif +}; + +#define BT_GPIO_POWER RK29_PIN5_PD6 +#define IOMUX_BT_GPIO_POWER rk29_mux_api_set(GPIO5D6_SDMMC1PWREN_NAME, GPIO5H_GPIO5D6); +#define BT_GPIO_RESET RK29_PIN6_PC4 +#define BT_GPIO_WAKE_UP RK29_PIN6_PC5 +#define BT_GPIO_WAKE_UP_HOST //RK2818_PIN_PA7 +#define IOMUX_BT_GPIO_WAKE_UP_HOST() //rk2818_mux_api_set(GPIOA7_FLASHCS3_SEL_NAME,0); + +#define BT_WAKE_LOCK_TIMEOUT 10 //s + +static const char bt_name[] = "bcm4329"; +extern int rk29sdk_bt_power_state; +extern int rk29sdk_wifi_power_state; + +struct bt_ctrl gBtCtrl; + +#if BT_WAKE_HOST_SUPPORT +void resetBtHostSleepTimer(void) +{ + mod_timer(&(gBtCtrl.tl),jiffies + BT_WAKE_LOCK_TIMEOUT*HZ);//ÔÙÖØÐÂÉèÖó¬Ê±Öµ¡£ +} + +void btWakeupHostLock(void) +{ + if(gBtCtrl.b_HostWake == false){ + DBG("*************************Lock\n"); + wake_lock(&(gBtCtrl.bt_wakelock)); + gBtCtrl.b_HostWake = true; + } +} + +void btWakeupHostUnlock(void) +{ + if(gBtCtrl.b_HostWake == true){ + DBG("*************************UnLock\n"); + wake_unlock(&(gBtCtrl.bt_wakelock)); //ÈÃϵͳ˯Ãß + gBtCtrl.b_HostWake = false; + } +} + +static void timer_hostSleep(unsigned long arg) +{ + DBG("%s---b_HostWake=%d\n",__FUNCTION__,gBtCtrl.b_HostWake); + btWakeupHostUnlock(); +} + + +#ifdef CONFIG_PM +static int bcm4329_rfkill_suspend(struct platform_device *pdev, pm_message_t state) +{ + DBG("%s\n",__FUNCTION__); + return 0; +} + +static int bcm4329_rfkill_resume(struct platform_device *pdev) +{ + DBG("%s\n",__FUNCTION__); + btWakeupHostLock(); + resetBtHostSleepTimer(); + return 0; +} +#else +#define bcm4329_rfkill_suspend NULL +#define bcm4329_rfkill_resume NULL +#endif + +static irqreturn_t bcm4329_wake_host_irq(int irq, void *dev) +{ + btWakeupHostLock(); + resetBtHostSleepTimer(); + return IRQ_HANDLED; +} +#endif + +#ifdef CONFIG_BT_HCIBCM4325 +int bcm4325_sleep(int bSleep) +{ +// printk("*************bt enter sleep***************\n"); + if (bSleep) + gpio_set_value(BT_GPIO_WAKE_UP, GPIO_LOW); //low represent bt device may enter sleep + else + gpio_set_value(BT_GPIO_WAKE_UP, GPIO_HIGH); //high represent bt device must be awake + + //printk("sleep=%d\n",bSleep); +} +#endif + +static int bcm4329_set_block(void *data, bool blocked) +{ + DBG("%s---blocked :%d\n", __FUNCTION__, blocked); + + IOMUX_BT_GPIO_POWER; + + if (false == blocked) { + gpio_set_value(BT_GPIO_POWER, GPIO_HIGH); /* bt power on */ + gpio_set_value(BT_GPIO_RESET, GPIO_HIGH); /* bt reset deactive*/ + mdelay(20); + +#if BT_WAKE_HOST_SUPPORT + btWakeupHostLock(); +#endif + pr_info("bt turn on power\n"); + } + else { +#if BT_WAKE_HOST_SUPPORT + btWakeupHostUnlock(); +#endif + if (!rk29sdk_wifi_power_state) { + gpio_set_value(BT_GPIO_POWER, GPIO_LOW); /* bt power off */ + mdelay(20); + pr_info("bt shut off power\n"); + }else { + pr_info("bt shouldn't shut off power, wifi is using it!\n"); + } + + gpio_set_value(BT_GPIO_RESET, GPIO_LOW); /* bt reset active*/ + mdelay(20); + } + + rk29sdk_bt_power_state = !blocked; + return 0; +} + + +static const struct rfkill_ops bcm4329_rfk_ops = { + .set_block = bcm4329_set_block, +}; + +static int __init bcm4329_rfkill_probe(struct platform_device *pdev) +{ + int rc = 0; + bool default_state = true; + + DBG("Enter::%s,line=%d\n",__FUNCTION__,__LINE__); + + /* default to bluetooth off */ + bcm4329_set_block(NULL, default_state); /* blocked -> bt off */ + + gBtCtrl.bt_rfk = rfkill_alloc(bt_name, + NULL, + RFKILL_TYPE_BLUETOOTH, + &bcm4329_rfk_ops, + NULL); + + if (!gBtCtrl.bt_rfk) + { + printk("fail to rfkill_allocate************\n"); + return -ENOMEM; + } + + rfkill_set_states(gBtCtrl.bt_rfk, default_state, false); + + rc = rfkill_register(gBtCtrl.bt_rfk); + if (rc) + { + printk("failed to rfkill_register,rc=0x%x\n",rc); + rfkill_destroy(gBtCtrl.bt_rfk); + } + + gpio_request(BT_GPIO_POWER, NULL); + gpio_request(BT_GPIO_RESET, NULL); + gpio_request(BT_GPIO_WAKE_UP, NULL); + +#if BT_WAKE_HOST_SUPPORT + init_timer(&(gBtCtrl.tl)); + gBtCtrl.tl.expires = jiffies + BT_WAKE_LOCK_TIMEOUT*HZ; + gBtCtrl.tl.function = timer_hostSleep; + add_timer(&(gBtCtrl.tl)); + gBtCtrl.b_HostWake = false; + + wake_lock_init(&(gBtCtrl.bt_wakelock), WAKE_LOCK_SUSPEND, "bt_wake"); + + rc = gpio_request(BT_GPIO_WAKE_UP_HOST, "bt_wake"); + if (rc) { + printk("%s:failed to request RAHO_BT_WAKE_UP_HOST\n",__FUNCTION__); + } + + IOMUX_BT_GPIO_WAKE_UP_HOST(); + gpio_pull_updown(BT_GPIO_WAKE_UP_HOST,GPIOPullUp); + rc = request_irq(gpio_to_irq(BT_GPIO_WAKE_UP_HOST),bcm4329_wake_host_irq,IRQF_TRIGGER_FALLING,NULL,NULL); + if(rc) + { + printk("%s:failed to request RAHO_BT_WAKE_UP_HOST irq\n",__FUNCTION__); + gpio_free(BT_GPIO_WAKE_UP_HOST); + } + enable_irq_wake(gpio_to_irq(BT_GPIO_WAKE_UP_HOST)); // so RAHO_BT_WAKE_UP_HOST can wake up system + + printk(KERN_INFO "bcm4329 module has been initialized,rc=0x%x\n",rc); + #endif + + return rc; + + +} + + +static int __devexit bcm4329_rfkill_remove(struct platform_device *pdev) +{ + if (gBtCtrl.bt_rfk) + rfkill_unregister(gBtCtrl.bt_rfk); + gBtCtrl.bt_rfk = NULL; +#if BT_WAKE_HOST_SUPPORT + del_timer(&(gBtCtrl.tl));//ɾµô¶¨Ê±Æ÷ + btWakeupHostUnlock(); + wake_lock_destroy(&(gBtCtrl.bt_wakelock)); +#endif + platform_set_drvdata(pdev, NULL); + + DBG("Enter::%s,line=%d\n",__FUNCTION__,__LINE__); + return 0; +} + +static struct platform_driver bcm4329_rfkill_driver = { + .probe = bcm4329_rfkill_probe, + .remove = __devexit_p(bcm4329_rfkill_remove), + .driver = { + .name = "rk29sdk_rfkill", + .owner = THIS_MODULE, + }, +#if BT_WAKE_HOST_SUPPORT + .suspend = bcm4329_rfkill_suspend, + .resume = bcm4329_rfkill_resume, +#endif +}; + +/* + * Module initialization + */ +static int __init bcm4329_mod_init(void) +{ + int ret; + DBG("Enter::%s,line=%d\n",__FUNCTION__,__LINE__); + ret = platform_driver_register(&bcm4329_rfkill_driver); + printk("ret=0x%x\n", ret); + return ret; +} + +static void __exit bcm4329_mod_exit(void) +{ + platform_driver_unregister(&bcm4329_rfkill_driver); +} + +module_init(bcm4329_mod_init); +module_exit(bcm4329_mod_exit); +MODULE_DESCRIPTION("bcm4329 Bluetooth driver"); +MODULE_AUTHOR("roger_chen cz@rock-chips.com"); +MODULE_LICENSE("GPL"); + diff --git a/arch/arm/mach-rk29/board-rk29sdk.c b/arch/arm/mach-rk29/board-rk29sdk.c index 50cb23ac20c5..75d110c50949 100755 --- a/arch/arm/mach-rk29/board-rk29sdk.c +++ b/arch/arm/mach-rk29/board-rk29sdk.c @@ -1041,6 +1041,14 @@ static struct platform_device rk29sdk_wifi_device = { }; #endif + +/* bluetooth rfkill device */ +static struct platform_device rk29sdk_rfkill = { + .name = "rk29sdk_rfkill", + .id = -1, +}; + + #ifdef CONFIG_VIVANTE static struct resource resources_gpu[] = { [0] = { @@ -1141,6 +1149,13 @@ static struct platform_device *devices[] __initdata = { #ifdef CONFIG_UART1_RK29 &rk29_device_uart1, #endif +#ifdef CONFIG_UART0_RK29 + &rk29_device_uart0, +#endif +#ifdef CONFIG_UART2_RK29 + &rk29_device_uart2, +#endif + #ifdef CONFIG_SPIM0_RK29 &rk29xx_device_spi0m, #endif @@ -1187,6 +1202,11 @@ static struct platform_device *devices[] __initdata = { #ifdef CONFIG_WIFI_CONTROL_FUNC &rk29sdk_wifi_device, #endif + +#ifdef CONFIG_BT + &rk29sdk_rfkill, +#endif + #ifdef CONFIG_MTD_NAND_RK29 &rk29_device_nand, #endif diff --git a/drivers/serial/rk29_serial.c b/drivers/serial/rk29_serial.c old mode 100644 new mode 100755 index 72bbe3647768..bd1fe6b515c7 --- a/drivers/serial/rk29_serial.c +++ b/drivers/serial/rk29_serial.c @@ -36,6 +36,12 @@ #include #include "rk2818_serial.h" +#define DBG_PORT 0 +#if 0 +#define DBG printk +#else +#define DBG +#endif /* * We wrap our port structure around the generic uart_port. */ @@ -174,6 +180,11 @@ static void rk29_serial_stop_tx(struct uart_port *port) static void rk29_serial_start_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; + + if(DBG_PORT == port->line) { + DBG("TX:"); + } + while(!(uart_circ_empty(xmit))) { while (!(rk29_uart_read(port,UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL)){ @@ -181,6 +192,11 @@ static void rk29_serial_start_tx(struct uart_port *port) return; } rk29_uart_write(port,xmit->buf[xmit->tail],UART_THR); + + if(DBG_PORT == port->line) { + DBG("0x%x, ", xmit->buf[xmit->tail]); + } + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; } @@ -188,6 +204,10 @@ static void rk29_serial_start_tx(struct uart_port *port) rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); + + if(DBG_PORT == port->line) { + DBG("\n"); + } } /* @@ -221,6 +241,11 @@ static void rk29_serial_break_ctl(struct uart_port *port, int break_state) static void rk29_rx_chars(struct uart_port *port) { unsigned int ch, flag; + + if(DBG_PORT == port->line) { + DBG("RX:"); + } + while((rk29_uart_read(port,UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY) { u32 lsr = rk29_uart_read(port, UART_LSR); @@ -237,9 +262,16 @@ static void rk29_rx_chars(struct uart_port *port) continue; } uart_insert_char(port, 0, 0, ch, flag); + + if(DBG_PORT == port->line) { + DBG("0x%x, ", ch); + } } tty_flip_buffer_push(port->state->port.tty); - + + if(DBG_PORT == port->line) { + DBG("\n"); + } } /* @@ -277,7 +309,20 @@ static int rk29_serial_startup(struct uart_port *port) struct rk29_port *rk29_port = UART_TO_RK29(port); struct tty_struct *tty = port->state->port.tty; int retval; - + + if(2 == port->line) { + rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT); + rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN); + rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_UART2_RTS_N); + rk29_mux_api_set(GPIO2A6_UART2CTSN_NAME, GPIO2L_UART2_CTS_N); + } + else if(0 == port->line) { + rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT); + rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN); + rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N); + rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N); + } + retval = request_irq(port->irq,rk29_uart_interrupt,IRQF_SHARED, tty ? tty->name : "rk29_serial",port); if(retval) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c old mode 100644 new mode 100755 index c2e4333282d6..b3dd3f09ff26 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -243,7 +243,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d) return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level, auth_type); } - +#if 0 //cz@rock-chips.com static void rfcomm_session_timeout(unsigned long arg) { struct rfcomm_session *s = (void *) arg; @@ -269,7 +269,7 @@ static void rfcomm_session_clear_timer(struct rfcomm_session *s) if (timer_pending(&s->timer) && del_timer(&s->timer)) rfcomm_session_put(s); } - +#endif /* ---- RFCOMM DLCs ---- */ static void rfcomm_dlc_timeout(unsigned long arg) { @@ -1891,14 +1891,14 @@ static inline void rfcomm_process_sessions(void) list_for_each_safe(p, n, &session_list) { struct rfcomm_session *s; s = list_entry(p, struct rfcomm_session, list); - +#if 0 //cz@rock-chips.com if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) { s->state = BT_DISCONN; rfcomm_send_disc(s, 0); rfcomm_session_put(s); continue; } - +#endif if (s->state == BT_LISTEN) { rfcomm_accept_connection(s); continue; -- 2.34.1