xref: /freebsd/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c (revision 36d486cc2ecdb9c290dba65bd5668b7e50d0d822)
16e778a7eSPedro F. Giffuni /*-
26e778a7eSPedro F. Giffuni  * SPDX-License-Identifier: ISC
36e778a7eSPedro F. Giffuni  *
46479ef78SAdrian Chadd  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
56479ef78SAdrian Chadd  * Copyright (c) 2002-2005 Atheros Communications, Inc.
66479ef78SAdrian Chadd  * Copyright (c) 2008-2010, Atheros Communications Inc.
76479ef78SAdrian Chadd  *
86479ef78SAdrian Chadd  * Permission to use, copy, modify, and/or distribute this software for any
96479ef78SAdrian Chadd  * purpose with or without fee is hereby granted, provided that the above
106479ef78SAdrian Chadd  * copyright notice and this permission notice appear in all copies.
116479ef78SAdrian Chadd  *
126479ef78SAdrian Chadd  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
136479ef78SAdrian Chadd  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
146479ef78SAdrian Chadd  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
156479ef78SAdrian Chadd  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
166479ef78SAdrian Chadd  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
176479ef78SAdrian Chadd  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
186479ef78SAdrian Chadd  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
196479ef78SAdrian Chadd  */
206479ef78SAdrian Chadd 
216479ef78SAdrian Chadd #include "opt_ah.h"
226479ef78SAdrian Chadd 
236479ef78SAdrian Chadd #include "ah.h"
246479ef78SAdrian Chadd #include "ah_internal.h"
256479ef78SAdrian Chadd #include "ah_devid.h"
266479ef78SAdrian Chadd #ifdef AH_DEBUG
276479ef78SAdrian Chadd #include "ah_desc.h"		    /* NB: for HAL_PHYERR* */
286479ef78SAdrian Chadd #endif
296479ef78SAdrian Chadd 
306479ef78SAdrian Chadd #include "ar5416/ar5416.h"
316479ef78SAdrian Chadd #include "ar5416/ar5416reg.h"
326479ef78SAdrian Chadd #include "ar5416/ar5416phy.h"
336479ef78SAdrian Chadd #include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */
346479ef78SAdrian Chadd 
356479ef78SAdrian Chadd #include "ar9002/ar9285phy.h"
366479ef78SAdrian Chadd #include "ar9002/ar9285.h"
376479ef78SAdrian Chadd 
386479ef78SAdrian Chadd /*
396479ef78SAdrian Chadd  * This is specific to Kite.
406479ef78SAdrian Chadd  *
416479ef78SAdrian Chadd  * Kiwi and others don't have antenna diversity like this.
426479ef78SAdrian Chadd  */
436479ef78SAdrian Chadd void
ar9285BTCoexAntennaDiversity(struct ath_hal * ah)446479ef78SAdrian Chadd ar9285BTCoexAntennaDiversity(struct ath_hal *ah)
456479ef78SAdrian Chadd {
466479ef78SAdrian Chadd 	struct ath_hal_5416 *ahp = AH5416(ah);
476479ef78SAdrian Chadd 	u_int32_t regVal;
486479ef78SAdrian Chadd 	u_int8_t ant_div_control1, ant_div_control2;
496479ef78SAdrian Chadd 
500c20aadbSAdrian Chadd 	HALDEBUG(ah, HAL_DEBUG_BT_COEX,
510c20aadbSAdrian Chadd 	    "%s: btCoexFlag: ALLOW=%d, ENABLE=%d\n",
520c20aadbSAdrian Chadd 	    __func__,
530c20aadbSAdrian Chadd 	    !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW),
540c20aadbSAdrian Chadd 	    !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE));
550c20aadbSAdrian Chadd 
566479ef78SAdrian Chadd 	if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) ||
57*36d486ccSDimitry Andric 	    (AH5212(ah)->ah_diversity == AH_TRUE)) {
586479ef78SAdrian Chadd 	if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE) &&
590639c54aSAdrian Chadd 	     (AH5212(ah)->ah_antControl == HAL_ANT_VARIABLE)) {
606479ef78SAdrian Chadd 		/* Enable antenna diversity */
616479ef78SAdrian Chadd 		ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE;
626479ef78SAdrian Chadd 		ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE;
636479ef78SAdrian Chadd 
646479ef78SAdrian Chadd 		/* Don't disable BT ant to allow BB to control SWCOM */
656479ef78SAdrian Chadd 		ahp->ah_btCoexMode2 &= (~(AR_BT_DISABLE_BT_ANT));
666479ef78SAdrian Chadd 		OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);
676479ef78SAdrian Chadd 
686479ef78SAdrian Chadd 		/* Program the correct SWCOM table */
696479ef78SAdrian Chadd 		OS_REG_WRITE(ah, AR_PHY_SWITCH_COM,
706479ef78SAdrian Chadd 		    HAL_BT_COEX_ANT_DIV_SWITCH_COM);
716479ef78SAdrian Chadd 		OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
720639c54aSAdrian Chadd 	} else if (AH5212(ah)->ah_antControl == HAL_ANT_FIXED_B) {
736479ef78SAdrian Chadd 		/* Disable antenna diversity. Use antenna B(LNA2) only. */
746479ef78SAdrian Chadd 		ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B;
756479ef78SAdrian Chadd 		ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B;
766479ef78SAdrian Chadd 
776479ef78SAdrian Chadd 		/* Disable BT ant to allow concurrent BT and WLAN receive */
786479ef78SAdrian Chadd 		ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT;
796479ef78SAdrian Chadd 		OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);
806479ef78SAdrian Chadd 
8187a85d8aSAdrian Chadd 		/*
8287a85d8aSAdrian Chadd 		 * Program SWCOM table to make sure RF switch always parks
8387a85d8aSAdrian Chadd 		 * at WLAN side
8487a85d8aSAdrian Chadd 		 */
8587a85d8aSAdrian Chadd 		OS_REG_WRITE(ah, AR_PHY_SWITCH_COM,
8687a85d8aSAdrian Chadd 		    HAL_BT_COEX_ANT_DIV_SWITCH_COM);
876479ef78SAdrian Chadd 		OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0x60000000, 0xf0000000);
886479ef78SAdrian Chadd 	} else {
896479ef78SAdrian Chadd 		/* Disable antenna diversity. Use antenna A(LNA1) only */
906479ef78SAdrian Chadd 		ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A;
916479ef78SAdrian Chadd 		ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A;
926479ef78SAdrian Chadd 
936479ef78SAdrian Chadd 		/* Disable BT ant to allow concurrent BT and WLAN receive */
946479ef78SAdrian Chadd 		ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT;
956479ef78SAdrian Chadd 		OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);
966479ef78SAdrian Chadd 
9787a85d8aSAdrian Chadd 		/*
9887a85d8aSAdrian Chadd 		 * Program SWCOM table to make sure RF switch always
9987a85d8aSAdrian Chadd 		 * parks at BT side
10087a85d8aSAdrian Chadd 		 */
1016479ef78SAdrian Chadd 		OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0);
1026479ef78SAdrian Chadd 		OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
1036479ef78SAdrian Chadd 	}
1046479ef78SAdrian Chadd 
1056479ef78SAdrian Chadd 	regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
1066479ef78SAdrian Chadd 	regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
10787a85d8aSAdrian Chadd 	/*
10887a85d8aSAdrian Chadd 	 * Clear ant_fast_div_bias [14:9] since for Janus the main LNA is
10987a85d8aSAdrian Chadd 	 * always LNA1.
11087a85d8aSAdrian Chadd 	 */
1116479ef78SAdrian Chadd 	regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS));
1126479ef78SAdrian Chadd 
1136479ef78SAdrian Chadd 	regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL);
1146479ef78SAdrian Chadd 	regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF);
1156479ef78SAdrian Chadd 	regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
1166479ef78SAdrian Chadd 	regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB);
1176479ef78SAdrian Chadd 	regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
1186479ef78SAdrian Chadd 	OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
1196479ef78SAdrian Chadd 
1206479ef78SAdrian Chadd 	regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
1216479ef78SAdrian Chadd 	regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
12287a85d8aSAdrian Chadd 	regVal |= SM((ant_div_control1 >> 3),
12387a85d8aSAdrian Chadd 	    AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
1246479ef78SAdrian Chadd 	OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
1256479ef78SAdrian Chadd     }
1266479ef78SAdrian Chadd }
1276479ef78SAdrian Chadd 
1286479ef78SAdrian Chadd void
ar9285BTCoexSetParameter(struct ath_hal * ah,u_int32_t type,u_int32_t value)1296479ef78SAdrian Chadd ar9285BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value)
1306479ef78SAdrian Chadd {
1316479ef78SAdrian Chadd 	struct ath_hal_5416 *ahp = AH5416(ah);
1326479ef78SAdrian Chadd 
1336479ef78SAdrian Chadd 	switch (type) {
1346479ef78SAdrian Chadd 	case HAL_BT_COEX_ANTENNA_DIVERSITY:
1356479ef78SAdrian Chadd 		if (AR_SREV_KITE(ah)) {
1366479ef78SAdrian Chadd 			ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW;
1376479ef78SAdrian Chadd 			if (value)
1386479ef78SAdrian Chadd 				ahp->ah_btCoexFlag |=
1396479ef78SAdrian Chadd 				    HAL_BT_COEX_FLAG_ANT_DIV_ENABLE;
1406479ef78SAdrian Chadd 			else
1416479ef78SAdrian Chadd 				ahp->ah_btCoexFlag &=
1426479ef78SAdrian Chadd 				    ~HAL_BT_COEX_FLAG_ANT_DIV_ENABLE;
1436479ef78SAdrian Chadd 			ar9285BTCoexAntennaDiversity(ah);
1446479ef78SAdrian Chadd 		}
1456479ef78SAdrian Chadd 		break;
1466479ef78SAdrian Chadd 	default:
1476479ef78SAdrian Chadd 		ar5416BTCoexSetParameter(ah, type, value);
1486479ef78SAdrian Chadd 		break;
1496479ef78SAdrian Chadd 	}
1506479ef78SAdrian Chadd }
151