Path: blob/main/sys/dev/ath/ath_hal/ar5416/ar5416_btcoex.c
39566 views
/*-1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting4* Copyright (c) 2002-2005 Atheros Communications, Inc.5* Copyright (c) 2008-2010, Atheros Communications Inc.6*7* Permission to use, copy, modify, and/or distribute this software for any8* purpose with or without fee is hereby granted, provided that the above9* copyright notice and this permission notice appear in all copies.10*11* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES12* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF13* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR14* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES15* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN16* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF17* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.18*/1920#include "opt_ah.h"2122#include "ah.h"23#include "ah_internal.h"24#include "ah_devid.h"25#ifdef AH_DEBUG26#include "ah_desc.h" /* NB: for HAL_PHYERR* */27#endif2829#include "ar5416/ar5416.h"30#include "ar5416/ar5416reg.h"31#include "ar5416/ar5416phy.h"32#include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */33#include "ar5416/ar5416_btcoex.h"3435void36ar5416SetBTCoexInfo(struct ath_hal *ah, HAL_BT_COEX_INFO *btinfo)37{38struct ath_hal_5416 *ahp = AH5416(ah);3940ahp->ah_btModule = btinfo->bt_module;41ahp->ah_btCoexConfigType = btinfo->bt_coex_config;42ahp->ah_btActiveGpioSelect = btinfo->bt_gpio_bt_active;43ahp->ah_btPriorityGpioSelect = btinfo->bt_gpio_bt_priority;44ahp->ah_wlanActiveGpioSelect = btinfo->bt_gpio_wlan_active;45ahp->ah_btActivePolarity = btinfo->bt_active_polarity;46ahp->ah_btCoexSingleAnt = btinfo->bt_single_ant;47ahp->ah_btWlanIsolation = btinfo->bt_isolation;48}4950void51ar5416BTCoexConfig(struct ath_hal *ah, HAL_BT_COEX_CONFIG *btconf)52{53struct ath_hal_5416 *ahp = AH5416(ah);54HAL_BOOL rxClearPolarity = btconf->bt_rxclear_polarity;5556/*57* For Kiwi and Osprey, the polarity of rx_clear is active high.58* The bt_rxclear_polarity flag from ath(4) needs to be inverted.59*/60if (AR_SREV_KIWI(ah)) {61rxClearPolarity = !btconf->bt_rxclear_polarity;62}6364ahp->ah_btCoexMode = (ahp->ah_btCoexMode & AR_BT_QCU_THRESH) |65SM(btconf->bt_time_extend, AR_BT_TIME_EXTEND) |66SM(btconf->bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |67SM(btconf->bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |68SM(btconf->bt_mode, AR_BT_MODE) |69SM(btconf->bt_quiet_collision, AR_BT_QUIET) |70SM(rxClearPolarity, AR_BT_RX_CLEAR_POLARITY) |71SM(btconf->bt_priority_time, AR_BT_PRIORITY_TIME) |72SM(btconf->bt_first_slot_time, AR_BT_FIRST_SLOT_TIME);7374ahp->ah_btCoexMode2 |= SM(btconf->bt_hold_rxclear,75AR_BT_HOLD_RX_CLEAR);7677if (ahp->ah_btCoexSingleAnt == AH_FALSE) {78/* Enable ACK to go out even though BT has higher priority. */79ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT;80}81}8283void84ar5416BTCoexSetQcuThresh(struct ath_hal *ah, int qnum)85{86struct ath_hal_5416 *ahp = AH5416(ah);8788ahp->ah_btCoexMode |= SM(qnum, AR_BT_QCU_THRESH);89}9091void92ar5416BTCoexSetWeights(struct ath_hal *ah, u_int32_t stompType)93{94struct ath_hal_5416 *ahp = AH5416(ah);9596if (AR_SREV_KIWI_10_OR_LATER(ah)) {97/* TODO: TX RX separate is not enabled. */98switch (stompType) {99case HAL_BT_COEX_STOMP_AUDIO:100/* XXX TODO */101case HAL_BT_COEX_STOMP_ALL:102ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;103ahp->ah_btCoexWLANWeight = AR5416_STOMP_ALL_WLAN_WGHT;104break;105case HAL_BT_COEX_STOMP_LOW:106ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;107ahp->ah_btCoexWLANWeight = AR5416_STOMP_LOW_WLAN_WGHT;108break;109case HAL_BT_COEX_STOMP_ALL_FORCE:110ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;111ahp->ah_btCoexWLANWeight =112AR5416_STOMP_ALL_FORCE_WLAN_WGHT;113break;114case HAL_BT_COEX_STOMP_LOW_FORCE:115ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;116ahp->ah_btCoexWLANWeight =117AR5416_STOMP_LOW_FORCE_WLAN_WGHT;118break;119case HAL_BT_COEX_STOMP_NONE:120case HAL_BT_COEX_NO_STOMP:121ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;122ahp->ah_btCoexWLANWeight = AR5416_STOMP_NONE_WLAN_WGHT;123break;124default:125/* There is a forceWeight from registry */126ahp->ah_btCoexBTWeight = stompType & 0xffff;127ahp->ah_btCoexWLANWeight = stompType >> 16;128break;129}130} else {131switch (stompType) {132case HAL_BT_COEX_STOMP_AUDIO:133/* XXX TODO */134case HAL_BT_COEX_STOMP_ALL:135ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;136ahp->ah_btCoexWLANWeight = AR5416_STOMP_ALL_WLAN_WGHT;137break;138case HAL_BT_COEX_STOMP_LOW:139ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;140ahp->ah_btCoexWLANWeight = AR5416_STOMP_LOW_WLAN_WGHT;141break;142case HAL_BT_COEX_STOMP_ALL_FORCE:143ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;144ahp->ah_btCoexWLANWeight =145AR5416_STOMP_ALL_FORCE_WLAN_WGHT;146break;147case HAL_BT_COEX_STOMP_LOW_FORCE:148ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;149ahp->ah_btCoexWLANWeight =150AR5416_STOMP_LOW_FORCE_WLAN_WGHT;151break;152case HAL_BT_COEX_STOMP_NONE:153case HAL_BT_COEX_NO_STOMP:154ahp->ah_btCoexBTWeight = AR5416_BT_WGHT;155ahp->ah_btCoexWLANWeight = AR5416_STOMP_NONE_WLAN_WGHT;156break;157default:158/* There is a forceWeight from registry */159ahp->ah_btCoexBTWeight = stompType & 0xffff;160ahp->ah_btCoexWLANWeight = stompType >> 16;161break;162}163}164}165166void167ar5416BTCoexSetupBmissThresh(struct ath_hal *ah, u_int32_t thresh)168{169struct ath_hal_5416 *ahp = AH5416(ah);170171ahp->ah_btCoexMode2 |= SM(thresh, AR_BT_BCN_MISS_THRESH);172}173174/*175* There is no antenna diversity for Owl, Kiwi, etc.176*177* Kite will override this particular method.178*/179void180ar5416BTCoexAntennaDiversity(struct ath_hal *ah)181{182}183184void185ar5416BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value)186{187struct ath_hal_5416 *ahp = AH5416(ah);188189switch (type) {190case HAL_BT_COEX_SET_ACK_PWR:191if (value) {192ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_LOW_ACK_PWR;193OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER);194} else {195ahp->ah_btCoexFlag &= ~HAL_BT_COEX_FLAG_LOW_ACK_PWR;196OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER);197}198break;199case HAL_BT_COEX_ANTENNA_DIVERSITY:200/* This is overridden for Kite */201break;202#if 0203case HAL_BT_COEX_LOWER_TX_PWR:204if (value) {205if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) == 0) {206ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_LOWER_TX_PWR;207AH_PRIVATE(ah)->ah_config.ath_hal_desc_tpc = 1;208ar5416SetTxPowerLimit(ah, AH_PRIVATE(ah)->ah_power_limit, AH_PRIVATE(ah)->ah_extra_txpow, 0);209}210}211else {212if (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOWER_TX_PWR) {213ahp->ah_btCoexFlag &= ~HAL_BT_COEX_FLAG_LOWER_TX_PWR;214AH_PRIVATE(ah)->ah_config.ath_hal_desc_tpc = 0;215ar5416SetTxPowerLimit(ah, AH_PRIVATE(ah)->ah_power_limit, AH_PRIVATE(ah)->ah_extra_txpow, 0);216}217}218break;219#endif220default:221break;222}223}224225void226ar5416BTCoexDisable(struct ath_hal *ah)227{228struct ath_hal_5416 *ahp = AH5416(ah);229230/* Always drive rx_clear_external output as 0 */231ar5416GpioSet(ah, ahp->ah_wlanActiveGpioSelect, 0);232ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect,233HAL_GPIO_OUTPUT_MUX_AS_OUTPUT);234235if (AR_SREV_9271(ah)) {236/*237* Set wlanActiveGpio to input when disabling BT-COEX to238* reduce power consumption239*/240ar5416GpioCfgInput(ah, ahp->ah_wlanActiveGpioSelect);241}242243if (ahp->ah_btCoexSingleAnt == AH_TRUE) {244OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE,2451);246OS_REG_RMW_FIELD(ah, AR_MISC_MODE, AR_PCU_BT_ANT_PREVENT_RX,2470);248}249250OS_REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);251OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0);252if (AR_SREV_KIWI_10_OR_LATER(ah))253OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT2, 0);254OS_REG_WRITE(ah, AR_BT_COEX_MODE2, 0);255256ahp->ah_btCoexEnabled = AH_FALSE;257}258259int260ar5416BTCoexEnable(struct ath_hal *ah)261{262struct ath_hal_5416 *ahp = AH5416(ah);263264/* Program coex mode and weight registers to actually enable coex */265OS_REG_WRITE(ah, AR_BT_COEX_MODE, ahp->ah_btCoexMode);266OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT,267SM(ahp->ah_btCoexWLANWeight & 0xFFFF, AR_BT_WL_WGHT) |268SM(ahp->ah_btCoexBTWeight & 0xFFFF, AR_BT_BT_WGHT));269if (AR_SREV_KIWI_10_OR_LATER(ah)) {270OS_REG_WRITE(ah, AR_BT_COEX_WEIGHT2,271SM(ahp->ah_btCoexWLANWeight >> 16, AR_BT_WL_WGHT));272}273OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);274275/* Added Select GPIO5~8 instaed SPI */276if (AR_SREV_9271(ah)) {277uint32_t val;278279val = OS_REG_READ(ah, AR9271_CLOCK_CONTROL);280val &= 0xFFFFFEFF;281OS_REG_WRITE(ah, AR9271_CLOCK_CONTROL, val);282}283284if (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_LOW_ACK_PWR)285OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_LOW_ACK_POWER);286else287OS_REG_WRITE(ah, AR_TPC, HAL_BT_COEX_HIGH_ACK_POWER);288289if (ahp->ah_btCoexSingleAnt == AH_TRUE) {290OS_REG_RMW_FIELD(ah, AR_QUIET1,291AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);292/* XXX should update miscMode? */293OS_REG_RMW_FIELD(ah, AR_MISC_MODE,294AR_PCU_BT_ANT_PREVENT_RX, 1);295} else {296OS_REG_RMW_FIELD(ah, AR_QUIET1,297AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);298/* XXX should update miscMode? */299OS_REG_RMW_FIELD(ah, AR_MISC_MODE,300AR_PCU_BT_ANT_PREVENT_RX, 0);301}302303if (ahp->ah_btCoexConfigType == HAL_BT_COEX_CFG_3WIRE) {304/* For 3-wire, configure the desired GPIO port for rx_clear */305ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect,306HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE);307} else {308/*309* For 2-wire, configure the desired GPIO port310* for TX_FRAME output311*/312ar5416GpioCfgOutput(ah, ahp->ah_wlanActiveGpioSelect,313HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME);314}315316/*317* Enable a weak pull down on BT_ACTIVE.318* When BT device is disabled, BT_ACTIVE might be floating.319*/320OS_REG_RMW(ah, AR_GPIO_PDPU,321(0x2 << (ahp->ah_btActiveGpioSelect * 2)),322(0x3 << (ahp->ah_btActiveGpioSelect * 2)));323324ahp->ah_btCoexEnabled = AH_TRUE;325326return (0);327}328329void330ar5416InitBTCoex(struct ath_hal *ah)331{332struct ath_hal_5416 *ahp = AH5416(ah);333334HALDEBUG(ah, HAL_DEBUG_BT_COEX,335"%s: called; configType=%d\n",336__func__,337ahp->ah_btCoexConfigType);338339if (ahp->ah_btCoexConfigType == HAL_BT_COEX_CFG_3WIRE) {340OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,341(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |342AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB));343344/*345* Set input mux for bt_prority_async and346* bt_active_async to GPIO pins347*/348OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,349AR_GPIO_INPUT_MUX1_BT_ACTIVE,350ahp->ah_btActiveGpioSelect);351OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,352AR_GPIO_INPUT_MUX1_BT_PRIORITY,353ahp->ah_btPriorityGpioSelect);354355/*356* Configure the desired GPIO ports for input357*/358ar5416GpioCfgInput(ah, ahp->ah_btActiveGpioSelect);359ar5416GpioCfgInput(ah, ahp->ah_btPriorityGpioSelect);360361/*362* Configure the antenna diversity setup.363* It's a no-op for AR9287; AR9285 overrides this364* as required.365*/366AH5416(ah)->ah_btCoexSetDiversity(ah);367368if (ahp->ah_btCoexEnabled)369ar5416BTCoexEnable(ah);370else371ar5416BTCoexDisable(ah);372} else if (ahp->ah_btCoexConfigType != HAL_BT_COEX_CFG_NONE) {373/* 2-wire */374if (ahp->ah_btCoexEnabled) {375/* Connect bt_active_async to baseband */376OS_REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,377(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |378AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF));379OS_REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,380AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);381382/*383* Set input mux for bt_prority_async and384* bt_active_async to GPIO pins385*/386OS_REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,387AR_GPIO_INPUT_MUX1_BT_ACTIVE,388ahp->ah_btActiveGpioSelect);389390/* Configure the desired GPIO ports for input */391ar5416GpioCfgInput(ah, ahp->ah_btActiveGpioSelect);392393/* Enable coexistence on initialization */394ar5416BTCoexEnable(ah);395}396}397}398399400