868 lines
23 KiB
C
868 lines
23 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#ifdef DFT_TAG
|
|
#undef DFT_TAG
|
|
#endif
|
|
#define DFT_TAG "MTK-BTIF-EXP"
|
|
|
|
/*#include "mtk_btif_exp.h"*/
|
|
#include "mtk_btif.h"
|
|
|
|
/*---------------------------------Function----------------------------------*/
|
|
|
|
struct _mtk_btif_ *btif_exp_srh_id(unsigned long u_id)
|
|
{
|
|
int index = 0;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
struct list_head *p_list = NULL;
|
|
struct list_head *tmp = NULL;
|
|
struct _mtk_btif_user_ *p_user = NULL;
|
|
|
|
for (index = 0; (index < BTIF_PORT_NR) && (p_btif == NULL); index++) {
|
|
p_list = &(g_btif[index].user_list);
|
|
list_for_each(tmp, p_list) {
|
|
p_user = container_of(tmp,
|
|
struct _mtk_btif_user_,
|
|
entry);
|
|
if (u_id == p_user->u_id) {
|
|
p_btif = p_user->p_btif;
|
|
BTIF_DBG_FUNC
|
|
("BTIF's user id(%lu), p_btif(0x%p)\n",
|
|
p_user->u_id, p_btif);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (p_btif == NULL) {
|
|
BTIF_INFO_FUNC
|
|
("no btif structure found for BTIF's user id(0x%lx)\n",
|
|
u_id);
|
|
}
|
|
return p_btif;
|
|
}
|
|
|
|
/*-----Normal Mode API declearation-------*/
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_open
|
|
* DESCRIPTION
|
|
* open BTIF interface, will do BTIF module HW and SW initialization
|
|
* PARAMETERS
|
|
* p_owner [IN] pointer to owner who call this API,
|
|
* currently there are 2 owner ("stp" or "btif_tester")
|
|
* may use this module
|
|
* for "stp", BTIF will call rx callback function to route rx data to STP
|
|
* for "stp_tester", BTIF will save rx data and wait for native process
|
|
* to access
|
|
* p_id [IN] BTIF's user id will be put to this address
|
|
* RETURNS
|
|
* int 0 = BTIF module initialization fail;
|
|
* negative = BTIF module initialization success
|
|
* if open success, value p_id will be the only identifier
|
|
* for user to access BTIF's other operations
|
|
* including read/write/dpidle_ctrl/rx_cb_retister
|
|
* this user id is only an identifier used for owner identification
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_open(char *p_owner, unsigned long *p_id)
|
|
{
|
|
int i_ret = -1;
|
|
unsigned int index = 0;
|
|
struct _mtk_btif_user_ *p_new_user = NULL;
|
|
struct _mtk_btif_ *p_btif = &g_btif[index];
|
|
struct list_head *p_user_list = &(p_btif->user_list);
|
|
|
|
BTIF_DBG_FUNC("++");
|
|
BTIF_DBG_FUNC("p_btif(0x%p)\n", p_btif);
|
|
|
|
if (mutex_lock_killable(&(p_btif->ops_mtx))) {
|
|
BTIF_ERR_FUNC("mutex_lock_killable return failed\n");
|
|
return E_BTIF_INTR;
|
|
}
|
|
if ((p_owner == NULL) || (p_id == NULL)) {
|
|
if (p_id)
|
|
*p_id = 0;
|
|
BTIF_ERR_FUNC("parameter invalid, p_owner(0x%p), p_id(0x%p)\n",
|
|
p_owner, p_id);
|
|
BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx));
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
|
|
/*check if btif is already opened or not, if yes, just return fail*/
|
|
if (!list_empty(p_user_list)) {
|
|
struct list_head *pos = NULL;
|
|
struct _mtk_btif_user_ *p_user = NULL;
|
|
|
|
BTIF_ERR_FUNC("BTIF's user list is not empty\n");
|
|
list_for_each(pos, p_user_list) {
|
|
p_user = container_of(pos,
|
|
struct _mtk_btif_user_,
|
|
entry);
|
|
BTIF_INFO_FUNC("BTIF's user id(0x%lx), name(%s)\n",
|
|
p_user->u_id, p_user->u_name);
|
|
}
|
|
/*leave p_id alone*/
|
|
BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx));
|
|
return E_BTIF_ALREADY_OPEN;
|
|
}
|
|
p_new_user = vmalloc(sizeof(struct _mtk_btif_user_));
|
|
|
|
if (p_new_user != NULL) {
|
|
INIT_LIST_HEAD(&(p_new_user->entry));
|
|
p_new_user->enable = false;
|
|
p_new_user->p_btif = p_btif;
|
|
p_new_user->u_id = (unsigned long)p_new_user;
|
|
strncpy(p_new_user->u_name, p_owner,
|
|
sizeof(p_new_user->u_name) - 1);
|
|
p_new_user->u_name[sizeof(p_new_user->u_name) - 1] = '\0';
|
|
BTIF_DBG_FUNC("owner name:%s, recorded name:%s\n",
|
|
p_owner, p_new_user->u_name);
|
|
|
|
i_ret = btif_open(p_btif);
|
|
if (i_ret) {
|
|
BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret);
|
|
*p_id = 0;
|
|
/*free btif new user's structure*/
|
|
vfree(p_new_user);
|
|
p_new_user = NULL;
|
|
} else {
|
|
BTIF_INFO_FUNC("btif_open succeed\n");
|
|
*p_id = p_new_user->u_id;
|
|
/*mark enable flag to true*/
|
|
p_new_user->enable = true;
|
|
/*add to uer lsit*/
|
|
list_add_tail(&(p_new_user->entry), p_user_list);
|
|
}
|
|
} else {
|
|
*p_id = 0;
|
|
i_ret = -ENOMEM;
|
|
BTIF_ERR_FUNC("alloc memory struct _mtk_btif_user_ failed\n");
|
|
}
|
|
BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx));
|
|
BTIF_DBG_FUNC("--");
|
|
return i_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_open);
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_close
|
|
* DESCRIPTION
|
|
* close BTIF interface, will do BTIF module HW and SW de-initialization
|
|
* once this API is called, p_btif should never be used by BTIF's user again
|
|
* PARAMETERS
|
|
* u_id [IN] BTIF's user id
|
|
* RETURNS
|
|
* int 0 = succeed;
|
|
* others = fail,
|
|
* for detailed information, please see ENUM_BTIF_OP_ERROR_CODE
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_close(unsigned long u_id)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
struct list_head *pos = NULL;
|
|
struct list_head *p_user_list = NULL;
|
|
|
|
BTIF_DBG_FUNC("++");
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
|
|
if (mutex_lock_killable(&(p_btif->ops_mtx))) {
|
|
BTIF_ERR_FUNC("mutex_lock_killable return failed\n");
|
|
return E_BTIF_INTR;
|
|
}
|
|
p_user_list = &(p_btif->user_list);
|
|
list_for_each(pos, p_user_list) {
|
|
struct _mtk_btif_user_ *p_user =
|
|
container_of(pos, struct _mtk_btif_user_, entry);
|
|
|
|
if (p_user->u_id == u_id) {
|
|
BTIF_INFO_FUNC
|
|
("user who's id is 0x%lx deleted from user list\n",
|
|
u_id);
|
|
list_del(pos);
|
|
vfree(p_user);
|
|
i_ret = btif_close(p_btif);
|
|
if (i_ret)
|
|
BTIF_WARN_FUNC("BTIF close failed");
|
|
break;
|
|
}
|
|
}
|
|
BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx));
|
|
BTIF_DBG_FUNC("--");
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_close);
|
|
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_write
|
|
* DESCRIPTION
|
|
* send data throuth BTIF module
|
|
* there's no internal buffer to cache STP data in BTIF driver,
|
|
* if in DMA mode
|
|
* btif driver will check if there's enough space in vFIFO for data to send
|
|
* in DMA mode
|
|
* if yes, put data to vFIFO and return corresponding data length to caller
|
|
* if no, corresponding error code will be returned to called
|
|
* PARAMETERS
|
|
* p_btif [IN] pointer returned by mtk_wcn_btif_open
|
|
* p_buf [IN] pointer to target data to send
|
|
* len [IN] data length (less than 2014 bytes per STP package)
|
|
*
|
|
* if in non-DMA mode, BTIF driver will try to write to THR of BTIF controller
|
|
* if btif driver detected that no space is available in Tx FIFO,
|
|
* will return E_BTIF_NO_SPACE, mostly something is wrong with BTIF or
|
|
* consys when this return value is returned
|
|
* RETURNS
|
|
* int positive: data length send through BTIF;
|
|
* negative: please see ENUM_BTIF_OP_ERROR_CODE
|
|
* E_BTIF_AGAIN (0) will be returned to caller
|
|
* if btif does not have enough vFIFO to send data,
|
|
* when caller get 0, he should wait for a moment
|
|
* (5~10ms maybe) and try a few times (maybe 10~20)
|
|
* if still get E_BTIF_AGAIN,
|
|
* should call BTIF's debug API and dump BTIF driver
|
|
* and BTIF/DMA register information to kernel log for debug
|
|
* E_BTIF_BAD_POINTER will be returned to caller
|
|
* if btif is not opened successfully before call this API
|
|
* E_BTIF_INVAL_PARAM will be returned if parameter is not valid
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_write(unsigned long u_id,
|
|
const unsigned char *p_buf, unsigned int len)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
BTIF_DBG_FUNC("++");
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
if (p_buf == NULL) {
|
|
BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf);
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) {
|
|
BTIF_ERR_FUNC("invalid buffer length(%d)\n", len);
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
|
|
i_ret = btif_send_data(p_btif, p_buf, len);
|
|
BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret);
|
|
return i_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_write);
|
|
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_read
|
|
* DESCRIPTION
|
|
* read data from BTIF module
|
|
* PARAMETERS
|
|
* p_btif [IN] pointer returned by mtk_wcn_btif_open
|
|
* p_buf [IN/OUT] pointer to buffer where rx data will be put
|
|
* max_len [IN] max buffer length
|
|
* RETURNS
|
|
* int positive: data length read from BTIF;
|
|
* negative: please see ENUM_BTIF_OP_ERROR_CODE
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_read(unsigned long u_id,
|
|
unsigned char *p_buf, unsigned int max_len)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_dpidle_ctrl
|
|
* DESCRIPTION
|
|
* control if BTIF module allow system enter deepidle state or not
|
|
* PARAMETERS
|
|
* p_btif [IN] pointer returned by mtk_wcn_btif_open
|
|
* en_flag [IN] one of enum _ENUM_BTIF_DPIDLE_
|
|
* RETURNS
|
|
* int always return 0
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_dpidle_ctrl(unsigned long u_id,
|
|
enum _ENUM_BTIF_DPIDLE_ en_flag)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
|
|
if (en_flag == BTIF_DPIDLE_DISABLE)
|
|
i_ret = btif_exit_dpidle(p_btif);
|
|
else
|
|
i_ret = btif_enter_dpidle(p_btif);
|
|
|
|
return i_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_dpidle_ctrl);
|
|
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_rx_cb_register
|
|
* DESCRIPTION
|
|
* register rx callback function to BTIF module by btif user
|
|
* PARAMETERS
|
|
* p_btif [IN] pointer returned by mtk_wcn_btif_open
|
|
* rx_cb [IN] pointer to stp rx handler callback function,
|
|
* should be comply with MTK_WCN_BTIF_RX_CB
|
|
* RETURNS
|
|
* int 0 = succeed;
|
|
* others = fail, for detailed information,
|
|
* please see ENUM_BTIF_OP_ERROR_CODE
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_rx_cb_register(unsigned long u_id, MTK_WCN_BTIF_RX_CB rx_cb)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
|
|
i_ret = btif_rx_cb_reg(p_btif, rx_cb);
|
|
|
|
return i_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_rx_cb_register);
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_wakeup_consys
|
|
* DESCRIPTION
|
|
* once sleep command is sent to con sys,
|
|
* should call this API before send wakeup command
|
|
* to make con sys aware host want to send data to consys
|
|
* PARAMETERS
|
|
* p_btif [IN] pointer returned by mtk_wcn_btif_open
|
|
* RETURNS
|
|
* int 0 = succeed; others = fail, for detailed information,
|
|
* please see ENUM_BTIF_OP_ERROR_CODE
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_wakeup_consys(unsigned long u_id)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
|
|
/*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/
|
|
i_ret = btif_raise_wak_signal(p_btif);
|
|
|
|
return i_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_wakeup_consys);
|
|
|
|
|
|
/***************End of Normal Mode API declearation**********/
|
|
|
|
/***************Debug Purpose API declearation**********/
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_loopback_ctrl
|
|
* DESCRIPTION
|
|
* enable/disable BTIF internal loopback function,
|
|
* when this function is enabled data send to btif
|
|
* will be received by btif itself
|
|
* only for debug purpose, should never use this function in normal mode
|
|
* PARAMETERS
|
|
* p_btif [IN] pointer returned by mtk_wcn_btif_open
|
|
* enable [IN] loopback mode control flag, enable or disable,
|
|
* shou be one of enum _ENUM_BTIF_LPBK_MODE_
|
|
* RETURNS
|
|
* int 0 = succeed;
|
|
* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_loopback_ctrl(unsigned long u_id,
|
|
enum _ENUM_BTIF_LPBK_MODE_ enable)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
i_ret =
|
|
btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false);
|
|
|
|
return i_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_loopback_ctrl);
|
|
|
|
/*****************************************************************************
|
|
* FUNCTION
|
|
* mtk_wcn_btif_logger_ctrl
|
|
* DESCRIPTION
|
|
* control BTIF logger function's behavior
|
|
* PARAMETERS
|
|
* p_btif [IN] pointer returned by mtk_wcn_btif_open
|
|
* flag [IN] should be one of enum _ENUM_BTIF_DBG_ID_
|
|
* BTIF_DISABLE_LOGGER - disable btif logger
|
|
* BTIF_ENABLE_LOGGER - enable btif logger
|
|
* BTIF_DUMP_LOG - dump log logged by btif
|
|
* BTIF_CLR_LOG - clear btif log buffer
|
|
* BTIF_DUMP_BTIF_REG - dump btif controller's register
|
|
* BTIF_DUMP_DMA_REG - dump DMA controller's register
|
|
* RETURNS
|
|
* int 0 = succeed; others = fail, for detailed information,
|
|
* please see ENUM_BTIF_OP_ERROR_CODE
|
|
*****************************************************************************/
|
|
int mtk_wcn_btif_dbg_ctrl(unsigned long u_id, enum _ENUM_BTIF_DBG_ID_ flag)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
|
|
i_ret = 0;
|
|
switch (flag) {
|
|
case BTIF_DISABLE_LOGGER:{
|
|
BTIF_INFO_FUNC
|
|
("disable btif log function for both Tx and Rx\n");
|
|
btif_log_buf_disable(&p_btif->tx_log);
|
|
btif_log_buf_disable(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
case BTIF_ENABLE_LOGGER:{
|
|
BTIF_INFO_FUNC
|
|
("enable btif log function for both Tx and Rx\n");
|
|
btif_log_buf_enable(&p_btif->tx_log);
|
|
btif_log_buf_enable(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
case BTIF_DUMP_LOG:{
|
|
BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n");
|
|
btif_log_buf_dmp_out(&p_btif->tx_log);
|
|
btif_log_buf_dmp_out(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
|
|
case BTIF_CLR_LOG:{
|
|
BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n");
|
|
btif_log_buf_reset(&p_btif->tx_log);
|
|
btif_log_buf_reset(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
case BTIF_DUMP_BTIF_REG:
|
|
btif_dump_reg(p_btif, REG_ALL);
|
|
break;
|
|
case BTIF_DUMP_BTIF_IRQ:
|
|
btif_dump_reg(p_btif, REG_IRQ);
|
|
break;
|
|
case BTIF_ENABLE_RT_LOG:
|
|
BTIF_INFO_FUNC
|
|
("enable btif real time log for both Tx and Rx\n");
|
|
btif_log_output_enable(&p_btif->tx_log);
|
|
btif_log_output_enable(&p_btif->rx_log);
|
|
break;
|
|
case BTIF_DISABLE_RT_LOG:
|
|
BTIF_INFO_FUNC
|
|
("disable btif real time log for both Tx and Rx\n");
|
|
btif_log_output_disable(&p_btif->tx_log);
|
|
btif_log_output_disable(&p_btif->rx_log);
|
|
break;
|
|
case BTIF_DUMP_DMA_VFIFO:
|
|
btif_dump_dma_vfifo(p_btif);
|
|
break;
|
|
default:
|
|
BTIF_INFO_FUNC("not supported flag:%d\n", flag);
|
|
i_ret = -2;
|
|
break;
|
|
}
|
|
|
|
return i_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_dbg_ctrl);
|
|
|
|
bool mtk_wcn_btif_parser_wmt_evt(unsigned long u_id,
|
|
const char *sub_str, unsigned int str_len)
|
|
{
|
|
bool b_ret = false;
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
|
|
if (p_btif == NULL)
|
|
return E_BTIF_INVAL_PARAM;
|
|
b_ret = btif_parser_wmt_evt(p_btif, sub_str, str_len);
|
|
BTIF_INFO_FUNC("parser wmt evt %s\n", b_ret ? "ok" : "fail");
|
|
|
|
return b_ret;
|
|
}
|
|
EXPORT_SYMBOL(mtk_wcn_btif_parser_wmt_evt);
|
|
|
|
/**********End of Debug Purpose API declearation**********/
|
|
|
|
int btif_open_no_id(void)
|
|
{
|
|
int i_ret = 0;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret = btif_open(p_btif);
|
|
|
|
if (i_ret)
|
|
BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret);
|
|
else
|
|
BTIF_INFO_FUNC("btif_open succeed\n");
|
|
|
|
return i_ret;
|
|
}
|
|
|
|
int btif_close_no_id(void)
|
|
{
|
|
int i_ret = 0;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret = btif_close(p_btif);
|
|
|
|
if (i_ret)
|
|
BTIF_ERR_FUNC("btif_close failed, i_ret(%d)\n", i_ret);
|
|
else
|
|
BTIF_INFO_FUNC("btif_close succeed\n");
|
|
return i_ret;
|
|
}
|
|
|
|
int btif_write_no_id(const unsigned char *p_buf, unsigned int len)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
BTIF_DBG_FUNC("++");
|
|
|
|
if (p_buf == NULL) {
|
|
BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf);
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) {
|
|
BTIF_ERR_FUNC("invalid buffer length(%d)\n", len);
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
|
|
i_ret = btif_send_data(p_btif, p_buf, len);
|
|
BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret);
|
|
return i_ret;
|
|
}
|
|
|
|
int btif_dpidle_ctrl_no_id(enum _ENUM_BTIF_DPIDLE_ en_flag)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
if (en_flag == BTIF_DPIDLE_DISABLE)
|
|
i_ret = btif_exit_dpidle(p_btif);
|
|
else
|
|
i_ret = btif_enter_dpidle(p_btif);
|
|
|
|
return i_ret;
|
|
}
|
|
|
|
int btif_wakeup_consys_no_id(void)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
/*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/
|
|
i_ret = btif_raise_wak_signal(p_btif);
|
|
|
|
return i_ret;
|
|
}
|
|
|
|
int btif_loopback_ctrl_no_id(enum _ENUM_BTIF_LPBK_MODE_ enable)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret =
|
|
btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false);
|
|
|
|
return i_ret;
|
|
}
|
|
|
|
int btif_dbg_ctrl_no_id(enum _ENUM_BTIF_DBG_ID_ flag)
|
|
{
|
|
int i_ret = -1;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret = 0;
|
|
switch (flag) {
|
|
case BTIF_DISABLE_LOGGER:{
|
|
BTIF_INFO_FUNC
|
|
("disable btif log function for both Tx and Rx\n");
|
|
btif_log_buf_disable(&p_btif->tx_log);
|
|
btif_log_buf_disable(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
case BTIF_ENABLE_LOGGER:{
|
|
BTIF_INFO_FUNC
|
|
("enable btif log function for both Tx and Rx\n");
|
|
btif_log_buf_enable(&p_btif->tx_log);
|
|
btif_log_buf_enable(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
case BTIF_DUMP_LOG:{
|
|
BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n");
|
|
btif_log_buf_dmp_out(&p_btif->tx_log);
|
|
btif_log_buf_dmp_out(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
|
|
case BTIF_CLR_LOG:{
|
|
BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n");
|
|
btif_log_buf_reset(&p_btif->tx_log);
|
|
btif_log_buf_reset(&p_btif->rx_log);
|
|
}
|
|
break;
|
|
case BTIF_DUMP_BTIF_REG:
|
|
btif_dump_reg(p_btif, REG_ALL);
|
|
break;
|
|
case BTIF_DUMP_BTIF_IRQ:
|
|
btif_dump_reg(p_btif, REG_IRQ);
|
|
break;
|
|
case BTIF_ENABLE_RT_LOG:
|
|
BTIF_INFO_FUNC
|
|
("enable btif real time log for both Tx and Rx\n");
|
|
btif_log_output_enable(&p_btif->tx_log);
|
|
btif_log_output_enable(&p_btif->rx_log);
|
|
break;
|
|
case BTIF_DISABLE_RT_LOG:
|
|
BTIF_INFO_FUNC
|
|
("disable btif real time log for both Tx and Rx\n");
|
|
btif_log_output_disable(&p_btif->tx_log);
|
|
btif_log_output_disable(&p_btif->rx_log);
|
|
break;
|
|
default:
|
|
BTIF_INFO_FUNC("not supported flag:%d\n", flag);
|
|
i_ret = -2;
|
|
break;
|
|
}
|
|
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_open_test(void)
|
|
{
|
|
int i_ret = 0;
|
|
|
|
i_ret = btif_open_no_id();
|
|
if (i_ret < 0) {
|
|
BTIF_INFO_FUNC("mtk_wcn_btif_open failed\n");
|
|
return -1;
|
|
}
|
|
|
|
BTIF_INFO_FUNC("mtk_wcn_btif_open succeed\n");
|
|
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_close_test(void)
|
|
{
|
|
int i_ret = 0;
|
|
|
|
i_ret = btif_close_no_id();
|
|
if (i_ret < 0) {
|
|
BTIF_INFO_FUNC("mtk_wcn_btif_close failed\n");
|
|
return -1;
|
|
}
|
|
|
|
BTIF_INFO_FUNC("mtk_wcn_btif_close succeed\n");
|
|
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_write_test(void)
|
|
{
|
|
return mtk_btif_exp_write_stress_test(100, 10);
|
|
}
|
|
|
|
int mtk_btif_exp_write_stress_test(unsigned int length, unsigned int max_loop)
|
|
{
|
|
#define BUF_LEN 1024
|
|
int i_ret = 0;
|
|
int idx = 0;
|
|
int buf_len = length > BUF_LEN ? BUF_LEN : length;
|
|
int loop = max_loop > 1000000 ? 1000000 : max_loop;
|
|
unsigned char *buffer;
|
|
|
|
buffer = kmalloc(BUF_LEN, GFP_KERNEL);
|
|
if (!buffer) {
|
|
BTIF_ERR_FUNC("btif tester kmalloc failed\n");
|
|
return -1;
|
|
}
|
|
|
|
for (idx = 0; idx < buf_len; idx++)
|
|
/* btif_stress_test_buf[idx] = BUF_LEN -idx; */
|
|
*(buffer + idx) = idx % 255;
|
|
i_ret = btif_loopback_ctrl_no_id(BTIF_LPBK_ENABLE);
|
|
BTIF_INFO_FUNC("mtk_wcn_btif_loopback_ctrl returned %d\n", i_ret);
|
|
while (loop--) {
|
|
i_ret = btif_write_no_id(buffer, buf_len);
|
|
BTIF_INFO_FUNC("mtk_wcn_btif_write left loop:%d, i_ret:%d\n",
|
|
loop, i_ret);
|
|
if (i_ret != buf_len) {
|
|
BTIF_INFO_FUNC("target len %d, sent len: %d\n",
|
|
buf_len, i_ret);
|
|
break;
|
|
}
|
|
buf_len--;
|
|
if (buf_len <= 0)
|
|
buf_len = length > BUF_LEN ? BUF_LEN : length;
|
|
}
|
|
kfree(buffer);
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_suspend_test(void)
|
|
{
|
|
int i_ret = 0;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret = _btif_suspend(p_btif);
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_restore_noirq_test(void)
|
|
{
|
|
int i_ret = 0;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret = _btif_restore_noirq(p_btif);
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_clock_ctrl(int en)
|
|
{
|
|
int i_ret = 0;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret = btif_clock_ctrl(p_btif, en);
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_resume_test(void)
|
|
{
|
|
int i_ret = 0;
|
|
struct _mtk_btif_ *p_btif = &g_btif[0];
|
|
|
|
i_ret = _btif_resume(p_btif);
|
|
return i_ret;
|
|
}
|
|
|
|
int mtk_btif_exp_enter_dpidle_test(void)
|
|
{
|
|
return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_ENABLE);
|
|
}
|
|
|
|
int mtk_btif_exp_exit_dpidle_test(void)
|
|
{
|
|
return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_DISABLE);
|
|
}
|
|
|
|
int mtk_btif_exp_log_debug_test(int flag)
|
|
{
|
|
int i_ret = 0;
|
|
|
|
i_ret = btif_dbg_ctrl_no_id(flag);
|
|
return i_ret;
|
|
}
|
|
|
|
void mtk_btif_read_cpu_sw_rst_debug_exp(void)
|
|
{
|
|
mtk_btif_read_cpu_sw_rst_debug();
|
|
}
|
|
|
|
int mtk_btif_exp_rx_has_pending_data(unsigned long u_id)
|
|
{
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
int has_pending_data = 0;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
if (p_btif == NULL) {
|
|
BTIF_ERR_FUNC("parameter invalid\n");
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
|
|
/* Lock the data path to ensure that the current data path is
|
|
* not processing data. If fail to get lock, it means rx data
|
|
* path is busy and we assume there has pending data to avoid
|
|
* thread is blocked here.
|
|
*/
|
|
if (btif_rx_data_path_lock(p_btif))
|
|
return 1;
|
|
|
|
has_pending_data = btif_rx_buf_has_pending_data(p_btif);
|
|
if (has_pending_data == 0)
|
|
has_pending_data = btif_rx_dma_has_pending_data(p_btif);
|
|
|
|
btif_rx_data_path_unlock(p_btif);
|
|
return has_pending_data;
|
|
}
|
|
EXPORT_SYMBOL(mtk_btif_exp_rx_has_pending_data);
|
|
|
|
int mtk_btif_exp_tx_has_pending_data(unsigned long u_id)
|
|
{
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
if (p_btif == NULL) {
|
|
BTIF_ERR_FUNC("E_BTIF_INVAL_PARAM\n");
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
|
|
return btif_tx_dma_has_pending_data(p_btif);
|
|
}
|
|
EXPORT_SYMBOL(mtk_btif_exp_tx_has_pending_data);
|
|
|
|
int mtk_btif_is_tx_complete(unsigned long u_id)
|
|
{
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
if (p_btif == NULL) {
|
|
BTIF_ERR_FUNC("E_BTIF_INVAL_PARAM\n");
|
|
return E_BTIF_INVAL_PARAM;
|
|
}
|
|
|
|
return btif_is_tx_complete(p_btif);
|
|
}
|
|
EXPORT_SYMBOL(mtk_btif_is_tx_complete);
|
|
|
|
struct task_struct *mtk_btif_exp_rx_thread_get(unsigned long u_id)
|
|
{
|
|
struct _mtk_btif_ *p_btif = NULL;
|
|
|
|
p_btif = btif_exp_srh_id(u_id);
|
|
if (p_btif == NULL) {
|
|
BTIF_ERR_FUNC("E_BTIF_INVAL_PARAM\n");
|
|
return NULL;
|
|
}
|
|
|
|
return btif_rx_thread_get(p_btif);
|
|
}
|
|
EXPORT_SYMBOL(mtk_btif_exp_rx_thread_get);
|
|
|
|
/************End of Function**********/
|