ar9285_btcoex.c revision 272461
1139825Simp/* 2103620Sgrehan * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 3103620Sgrehan * Copyright (c) 2002-2005 Atheros Communications, Inc. 4103620Sgrehan * Copyright (c) 2008-2010, Atheros Communications Inc. 5103620Sgrehan * 6103620Sgrehan * Permission to use, copy, modify, and/or distribute this software for any 7103620Sgrehan * purpose with or without fee is hereby granted, provided that the above 8103620Sgrehan * copyright notice and this permission notice appear in all copies. 9103620Sgrehan * 10103620Sgrehan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11103620Sgrehan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12103620Sgrehan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13103620Sgrehan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14103620Sgrehan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15103620Sgrehan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16103620Sgrehan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17103620Sgrehan * 18103620Sgrehan * $FreeBSD: releng/10.1/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c 251483 2013-06-07 05:17:58Z adrian $ 19103620Sgrehan */ 20103620Sgrehan 21103620Sgrehan#include "opt_ah.h" 22103620Sgrehan 23103620Sgrehan#include "ah.h" 24103620Sgrehan#include "ah_internal.h" 25103620Sgrehan#include "ah_devid.h" 26103620Sgrehan#ifdef AH_DEBUG 27103620Sgrehan#include "ah_desc.h" /* NB: for HAL_PHYERR* */ 28103620Sgrehan#endif 29103620Sgrehan 30103620Sgrehan#include "ar5416/ar5416.h" 31103620Sgrehan#include "ar5416/ar5416reg.h" 32103620Sgrehan#include "ar5416/ar5416phy.h" 33103620Sgrehan#include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */ 34103620Sgrehan 35103620Sgrehan#include "ar9002/ar9285phy.h" 36103620Sgrehan#include "ar9002/ar9285.h" 37103620Sgrehan 38103620Sgrehan/* 39103620Sgrehan * This is specific to Kite. 40103620Sgrehan * 41103620Sgrehan * Kiwi and others don't have antenna diversity like this. 42103620Sgrehan */ 43103620Sgrehanvoid 44103620Sgrehanar9285BTCoexAntennaDiversity(struct ath_hal *ah) 45103620Sgrehan{ 46103620Sgrehan struct ath_hal_5416 *ahp = AH5416(ah); 47103620Sgrehan u_int32_t regVal; 48103620Sgrehan u_int8_t ant_div_control1, ant_div_control2; 49103620Sgrehan 50160722Smarcel HALDEBUG(ah, HAL_DEBUG_BT_COEX, 51160722Smarcel "%s: btCoexFlag: ALLOW=%d, ENABLE=%d\n", 52103620Sgrehan __func__, 53160722Smarcel !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW), 54103620Sgrehan !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE)); 55160722Smarcel 56103620Sgrehan if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) || 57160722Smarcel (AH5212(ah)->ah_diversity != HAL_ANT_VARIABLE)) { 58160722Smarcel if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE) && 59160722Smarcel (AH5212(ah)->ah_antControl == HAL_ANT_VARIABLE)) { 60103620Sgrehan /* Enable antenna diversity */ 61103620Sgrehan ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE; 62103620Sgrehan ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE; 63103620Sgrehan 64160722Smarcel /* Don't disable BT ant to allow BB to control SWCOM */ 65160722Smarcel ahp->ah_btCoexMode2 &= (~(AR_BT_DISABLE_BT_ANT)); 66160722Smarcel OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 67160722Smarcel 68103620Sgrehan /* Program the correct SWCOM table */ 69103620Sgrehan OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 70103620Sgrehan HAL_BT_COEX_ANT_DIV_SWITCH_COM); 71160722Smarcel OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); 72103620Sgrehan } else if (AH5212(ah)->ah_antControl == HAL_ANT_FIXED_B) { 73160722Smarcel /* Disable antenna diversity. Use antenna B(LNA2) only. */ 74160722Smarcel ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B; 75103620Sgrehan ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B; 76160722Smarcel 77103620Sgrehan /* Disable BT ant to allow concurrent BT and WLAN receive */ 78103620Sgrehan ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; 79103620Sgrehan OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 80160722Smarcel 81160722Smarcel /* 82103620Sgrehan * Program SWCOM table to make sure RF switch always parks 83103620Sgrehan * at WLAN side 84160722Smarcel */ 85103620Sgrehan OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 86103620Sgrehan HAL_BT_COEX_ANT_DIV_SWITCH_COM); 87160722Smarcel OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0x60000000, 0xf0000000); 88 } else { 89 /* Disable antenna diversity. Use antenna A(LNA1) only */ 90 ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A; 91 ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A; 92 93 /* Disable BT ant to allow concurrent BT and WLAN receive */ 94 ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; 95 OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 96 97 /* 98 * Program SWCOM table to make sure RF switch always 99 * parks at BT side 100 */ 101 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0); 102 OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); 103 } 104 105 regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); 106 regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); 107 /* 108 * Clear ant_fast_div_bias [14:9] since for Janus the main LNA is 109 * always LNA1. 110 */ 111 regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); 112 113 regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); 114 regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); 115 regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); 116 regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); 117 regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); 118 OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); 119 120 regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 121 regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); 122 regVal |= SM((ant_div_control1 >> 3), 123 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); 124 OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); 125 } 126} 127 128void 129ar9285BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value) 130{ 131 struct ath_hal_5416 *ahp = AH5416(ah); 132 133 switch (type) { 134 case HAL_BT_COEX_ANTENNA_DIVERSITY: 135 if (AR_SREV_KITE(ah)) { 136 ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW; 137 if (value) 138 ahp->ah_btCoexFlag |= 139 HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; 140 else 141 ahp->ah_btCoexFlag &= 142 ~HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; 143 ar9285BTCoexAntennaDiversity(ah); 144 } 145 break; 146 default: 147 ar5416BTCoexSetParameter(ah, type, value); 148 break; 149 } 150} 151 152 153