kernel_samsung_a34x-permissive/drivers/misc/mediatek/btif/common/btif_plat.c
2024-04-28 15:49:01 +02:00

1386 lines
38 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#ifdef DFT_TAG
#undef DFT_TAG
#endif
#define DFT_TAG "MTK-BTIF"
#define NEW_TX_HANDLING_SUPPORT 1
#include "btif_pub.h"
#include "btif_priv.h"
#include "mtk_btif.h"
#define BTIF_USER_ID "btif_driver"
static spinlock_t g_clk_cg_spinlock; /*BTIF clock's spinlock */
/*----------------BTIF Module Clock and Power Control Defination--------------*/
struct _MTK_BTIF_IRQ_STR_ mtk_btif_irq = {
.name = "mtk btif irq",
.is_irq_sup = true,
.reg_flag = false,
#ifdef CONFIG_OF
.irq_flags = IRQF_TRIGGER_NONE,
#else
.irq_id = MT_BTIF_IRQ_ID,
.sens_type = IRQ_SENS_LVL,
.lvl_type = IRQ_LVL_LOW,
#endif
.p_irq_handler = NULL,
};
/*
* will call clock manager's API export by WCP to control BTIF's clock,
* but we may need to access these registers in case of
* btif clock control logic is wrong in clock manager
*/
struct _MTK_BTIF_INFO_STR_ mtk_btif_info = {
#ifndef CONFIG_OF
.base = MTK_BTIF_REG_BASE,
#endif
.p_irq = &mtk_btif_irq,
.tx_fifo_size = BTIF_TX_FIFO_SIZE,
.rx_fifo_size = BTIF_RX_FIFO_SIZE,
.tx_tri_lvl = BTIF_TX_FIFO_THRE,
.rx_tri_lvl = BTIF_RX_FIFO_THRE,
.rx_data_len = 0,
.p_tx_fifo = NULL,
};
#if !(NEW_TX_HANDLING_SUPPORT)
static bool _btif_is_tx_allow(struct _MTK_BTIF_INFO_STR_ *p_btif);
#endif
static int btif_rx_irq_handler(struct _MTK_BTIF_INFO_STR_ *p_btif_info,
unsigned char *p_buf,
const unsigned int max_len);
static int btif_tx_irq_handler(struct _MTK_BTIF_INFO_STR_ *p_btif);
/*****************************************************************************
* FUNCTION
* hal_btif_rx_ier_ctrl
* DESCRIPTION
* BTIF Rx interrupt enable/disable
* PARAMETERS
* p_base [IN] BTIF module's base address
* enable [IN] control if rx interrupt enabled or not
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
static int hal_btif_rx_ier_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif, bool en);
/*****************************************************************************
* FUNCTION
* hal_btif_tx_ier_ctrl
* DESCRIPTION
* BTIF Tx interrupt enable/disable
* PARAMETERS
* p_base [IN] BTIF module's base address
* enable [IN] control if tx interrupt enabled or not
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
static int hal_btif_tx_ier_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif, bool en);
#ifndef MTK_BTIF_MARK_UNUSED_API
static int btif_sleep_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif, bool en);
/*****************************************************************************
* FUNCTION
* _btif_receive_data
* DESCRIPTION
* receive data from btif module in FIFO polling mode
* PARAMETERS
* p_base [IN] BTIF module's base address
* p_buf [IN/OUT] pointer to rx data buffer
* max_len [IN] max length of rx buffer
* RETURNS
* positive means data is available, 0 means no data available
*****************************************************************************/
static int _btif_receive_data(struct _MTK_BTIF_INFO_STR_ *p_btif,
unsigned char *p_buf, const unsigned int max_len);
static int btif_tx_thr_set(struct _MTK_BTIF_INFO_STR_ *p_btif,
unsigned int thr_count);
#endif
int btif_dump_array(const char *string, const char *p_buf, int len)
{
#define BTIF_LENGTH_PER_LINE 32
unsigned int idx = 0;
unsigned char str[BTIF_LENGTH_PER_LINE * 3 + 2];
unsigned char *p_str = NULL;
pr_info("========dump %s start <length:%d>========\n", string, len);
p_str = &str[0];
for (idx = 0; idx < len; idx++, p_buf++) {
if (sprintf(p_str, "%02x ", *p_buf) < 0)
return -1;
p_str += 3;
if ((BTIF_LENGTH_PER_LINE - 1) == (idx % BTIF_LENGTH_PER_LINE)) {
*p_str++ = '\n';
*p_str = '\0';
pr_info("%s", str);
p_str = &str[0];
}
}
if (len % BTIF_LENGTH_PER_LINE) {
*p_str++ = '\n';
*p_str = '\0';
pr_info("%s", str);
}
pr_info("========dump %s end========\n", string);
return 0;
}
#if NEW_TX_HANDLING_SUPPORT
static int _btif_tx_fifo_init(struct _MTK_BTIF_INFO_STR_ *p_btif_info)
{
int i_ret = -1;
spin_lock_init(&(p_btif_info->tx_fifo_spinlock));
if (p_btif_info->p_tx_fifo == NULL) {
p_btif_info->p_tx_fifo = kzalloc(sizeof(struct kfifo),
GFP_ATOMIC);
if (p_btif_info->p_tx_fifo == NULL) {
i_ret = -ENOMEM;
BTIF_ERR_FUNC("kzalloc for p_btif->p_tx_fifo failed\n");
goto ret;
}
i_ret = kfifo_alloc(p_btif_info->p_tx_fifo,
BTIF_HAL_TX_FIFO_SIZE, GFP_ATOMIC);
if (i_ret != 0) {
BTIF_ERR_FUNC("kfifo_alloc failed, errno(%d)\n", i_ret);
i_ret = -ENOMEM;
goto ret;
}
i_ret = 0;
} else {
BTIF_WARN_FUNC
("p_tx_fifo is already init p_btif_info->p_tx_fifo(0x%p)\n",
p_btif_info->p_tx_fifo);
i_ret = 0;
}
ret:
return i_ret;
}
static int _get_btif_tx_fifo_room(struct _MTK_BTIF_INFO_STR_ *p_btif_info)
{
int i_ret = 0;
unsigned long flag = 0;
spin_lock_irqsave(&(p_btif_info->tx_fifo_spinlock), flag);
if (p_btif_info->p_tx_fifo == NULL)
i_ret = 0;
else
i_ret = kfifo_avail(p_btif_info->p_tx_fifo);
spin_unlock_irqrestore(&(p_btif_info->tx_fifo_spinlock), flag);
BTIF_DBG_FUNC("tx kfifo:0x%p, available room:%d\n",
p_btif_info->p_tx_fifo, i_ret);
return i_ret;
}
static int _btif_tx_fifo_reset(struct _MTK_BTIF_INFO_STR_ *p_btif_info)
{
int i_ret = 0;
if (p_btif_info->p_tx_fifo != NULL)
kfifo_reset(p_btif_info->p_tx_fifo);
return i_ret;
}
#endif
#ifdef CONFIG_OF
static void _btif_set_default_setting(void)
{
struct device_node *node = NULL;
unsigned int irq_info[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned int phy_base;
if (!g_btif[0].private_data) {
BTIF_INFO_FUNC("g_btif[0].private_data is NULL");
return;
}
node = ((struct device *)(g_btif[0].private_data))->of_node;
if (node) {
mtk_btif_info.p_irq->irq_id = irq_of_parse_and_map(node, 0);
/*fixme, be compitable arch 64bits*/
mtk_btif_info.base = (unsigned long)of_iomap(node, 0);
BTIF_INFO_FUNC("get btif irq(%d),register base(0x%lx)\n",
mtk_btif_info.p_irq->irq_id, mtk_btif_info.base);
} else {
BTIF_ERR_FUNC("get btif device node fail\n");
}
/* get the interrupt line behaviour */
if (of_property_read_u32_array(node, "interrupts", irq_info,
ARRAY_SIZE(irq_info))) {
BTIF_ERR_FUNC("get interrupt flag from DTS fail\n");
} else {
mtk_btif_info.p_irq->irq_flags = irq_info[2];
BTIF_INFO_FUNC("get interrupt flag(0x%x)\n",
mtk_btif_info.p_irq->irq_flags);
}
if (of_property_read_u32_index(node, "reg", 1, &phy_base))
BTIF_ERR_FUNC("get register phy base from DTS fail\n");
else
BTIF_INFO_FUNC("get register phy base(0x%x)\n",
(unsigned int)phy_base);
}
#endif
/*****************************************************************************
* FUNCTION
* hal_btif_info_get
* DESCRIPTION
* get btif's information included base address , irq related information
* PARAMETERS
* RETURNS
* BTIF's information
*****************************************************************************/
struct _MTK_BTIF_INFO_STR_ *hal_btif_info_get(void)
{
#if NEW_TX_HANDLING_SUPPORT
int i_ret = 0;
/*tx fifo and fifo lock init*/
i_ret = _btif_tx_fifo_init(&mtk_btif_info);
if (i_ret == 0)
BTIF_INFO_FUNC("_btif_tx_fifo_init succeed\n");
else
BTIF_ERR_FUNC("_btif_tx_fifo_init failed, i_ret:%d\n", i_ret);
#endif
#ifdef CONFIG_OF
_btif_set_default_setting();
#endif
spin_lock_init(&g_clk_cg_spinlock);
return &mtk_btif_info;
}
/*****************************************************************************
* FUNCTION
* hal_btif_clk_get_and_prepare
* DESCRIPTION
* get clock from device tree and prepare for enable/disable control
* PARAMETERS
* pdev device pointer
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
#if !defined(CONFIG_MTK_CLKMGR)
int hal_btif_clk_get_and_prepare(struct platform_device *pdev)
{
int i_ret = -1;
clk_btif = devm_clk_get(&pdev->dev, "btifc");
if (IS_ERR(clk_btif)) {
BTIF_ERR_FUNC("[CCF]cannot get clk_btif clock.\n");
return PTR_ERR(clk_btif);
}
BTIF_ERR_FUNC("[CCF]clk_btif=%p\n", clk_btif);
clk_btif_apdma = devm_clk_get(&pdev->dev, "apdmac");
if (IS_ERR(clk_btif_apdma)) {
BTIF_ERR_FUNC("[CCF]can't get clk_btif_apdma clock.\n");
return PTR_ERR(clk_btif_apdma);
}
BTIF_ERR_FUNC("[CCF]clk_btif_apdma=%p\n", clk_btif_apdma);
i_ret = clk_prepare(clk_btif);
if (i_ret != 0) {
BTIF_ERR_FUNC("clk_prepare failed! ret:%d\n", i_ret);
return i_ret;
}
i_ret = clk_prepare(clk_btif_apdma);
if (i_ret != 0) {
BTIF_ERR_FUNC("clk_prepare failed! ret:%d\n", i_ret);
return i_ret;
}
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_clk_unprepare
* DESCRIPTION
* unprepare btif clock and apdma clock
* PARAMETERS
* none
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_clk_unprepare(void)
{
clk_unprepare(clk_btif);
clk_unprepare(clk_btif_apdma);
return 0;
}
#endif
/*****************************************************************************
* FUNCTION
* hal_btif_clk_ctrl
* DESCRIPTION
* control clock output enable/disable of BTIF module
* PARAMETERS
* p_base [IN] BTIF module's base address
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_clk_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif,
enum _ENUM_CLOCK_CTRL_ flag)
{
/*In MTK BTIF, there's only one global CG on AP_DMA, no sub channel's CG bit*/
/*according to Artis's comment, clock of DMA and BTIF is default off,*/
/*so we assume it to be off by default*/
int i_ret = 0;
unsigned long irq_flag = 0;
#if MTK_BTIF_ENABLE_CLK_REF_COUNTER
static atomic_t s_clk_ref = ATOMIC_INIT(0);
#else
static enum _ENUM_CLOCK_CTRL_ status = CLK_OUT_DISABLE;
#endif
spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);
#if MTK_BTIF_ENABLE_CLK_CTL
#if MTK_BTIF_ENABLE_CLK_REF_COUNTER
if (flag == CLK_OUT_ENABLE) {
if (atomic_inc_return(&s_clk_ref) == 1) {
#if defined(CONFIG_MTK_CLKMGR)
i_ret = enable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID);
#else
BTIF_DBG_FUNC("[CCF]enable clk_btif\n");
i_ret = clk_enable(clk_btif);
#endif /* defined(CONFIG_MTK_CLKMGR) */
if (i_ret) {
BTIF_WARN_FUNC
("enable_clock failed, ret:%d", i_ret);
}
}
} else if (flag == CLK_OUT_DISABLE) {
if (atomic_dec_return(&s_clk_ref) == 0) {
#if defined(CONFIG_MTK_CLKMGR)
i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID);
if (i_ret) {
BTIF_WARN_FUNC
("disable_clock failed, ret:%d", i_ret);
}
#else
BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif) calling\n");
clk_disable(clk_btif);
#endif /* defined(CONFIG_MTK_CLKMGR) */
}
} else {
i_ret = ERR_INVALID_PAR;
BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag);
}
#else
if (status == flag) {
i_ret = 0;
BTIF_DBG_FUNC("btif clock already %s\n",
CLK_OUT_ENABLE ==
status ? "enabled" : "disabled");
} else {
if (flag == CLK_OUT_ENABLE) {
#if defined(CONFIG_MTK_CLKMGR)
i_ret = enable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID);
#else
BTIF_DBG_FUNC("[CCF]enable clk_btif\n");
i_ret = clk_enable(clk_btif);
#endif /* defined(CONFIG_MTK_CLKMGR) */
status = (i_ret == 0) ? flag : status;
if (i_ret) {
BTIF_WARN_FUNC
("enable_clock failed, ret:%d", i_ret);
}
} else if (flag == CLK_OUT_DISABLE) {
#if defined(CONFIG_MTK_CLKMGR)
i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID);
status = (i_ret == 0) ? flag : status;
if (i_ret) {
BTIF_WARN_FUNC
("disable_clock failed, ret:%d", i_ret);
}
#else
BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif) calling\n");
clk_disable(clk_btif);
#endif /* defined(CONFIG_MTK_CLKMGR) */
} else {
i_ret = ERR_INVALID_PAR;
BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag);
}
}
#endif
#else
#if MTK_BTIF_ENABLE_CLK_REF_COUNTER
#else
status = flag;
#endif
i_ret = 0;
#endif
spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);
#if MTK_BTIF_ENABLE_CLK_REF_COUNTER
if (i_ret == 0) {
BTIF_DBG_FUNC("btif clock %s\n", flag == CLK_OUT_ENABLE ?
"enabled" : "disabled");
} else {
BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n",
flag == CLK_OUT_ENABLE ? "enable" : "disable",
i_ret);
}
#else
if (i_ret == 0) {
BTIF_DBG_FUNC("btif clock %s\n", flag == CLK_OUT_ENABLE ?
"enabled" : "disabled");
} else {
BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n",
flag == CLK_OUT_ENABLE ? "enable" : "disable",
i_ret);
}
#endif
#if defined(CONFIG_MTK_CLKMGR)
BTIF_DBG_FUNC("BTIF's clock is %s\n",
(clock_is_on(MTK_BTIF_CG_BIT) == 0) ? "off" : "on");
#endif
return i_ret;
}
static int btif_new_handshake_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif,
bool enable)
{
unsigned long base = p_btif->base;
if (enable == true)
BTIF_SET_BIT(BTIF_HANDSHAKE(base), BTIF_HANDSHAKE_EN_HANDSHAKE);
else
BTIF_CLR_BIT(BTIF_HANDSHAKE(base), BTIF_HANDSHAKE_EN_HANDSHAKE);
return true;
}
/*****************************************************************************
* FUNCTION
* hal_btif_hw_init
* DESCRIPTION
* BTIF hardware init
* PARAMETERS
* p_base [IN] BTIF module's base address
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_hw_init(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
/*Chaozhong: To be implement*/
int i_ret = -1;
unsigned long base = p_btif->base;
#if NEW_TX_HANDLING_SUPPORT
_btif_tx_fifo_reset(p_btif);
#endif
/*set to normal mode*/
btif_reg_sync_writel(BTIF_FAKELCR_NORMAL_MODE, BTIF_FAKELCR(base));
/*set to newhandshake mode*/
btif_new_handshake_ctrl(p_btif, true);
/*No need to access: enable sleep mode*/
/*No need to access: set Rx timeout count*/
/*set Tx threshold*/
/*set Rx threshold*/
/*disable internal loopback test*/
/*set Rx FIFO clear bit to 1*/
BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX);
/*clear Rx FIFO clear bit to 0*/
BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX);
/*set Tx FIFO clear bit to 1*/
BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX);
/*clear Tx FIFO clear bit to 0*/
BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX);
btif_reg_sync_writel(BTIF_TRI_LVL_TX(p_btif->tx_tri_lvl)
| BTIF_TRI_LVL_RX(p_btif->rx_tri_lvl)
| BTIF_TRI_LOOP_DIS, BTIF_TRI_LVL(base));
hal_btif_loopback_ctrl(p_btif, false);
/*disable BTIF Tx DMA mode*/
hal_btif_tx_mode_ctrl(p_btif, false);
/*disable BTIF Rx DMA mode*/
hal_btif_rx_mode_ctrl(p_btif, false);
/*auto reset*/
BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_AUTORST_EN);
/*disable Tx IER*/
hal_btif_tx_ier_ctrl(p_btif, false);
/*enable Rx IER by default*/
hal_btif_rx_ier_ctrl(p_btif, true);
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_rx_ier_ctrl
* DESCRIPTION
* BTIF Rx interrupt enable/disable
* PARAMETERS
* p_base [IN] BTIF module's base address
* enable [IN] control if rx interrupt enabled or not
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_rx_ier_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif, bool en)
{
int i_ret = -1;
unsigned long base = p_btif->base;
if (en == false)
BTIF_CLR_BIT(BTIF_IER(base), BTIF_IER_RXFEN);
else
BTIF_SET_BIT(BTIF_IER(base), BTIF_IER_RXFEN);
/*TODO:do we need to read back ? Answer: no*/
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_tx_ier_ctrl
* DESCRIPTION
* BTIF Tx interrupt enable/disable
* PARAMETERS
* p_base [IN] BTIF module's base address
* enable [IN] control if tx interrupt enabled or not
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_tx_ier_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif, bool en)
{
int i_ret = -1;
unsigned long base = p_btif->base;
if (en == false)
BTIF_CLR_BIT(BTIF_IER(base), BTIF_IER_TXEEN);
else
BTIF_SET_BIT(BTIF_IER(base), BTIF_IER_TXEEN);
/*TODO:do we need to read back ? Answer: no*/
i_ret = 0;
return i_ret;
}
#ifndef MTK_BTIF_MARK_UNUSED_API
/*****************************************************************************
* FUNCTION
* _btif_receive_data
* DESCRIPTION
* receive data from btif module in FIFO polling mode
* PARAMETERS
* p_base [IN] BTIF module's base address
* p_buf [IN/OUT] pointer to rx data buffer
* max_len [IN] max length of rx buffer
* RETURNS
* positive means data is available, 0 means no data available
*****************************************************************************/
int _btif_receive_data(struct _MTK_BTIF_INFO_STR_ *p_btif,
unsigned char *p_buf, const unsigned int max_len)
{
/*Chaozhong: To be implement*/
int i_ret = -1;
/*check parameter valid or not*/
if ((p_buf == NULL) || (max_len == 0)) {
i_ret = ERR_INVALID_PAR;
return i_ret;
}
i_ret = btif_rx_irq_handler(p_btif, p_buf, max_len);
return i_ret;
}
int btif_sleep_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif, bool en)
{
int i_ret = -1;
unsigned long base = p_btif->base;
if (en == false)
BTIF_CLR_BIT(BTIF_SLEEP_EN(base), BTIF_SLEEP_EN_BIT);
else
BTIF_SET_BIT(BTIF_SLEEP_EN(base), BTIF_SLEEP_EN_BIT);
/*TODO:do we need to read back ? Answer: no*/
/*TODO:do we need to dsb?*/
i_ret = 0;
return i_ret;
}
static int btif_tx_thr_set(struct _MTK_BTIF_INFO_STR_ *p_btif,
unsigned int thr_count)
{
int i_ret = -1;
unsigned long base = p_btif->base;
unsigned int value = 0;
/*read BTIF_TRI_LVL*/
value = BTIF_READ32(BTIF_TRI_LVL(base));
/*clear Tx threshold bits*/
value &= (~BTIF_TRI_LVL_TX_MASK);
/*set tx threshold bits*/
value |= BTIF_TRI_LVL_TX(BTIF_TX_FIFO_THRE);
/*write back to BTIF_TRI_LVL*/
btif_reg_sync_writel(value, BTIF_TRI_LVL(base));
return i_ret;
}
/*****************************************************************************
* FUNCTION
* btif_rx_fifo_reset
* DESCRIPTION
* reset BTIF's rx fifo
* PARAMETERS
* p_base [IN] BTIF module's base address
* ec [IN] control if loopback mode is enabled or not
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
static int btif_rx_fifo_reset(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
/*Chaozhong: To be implement*/
int i_ret = -1;
unsigned long base = p_btif->base;
/*set Rx FIFO clear bit to 1*/
BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX);
/*clear Rx FIFO clear bit to 0*/
BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX);
/*TODO:do we need to read back ? Answer: no*/
/*TODO:do we need to dsb?*/
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* btif_tx_fifo_reset
* DESCRIPTION
* reset BTIF's tx fifo
* PARAMETERS
* p_base [IN] BTIF module's base address
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
static int btif_tx_fifo_reset(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
int i_ret = -1;
unsigned long base = p_btif->base;
/*set Tx FIFO clear bit to 1*/
BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX);
/*clear Tx FIFO clear bit to 0*/
BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX);
/*TODO:do we need to read back ? Answer: no*/
/*TODO:do we need to dsb?*/
i_ret = 0;
return i_ret;
}
#endif
/*****************************************************************************
* FUNCTION
* hal_btif_loopback_ctrl
* DESCRIPTION
* BTIF Tx/Rx loopback mode set, this operation can only be done
* after set BTIF to normal mode
* PARAMETERS
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_loopback_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif, bool en)
{
int i_ret = -1;
unsigned long base = p_btif->base;
if (en == false)
BTIF_CLR_BIT(BTIF_TRI_LVL(base), BTIF_TRI_LOOP_EN);
else
BTIF_SET_BIT(BTIF_TRI_LVL(base), BTIF_TRI_LOOP_EN);
/*TODO:do we need to read back ? Answer: no*/
/*TODO:do we need to dsb?*/
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_rx_handler
* DESCRIPTION
* lower level interrupt handler
* PARAMETERS
* p_base [IN] BTIF module's base address
* p_buf [IN/OUT] pointer to rx data buffer
* max_len [IN] max length of rx buffer
* RETURNS
* 0 means success; negative means fail; positive means rx data length
*****************************************************************************/
int hal_btif_irq_handler(struct _MTK_BTIF_INFO_STR_ *p_btif,
unsigned char *p_buf, const unsigned int max_len)
{
/*Chaozhong: To be implement*/
int i_ret = -1;
unsigned int iir = 0;
unsigned int rx_len = 0;
unsigned long base = p_btif->base;
unsigned long irq_flag = 0;
spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);
#if defined(CONFIG_MTK_CLKMGR)
if (clock_is_on(MTK_BTIF_CG_BIT) == 0) {
spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);
BTIF_ERR_FUNC("%s: clock is off before irq handle done!!!\n",
__FILE__);
return i_ret;
}
#endif
/*read interrupt identifier register*/
iir = BTIF_READ32(BTIF_IIR(base));
while (iir & (BTIF_IIR_RX | BTIF_IIR_RX_TIMEOUT)) {
rx_len += btif_rx_irq_handler(p_btif, p_buf, max_len);
/*update IIR*/
iir = BTIF_READ32(BTIF_IIR(base));
}
/*is tx interrupt exist?*/
if (iir & BTIF_IIR_TX_EMPTY)
i_ret = btif_tx_irq_handler(p_btif);
spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);
i_ret = rx_len != 0 ? rx_len : i_ret;
return i_ret;
}
int hal_btif_rx_cb_reg(struct _MTK_BTIF_INFO_STR_ *p_btif_info,
btif_rx_buf_write rx_cb)
{
if (p_btif_info->rx_cb != NULL)
BTIF_DBG_FUNC("already registered, replace 0x%p with 0x%p\n",
p_btif_info->rx_cb, rx_cb);
p_btif_info->rx_cb = rx_cb;
return 0;
}
/*****************************************************************************
* FUNCTION
* btif_rx_irq_handler
* DESCRIPTION
* lower level rx interrupt handler
* PARAMETERS
* p_base [IN] BTIF module's base address
* RETURNS
* positive means length of rx data , negative means fail
*****************************************************************************/
static int btif_rx_irq_handler(struct _MTK_BTIF_INFO_STR_ *p_btif_info,
unsigned char *p_buf, const unsigned int max_len)
{
/*Chaozhong: To be implement*/
int i_ret = 0;
unsigned int iir = 0;
unsigned int rx_len = 0;
unsigned long base = p_btif_info->base;
unsigned char rx_buf[256];
unsigned int local_buf_len = 256;
btif_rx_buf_write rx_cb = p_btif_info->rx_cb;
unsigned int total_len = 0;
/*read interrupt identifier register*/
iir = BTIF_READ32(BTIF_IIR(base));
while ((iir & (BTIF_IIR_RX | BTIF_IIR_RX_TIMEOUT)) &&
(rx_len < local_buf_len)) {
rx_buf[rx_len] = BTIF_READ8(base);
rx_len++;
/*need to consult CC Hwang for advice */
/*
* whether we need to do memory barrier here
* Ans: no
*/
/*
* whether we need to d memory barrier when call BTIF_SET_BIT or BTIF_CLR_BIT
* Ans: no
*/
if (rx_len == local_buf_len) {
if (rx_cb)
(*rx_cb) (p_btif_info, rx_buf, rx_len);
rx_len = 0;
total_len += rx_len;
}
iir = BTIF_READ32(BTIF_IIR(base));
}
total_len += rx_len;
if (rx_len && rx_cb)
(*rx_cb) (p_btif_info, rx_buf, rx_len);
/*
* make sure all data write back to memory, mb or dsb?
* need to consult CC Hwang for advice
* Ans: no need here
*/
i_ret = total_len;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* btif_tx_irq_handler
* DESCRIPTION
* lower level tx interrupt handler
* PARAMETERS
* p_base [IN] BTIF module's base address
* p_buf [IN/OUT] pointer to rx data buffer
* max_len [IN] max length of rx buffer
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
static int btif_tx_irq_handler(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
int i_ret = -1;
#if NEW_TX_HANDLING_SUPPORT
int how_many = 0;
unsigned int lsr;
unsigned int ava_len = 0;
unsigned long base = p_btif->base;
char local_buf[BTIF_TX_FIFO_SIZE];
char *p_data = local_buf;
unsigned long flag = 0;
struct kfifo *p_tx_fifo = p_btif->p_tx_fifo;
/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/
lsr = BTIF_READ32(BTIF_LSR(base));
if (lsr & BTIF_LSR_TEMT_BIT)
/*Tx Holding Register if empty,*/
/*we can write tx FIFO count to BTIF*/
ava_len = BTIF_TX_FIFO_SIZE;
else if (lsr & BTIF_LSR_THRE_BIT)
/*Tx Holding Register if empty,*/
/*we can write (Tx FIFO count - Tx threshold)to BTIF*/
ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE;
else {
/*data size in tx FIFO is more than Tx threshold,*/
/*we will not write data to THR*/
ava_len = 0;
goto ret;
}
spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag);
how_many = kfifo_out(p_tx_fifo, local_buf, ava_len);
spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag);
BTIF_DBG_FUNC("BTIF tx size %d done, left:%d\n", how_many,
kfifo_avail(p_tx_fifo));
while (how_many--)
btif_reg_sync_writeb(*(p_data++), BTIF_THR(base));
spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag);
/*clear Tx enable flag if necessary*/
if (kfifo_is_empty(p_tx_fifo)) {
hal_btif_tx_ier_ctrl(p_btif, false);
BTIF_DBG_FUNC("BTIF tx FIFO is empty\n");
}
spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag);
ret:
#else
/*clear Tx enable flag*/
hal_btif_tx_ier_ctrl(p_btif, false);
#endif
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_tx_mode_ctrl
* DESCRIPTION
* set BTIF tx to corresponding mode (PIO/DMA)
* PARAMETERS
* p_base [IN] BTIF module's base address
* mode [IN] rx mode <PIO/DMA>
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_tx_mode_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif,
enum _ENUM_BTIF_MODE_ mode)
{
int i_ret = -1;
unsigned long base = p_btif->base;
if (mode == BTIF_MODE_DMA)
/*set to DMA mode*/
BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_TX);
else
/*set to PIO mode*/
BTIF_CLR_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_TX);
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_rx_mode_ctrl
* DESCRIPTION
* set BTIF rx to corresponding mode (PIO/DMA)
* PARAMETERS
* p_base [IN] BTIF module's base address
* mode [IN] rx mode <PIO/DMA>
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_rx_mode_ctrl(struct _MTK_BTIF_INFO_STR_ *p_btif,
enum _ENUM_BTIF_MODE_ mode)
{
int i_ret = -1;
unsigned long base = p_btif->base;
if (mode == BTIF_MODE_DMA)
/*set to DMA mode*/
BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_RX);
else
/*set to PIO mode*/
BTIF_CLR_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_RX);
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_send_data
* DESCRIPTION
* send data through btif in FIFO mode
* PARAMETERS
* p_base [IN] BTIF module's base address
* p_buf [IN] pointer to rx data buffer
* max_len [IN] tx buffer length
* RETURNS
* positive means number of data sent; 0 means no data put to FIFO;
* negative means error happens
*****************************************************************************/
int hal_btif_send_data(struct _MTK_BTIF_INFO_STR_ *p_btif,
const unsigned char *p_buf, const unsigned int buf_len)
{
/*Chaozhong: To be implement*/
int i_ret = -1;
unsigned int ava_len = 0;
unsigned int sent_len = 0;
#if !(NEW_TX_HANDLING_SUPPORT)
unsigned long base = p_btif->base;
unsigned int lsr = 0;
unsigned int left_len = 0;
unsigned char *p_data = (unsigned char *)p_buf;
#endif
/*check parameter valid or not*/
if ((p_buf == NULL) || (buf_len == 0)) {
i_ret = ERR_INVALID_PAR;
return i_ret;
}
#if NEW_TX_HANDLING_SUPPORT
ava_len = _get_btif_tx_fifo_room(p_btif);
sent_len = buf_len <= ava_len ? buf_len : ava_len;
if (sent_len > 0) {
int enqueue_len = 0;
unsigned long flag = 0;
spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag);
enqueue_len = kfifo_in(p_btif->p_tx_fifo,
(unsigned char *)p_buf, sent_len);
if (sent_len != enqueue_len) {
BTIF_ERR_FUNC("target tx len:%d, len sent:%d\n",
sent_len, enqueue_len);
}
i_ret = enqueue_len;
mb(); /* for btif send data */
/*enable BTIF Tx IRQ*/
hal_btif_tx_ier_ctrl(p_btif, true);
spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag);
BTIF_DBG_FUNC("enqueue len:%d\n", enqueue_len);
} else {
i_ret = 0;
}
#else
while ((_btif_is_tx_allow(p_btif)) && (sent_len < buf_len)) {
/*read LSR and check THER or TEMT,*/
/*either one is 1 means can accept tx data*/
lsr = BTIF_READ32(BTIF_LSR(base));
if (lsr & BTIF_LSR_TEMT_BIT)
/*Tx Holding Register if empty,*/
/*we can write tx FIFO count to BTIF*/
ava_len = BTIF_TX_FIFO_SIZE;
else if (lsr & BTIF_LSR_THRE_BIT)
/*Tx Holding Register if empty,*/
/*we can write (Tx FIFO count - Tx threshold)*/
/*to BTIF*/
ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE;
else {
/*data size in tx FIFO is more than Tx threshold,*/
/*we will not write data to THR*/
ava_len = 0;
break;
}
left_len = buf_len - sent_len;
/*ava_len will be real length will write to BTIF THR*/
ava_len = ava_len > left_len ? left_len : ava_len;
/*update sent length valud after this operation*/
sent_len += ava_len;
/*
* whether we need memory barrier here?
* Ans: No, no memory ordering issue exist,
* CPU will make sure logically right
*/
while (ava_len--)
btif_reg_sync_writeb(*(p_data++), BTIF_THR(base));
}
/* while ((hal_btif_is_tx_allow()) && (sent_len < buf_len)); */
i_ret = sent_len;
/*enable BTIF Tx IRQ*/
hal_btif_tx_ier_ctrl(p_btif, true);
#endif
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_raise_wak_sig
* DESCRIPTION
* raise wakeup signal to counterpart
* PARAMETERS
* p_base [IN] BTIF module's base address
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_raise_wak_sig(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
int i_ret = -1;
unsigned long base = p_btif->base;
#if defined(CONFIG_MTK_CLKMGR)
if (clock_is_on(MTK_BTIF_CG_BIT) == 0) {
BTIF_ERR_FUNC("%s: clock is off before send wakeup signal!!!\n",
__FILE__);
return i_ret;
}
#endif
/*write 0 to BTIF_WAK to pull ap_wakeup_consyss low */
BTIF_CLR_BIT(BTIF_WAK(base), BTIF_WAK_BIT);
/*wait for a period for longer than 1/32k period, here we use 40us*/
set_current_state(TASK_UNINTERRUPTIBLE);
usleep_range(128, 160);
/*
* according to linux/documentation/timers/timers-how-to, we choose usleep_range
* SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms): * Use usleep_range
*/
/*write 1 to pull ap_wakeup_consyss high*/
BTIF_SET_BIT(BTIF_WAK(base), BTIF_WAK_BIT);
i_ret = 0;
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_dump_reg
* DESCRIPTION
* dump BTIF module's information when needed
* PARAMETERS
* p_base [IN] BTIF module's base address
* flag [IN] register id flag
* RETURNS
* 0 means success, negative means fail
*****************************************************************************/
int hal_btif_dump_reg(struct _MTK_BTIF_INFO_STR_ *p_btif,
enum _ENUM_BTIF_REG_ID_ flag)
{
/*Chaozhong: To be implement*/
int i_ret = -1;
int idx = 0;
/*unsigned long irq_flag = 0;*/
unsigned long base = p_btif->base;
unsigned char reg_map[0xE0 / 4] = { 0 };
unsigned int lsr = 0x0;
unsigned int dma_en = 0;
/*spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);*/
#if defined(CONFIG_MTK_CLKMGR)
if (clock_is_on(MTK_BTIF_CG_BIT) == 0) {
/*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/
BTIF_ERR_FUNC("%s: clock is off, this should never happen!!!\n",
__FILE__);
return i_ret;
}
#endif
lsr = BTIF_READ32(BTIF_LSR(base));
dma_en = BTIF_READ32(BTIF_DMA_EN(base));
switch (flag) {
case REG_ALL:
/*
* here we omit 1st register which is THR/RBR register to avoid
* Rx data read by this debug information accidently
*/
for (idx = 1; idx < sizeof(reg_map); idx++)
reg_map[idx] = BTIF_READ8(p_btif->base + (4 * idx));
btif_dump_array("BTIF register", reg_map, sizeof(reg_map));
break;
case REG_IRQ:
BTIF_INFO_FUNC("IER:0x%x, IIR:0x%x, LSR:0x%x\n",
BTIF_READ32(BTIF_IER(base)),
BTIF_READ32(BTIF_IIR(base)),
lsr);
break;
default:
break;
}
BTIF_INFO_FUNC("Tx DMA %s, Rx DMA %s, Rx data is %s, Tx data is %s\n",
(dma_en & BTIF_DMA_EN_TX) ? "enabled" : "disabled",
(dma_en & BTIF_DMA_EN_RX) ? "enabled" : "disabled",
(lsr & BTIF_LSR_DR_BIT) ? "not empty" : "empty",
(lsr & BTIF_LSR_TEMT_BIT) ? "empty" : "not empty");
return i_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_is_tx_complete
* DESCRIPTION
* get tx complete flag
* PARAMETERS
* p_base [IN] BTIF module's base address
* RETURNS
* true means tx complete, false means tx in process
*****************************************************************************/
bool hal_btif_is_tx_complete(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
/*Chaozhong: To be implement*/
bool b_ret = false;
unsigned int lsr = 0;
unsigned long flags = 0;
unsigned long base = p_btif->base;
unsigned int tx_empty = 0;
unsigned int rx_dr = 0;
unsigned int tx_irq_disable = 0;
/*
* 3 conditions allow clock to be disable
* 1. if TEMT is set or not
* 2. if DR is set or not
* 3. Tx IRQ is disabled or not
*/
lsr = BTIF_READ32(BTIF_LSR(base));
tx_empty = lsr & BTIF_LSR_TEMT_BIT;
rx_dr = lsr & BTIF_LSR_DR_BIT;
tx_irq_disable = BTIF_READ32(BTIF_IER(base)) & BTIF_IER_TXEEN;
b_ret =
(tx_empty && (tx_irq_disable == 0) && (rx_dr == 0)) ? true : false;
if (!b_ret) {
BTIF_DBG_FUNC
("BTIF flag, tx_empty:%d, rx_dr:%d, tx_irq_disable:%d\n",
tx_empty, rx_dr, tx_irq_disable);
}
#if NEW_TX_HANDLING_SUPPORT
spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flags);
/*clear Tx enable flag if necessary*/
if (!(kfifo_is_empty(p_btif->p_tx_fifo))) {
BTIF_DBG_FUNC("BTIF tx FIFO is not empty\n");
b_ret = false;
}
spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flags);
#endif
return b_ret;
}
/*****************************************************************************
* FUNCTION
* hal_btif_is_tx_allow
* DESCRIPTION
* whether tx is allowed
* PARAMETERS
* p_base [IN] BTIF module's base address
* RETURNS
* true if tx operation is allowed; false if tx is not allowed
*****************************************************************************/
bool hal_btif_is_tx_allow(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
#define MIN_TX_MB ((26 * 1000000 / 13) / 1000000)
#define AVE_TX_MB ((26 * 1000000 / 8) / 1000000)
/*Chaozhong: To be implement*/
bool b_ret = false;
#if NEW_TX_HANDLING_SUPPORT
unsigned long flags = 0;
spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flags);
/*clear Tx enable flag if necessary*/
if (kfifo_is_full(p_btif->p_tx_fifo)) {
BTIF_WARN_FUNC("BTIF tx FIFO is full\n");
b_ret = false;
} else {
b_ret = true;
}
spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flags);
#else
unsigned int lsr = 0;
unsigned long base = p_btif->base;
unsigned int wait_us = (BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE) /
MIN_TX_MB; /*only ava length */
/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/
lsr = BTIF_READ32(BTIF_LSR(base));
if (!(lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT))) {
BTIF_DBG_FUNC("wait for %d ~ %d us\n", wait_us, 3 * wait_us);
/* usleep_range(wait_us, 3 * 10 * wait_us); */
usleep_range(wait_us, 3 * wait_us);
}
lsr = BTIF_READ32(BTIF_LSR(base));
b_ret = (lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT)) ? true : false;
if (!b_ret)
BTIF_DBG_FUNC(" tx is not allowed for the moment\n");
else
BTIF_DBG_FUNC(" tx is allowed\n");
#endif
return b_ret;
}
#if !(NEW_TX_HANDLING_SUPPORT)
static bool _btif_is_tx_allow(struct _MTK_BTIF_INFO_STR_ *p_btif)
{
/*Chaozhong: To be implement*/
bool b_ret = false;
unsigned long base = p_btif->base;
unsigned int lsr = 0;
/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/
lsr = BTIF_READ32(BTIF_LSR(base));
b_ret = (lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT)) ? true : false;
return b_ret;
}
#endif
int hal_btif_pm_ops(struct _MTK_BTIF_INFO_STR_ *p_btif_info,
enum _MTK_BTIF_PM_OPID_ opid)
{
int i_ret = -1;
BTIF_DBG_FUNC("op id: %d\n", opid);
switch (opid) {
case BTIF_PM_DPIDLE_EN:
i_ret = 0;
break;
case BTIF_PM_DPIDLE_DIS:
i_ret = 0;
break;
case BTIF_PM_SUSPEND:
i_ret = 0;
break;
case BTIF_PM_RESUME:
i_ret = 0;
break;
case BTIF_PM_RESTORE_NOIRQ:{
unsigned int flag = 0;
struct _MTK_BTIF_IRQ_STR_ *p_irq = p_btif_info->p_irq;
#ifdef CONFIG_OF
flag = p_irq->irq_flags;
#else
switch (p_irq->sens_type) {
case IRQ_SENS_EDGE:
if (p_irq->edge_type == IRQ_EDGE_FALL)
flag = IRQF_TRIGGER_FALLING;
else if (p_irq->edge_type == IRQ_EDGE_RAISE)
flag = IRQF_TRIGGER_RISING;
else if (p_irq->edge_type == IRQ_EDGE_BOTH)
flag = IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING;
else
flag = IRQF_TRIGGER_FALLING;
break;
case IRQ_SENS_LVL:
if (p_irq->lvl_type == IRQ_LVL_LOW)
flag = IRQF_TRIGGER_LOW;
else if (p_irq->lvl_type == IRQ_LVL_HIGH)
flag = IRQF_TRIGGER_HIGH;
else
flag = IRQF_TRIGGER_LOW;
break;
default:
flag = IRQF_TRIGGER_LOW;
break;
}
#endif
/* irq_set_irq_type(p_irq->irq_id, flag); */
i_ret = 0;
}
break;
default:
i_ret = ERR_INVALID_PAR;
break;
}
return i_ret;
}
void mtk_btif_read_cpu_sw_rst_debug_plat(void)
{
#define CONSYS_AP2CONN_WAKEUP_OFFSET 0x00000064
BTIF_WARN_FUNC("+CONSYS_AP2CONN_WAKEUP_OFFSET(0x%x)\n",
BTIF_READ32(mtk_btif_info.base + CONSYS_AP2CONN_WAKEUP_OFFSET));
}