| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359 |
- #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"
- #define BTIF_USER_ID "btif_driver"
- static spinlock_t g_clk_cg_spinlock; /*BTIF clock's spinlock */
- /*-----------------------------BTIF Module Clock and Power Control Defination------------------*/
- 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*/
- MTK_BTIF_INFO_STR mtk_btif = {
- #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(P_MTK_BTIF_INFO_STR p_btif);
- #endif
- static int btif_rx_irq_handler(P_MTK_BTIF_INFO_STR p_btif_info,
- unsigned char *p_buf,
- const unsigned int max_len);
- static int btif_tx_irq_handler(P_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(P_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(P_MTK_BTIF_INFO_STR p_btif, bool en);
- #ifndef MTK_BTIF_MARK_UNUSED_API
- static int btif_sleep_ctrl(P_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(P_MTK_BTIF_INFO_STR p_btif,
- unsigned char *p_buf, const unsigned int max_len);
- static int btif_tx_thr_set(P_MTK_BTIF_INFO_STR p_btif, unsigned int thr_count);
- #endif
- static int btif_dump_array(char *string, char *p_buf, int len)
- {
- unsigned int idx = 0;
- pr_debug("========dump %s start <length:%d>========\n", string, len);
- for (idx = 0; idx < len; idx++, p_buf++) {
- pr_debug("%02x ", *p_buf);
- if (3 == (idx % 4))
- pr_debug("\n");
- }
- pr_debug("\n");
- pr_debug("========dump %s end========\n", string);
- return 0;
- }
- #if NEW_TX_HANDLING_SUPPORT
- static int _btif_tx_fifo_init(P_MTK_BTIF_INFO_STR p_btif_info)
- {
- int i_ret = -1;
- spin_lock_init(&(p_btif_info->tx_fifo_spinlock));
- if (NULL == p_btif_info->p_tx_fifo) {
- p_btif_info->p_tx_fifo = kzalloc(sizeof(struct kfifo),
- GFP_ATOMIC);
- if (NULL == p_btif_info->p_tx_fifo) {
- 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 (0 != i_ret) {
- BTIF_ERR_FUNC("kfifo_alloc failed, errno(%d)\n", i_ret);
- i_ret = -ENOMEM;
- goto ret;
- }
- i_ret = 0;
- } else {
- BTIF_WARN_FUNC
- ("p_btif_info->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(P_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 (NULL == p_btif_info->p_tx_fifo)
- 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(P_MTK_BTIF_INFO_STR p_btif_info)
- {
- int i_ret = 0;
- if (NULL != p_btif_info->p_tx_fifo)
- 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[3] = {0, 0, 0};
- unsigned int phy_base;
- node = of_find_compatible_node(NULL, NULL, "mediatek,btif");
- if (node) {
- mtk_btif.p_irq->irq_id = irq_of_parse_and_map(node, 0);
- /*fixme, be compitable arch 64bits*/
- mtk_btif.base = (unsigned long)of_iomap(node, 0);
- BTIF_INFO_FUNC("get btif irq(%d),register base(0x%lx)\n",
- mtk_btif.p_irq->irq_id, mtk_btif.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.p_irq->irq_flags = irq_info[2];
- BTIF_INFO_FUNC("get interrupt flag(0x%x)\n", mtk_btif.p_irq->irq_flags);
- }
- if (of_property_read_u32_index(node, "reg", 0, &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
- *****************************************************************************/
- P_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);
- if (0 == i_ret)
- 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;
- }
- /*****************************************************************************
- * 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]cannot 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 (0 != i_ret) {
- BTIF_ERR_FUNC("clk_prepare clk_btif failed! ret:%d\n", i_ret);
- return i_ret;
- }
- i_ret = clk_prepare(clk_btif_apdma);
- if (0 != i_ret) {
- BTIF_ERR_FUNC("clk_prepare clk_btif_apdma 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(P_MTK_BTIF_INFO_STR p_btif, 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_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 (CLK_OUT_ENABLE == flag) {
- if (1 == atomic_inc_return(&s_clk_ref)) {
- #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 for MTK_BTIF_CG_BIT failed, ret:%d",
- i_ret);
- }
- }
- } else if (CLK_OUT_DISABLE == flag) {
- if (0 == atomic_dec_return(&s_clk_ref)) {
- #if defined(CONFIG_MTK_CLKMGR)
- i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID);
- if (i_ret) {
- BTIF_WARN_FUNC
- ("disable_clock for MTK_BTIF_CG_BIT 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 (CLK_OUT_ENABLE == flag) {
- #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 = (0 == i_ret) ? flag : status;
- if (i_ret) {
- BTIF_WARN_FUNC
- ("enable_clock for MTK_BTIF_CG_BIT failed, ret:%d",
- i_ret);
- }
- } else if (CLK_OUT_DISABLE == flag) {
- #if defined(CONFIG_MTK_CLKMGR)
- i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID);
- status = (0 == i_ret) ? flag : status;
- if (i_ret) {
- BTIF_WARN_FUNC
- ("disable_clock for MTK_BTIF_CG_BIT 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 (0 == i_ret) {
- BTIF_DBG_FUNC("btif clock %s\n",
- CLK_OUT_ENABLE == flag ? "enabled" : "disabled");
- } else {
- BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n",
- CLK_OUT_ENABLE == flag ? "enable" : "disable",
- i_ret);
- }
- #else
- if (0 == i_ret) {
- BTIF_DBG_FUNC("btif clock %s\n",
- CLK_OUT_ENABLE == flag ? "enabled" : "disabled");
- } else {
- BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n",
- CLK_OUT_ENABLE == flag ? "enable" : "disable",
- i_ret);
- }
- #endif
- #if defined(CONFIG_MTK_CLKMGR)
- BTIF_DBG_FUNC("BTIF's clock is %s\n",
- (0 == clock_is_on(MTK_BTIF_CG_BIT)) ? "off" : "on");
- #endif
- return i_ret;
- }
- static int btif_new_handshake_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool enable)
- {
- unsigned long base = p_btif->base;
- if (true == enable)
- 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(P_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(P_MTK_BTIF_INFO_STR p_btif, bool en)
- {
- int i_ret = -1;
- unsigned long base = p_btif->base;
- if (false == en)
- 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(P_MTK_BTIF_INFO_STR p_btif, bool en)
- {
- int i_ret = -1;
- unsigned long base = p_btif->base;
- if (false == en)
- 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(P_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 ((NULL == p_buf) || (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(P_MTK_BTIF_INFO_STR p_btif, bool en)
- {
- int i_ret = -1;
- unsigned long base = p_btif->base;
- if (false == en)
- 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(P_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(P_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(P_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(P_MTK_BTIF_INFO_STR p_btif, bool en)
- {
- int i_ret = -1;
- unsigned long base = p_btif->base;
- if (false == en)
- 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(P_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;
- #if 0
- /*check parameter valid or not*/
- if ((NULL == p_buf) || (max_len == 0)) {
- i_ret = ERR_INVALID_PAR;
- return i_ret;
- }
- #endif
- unsigned long irq_flag = 0;
- spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);
- #if defined(CONFIG_MTK_CLKMGR)
- if (0 == clock_is_on(MTK_BTIF_CG_BIT)) {
- 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));
- /*is rx interrupt exist?*/
- #if 0
- while ((iir & BTIF_IIR_RX) && (rx_len < max_len)) {
- rx_len +=
- btif_rx_irq_handler(p_btif, (p_buf + rx_len),
- (max_len - rx_len));
- /*update IIR*/
- iir = BTIF_READ32(BTIF_IIR(base));
- }
- #endif
- 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(P_MTK_BTIF_INFO_STR p_btif_info, btif_rx_buf_write rx_cb)
- {
- if (NULL != p_btif_info->rx_cb)
- BTIF_DBG_FUNC("rx_cb 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(P_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(P_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, which means 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, which means we can write (Tx FIFO count - Tx threshold)to BTIF*/
- ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE;
- else {
- /*this means 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(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode)
- {
- int i_ret = -1;
- unsigned long base = p_btif->base;
- if (BTIF_MODE_DMA == mode)
- /*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(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode)
- {
- int i_ret = -1;
- unsigned long base = p_btif->base;
- if (BTIF_MODE_DMA == mode)
- /*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(P_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 ((NULL == p_buf) || (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 (0 < sent_len) {
- 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();
- /*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, which means 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, which means we can write (Tx FIFO count - Tx threshold)to BTIF*/
- ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE;
- else {
- /*this means 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(P_MTK_BTIF_INFO_STR p_btif)
- {
- int i_ret = -1;
- unsigned long base = p_btif->base;
- #if defined(CONFIG_MTK_CLKMGR)
- if (0 == clock_is_on(MTK_BTIF_CG_BIT)) {
- 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(64, 96);
- /*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(P_MTK_BTIF_INFO_STR p_btif, 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 (0 == clock_is_on(MTK_BTIF_CG_BIT)) {
- /*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));
- /*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));
- /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/
- BTIF_INFO_FUNC("BTIF's clock is on\n");
- BTIF_INFO_FUNC("base address: 0x%lx\n", base);
- switch (flag) {
- case REG_BTIF_ALL:
- #if 0
- BTIF_INFO_FUNC("BTIF_IER:0x%x\n", BTIF_READ32(BTIF_IER(base)));
- BTIF_INFO_FUNC("BTIF_IIR:0x%x\n", BTIF_READ32(BTIF_IIR(base)));
- BTIF_INFO_FUNC("BTIF_FAKELCR:0x%x\n",
- BTIF_READ32(BTIF_FAKELCR(base)));
- BTIF_INFO_FUNC("BTIF_LSR:0x%x\n", BTIF_READ32(BTIF_LSR(base)));
- BTIF_INFO_FUNC("BTIF_SLEEP_EN:0x%x\n",
- BTIF_READ32(BTIF_SLEEP_EN(base)));
- BTIF_INFO_FUNC("BTIF_DMA_EN:0x%x\n",
- BTIF_READ32(BTIF_DMA_EN(base)));
- BTIF_INFO_FUNC("BTIF_RTOCNT:0x%x\n",
- BTIF_READ32(BTIF_RTOCNT(base)));
- BTIF_INFO_FUNC("BTIF_TRI_LVL:0x%x\n",
- BTIF_READ32(BTIF_TRI_LVL(base)));
- BTIF_INFO_FUNC("BTIF_WAT_TIME:0x%x\n",
- BTIF_READ32(BTIF_WAT_TIME(base)));
- BTIF_INFO_FUNC("BTIF_HANDSHAKE:0x%x\n",
- BTIF_READ32(BTIF_HANDSHAKE(base)));
- #endif
- btif_dump_array("BTIF register", reg_map, sizeof(reg_map));
- break;
- default:
- break;
- }
- BTIF_INFO_FUNC("Tx DMA %s\n",
- (dma_en & BTIF_DMA_EN_TX) ? "enabled" : "disabled");
- BTIF_INFO_FUNC("Rx DMA %s\n",
- (dma_en & BTIF_DMA_EN_RX) ? "enabled" : "disabled");
- BTIF_INFO_FUNC("Rx data is %s\n",
- (lsr & BTIF_LSR_DR_BIT) ? "not empty" : "empty");
- BTIF_INFO_FUNC("Tx data is %s\n",
- (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(P_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 && (0 == tx_irq_disable) && (0 == rx_dr)) ? 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(P_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(P_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(P_MTK_BTIF_INFO_STR p_btif_info, 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;
- P_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 (IRQ_EDGE_FALL == p_irq->edge_type)
- flag = IRQF_TRIGGER_FALLING;
- else if (IRQ_EDGE_RAISE == p_irq->edge_type)
- flag = IRQF_TRIGGER_RISING;
- else if (IRQ_EDGE_BOTH == p_irq->edge_type)
- flag = IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING;
- else
- flag = IRQF_TRIGGER_FALLING; /*make this as default type */
- break;
- case IRQ_SENS_LVL:
- if (IRQ_LVL_LOW == p_irq->lvl_type)
- flag = IRQF_TRIGGER_LOW;
- else if (IRQ_LVL_HIGH == p_irq->lvl_type)
- flag = IRQF_TRIGGER_HIGH;
- else
- flag = IRQF_TRIGGER_LOW; /*make this as default type */
- break;
- default:
- flag = IRQF_TRIGGER_LOW; /*make this as default type */
- 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;
- }
|