1 /* 2 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 3 * Copyright (c) 2002-2005 Atheros Communications, Inc. 4 * Copyright (c) 2008-2010, Atheros Communications Inc. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $FreeBSD$ 19 */ 20 21 #include "opt_ah.h" 22 23 #include "ah.h" 24 #include "ah_internal.h" 25 #include "ah_devid.h" 26 #ifdef AH_DEBUG 27 #include "ah_desc.h" /* NB: for HAL_PHYERR* */ 28 #endif 29 30 #include "ar5416/ar5416.h" 31 #include "ar5416/ar5416reg.h" 32 #include "ar5416/ar5416phy.h" 33 #include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */ 34 35 #include "ar9002/ar9285phy.h" 36 #include "ar9002/ar9285.h" 37 38 /* 39 * This is specific to Kite. 40 * 41 * Kiwi and others don't have antenna diversity like this. 42 */ 43 void 44 ar9285BTCoexAntennaDiversity(struct ath_hal *ah) 45 { 46 struct ath_hal_5416 *ahp = AH5416(ah); 47 u_int32_t regVal; 48 u_int8_t ant_div_control1, ant_div_control2; 49 50 HALDEBUG(ah, HAL_DEBUG_BT_COEX, 51 "%s: btCoexFlag: ALLOW=%d, ENABLE=%d\n", 52 __func__, 53 !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW), 54 !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE)); 55 56 /* NOTE: disparate enum comparison must be cast */ 57 if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) || 58 ((int)AH5212(ah)->ah_diversity != HAL_ANT_VARIABLE)) { 59 if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE) && 60 (AH5212(ah)->ah_antControl == HAL_ANT_VARIABLE)) { 61 /* Enable antenna diversity */ 62 ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE; 63 ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE; 64 65 /* Don't disable BT ant to allow BB to control SWCOM */ 66 ahp->ah_btCoexMode2 &= (~(AR_BT_DISABLE_BT_ANT)); 67 OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 68 69 /* Program the correct SWCOM table */ 70 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 71 HAL_BT_COEX_ANT_DIV_SWITCH_COM); 72 OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); 73 } else if (AH5212(ah)->ah_antControl == HAL_ANT_FIXED_B) { 74 /* Disable antenna diversity. Use antenna B(LNA2) only. */ 75 ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B; 76 ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B; 77 78 /* Disable BT ant to allow concurrent BT and WLAN receive */ 79 ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; 80 OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 81 82 /* 83 * Program SWCOM table to make sure RF switch always parks 84 * at WLAN side 85 */ 86 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 87 HAL_BT_COEX_ANT_DIV_SWITCH_COM); 88 OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0x60000000, 0xf0000000); 89 } else { 90 /* Disable antenna diversity. Use antenna A(LNA1) only */ 91 ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A; 92 ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A; 93 94 /* Disable BT ant to allow concurrent BT and WLAN receive */ 95 ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; 96 OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 97 98 /* 99 * Program SWCOM table to make sure RF switch always 100 * parks at BT side 101 */ 102 OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0); 103 OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); 104 } 105 106 regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); 107 regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); 108 /* 109 * Clear ant_fast_div_bias [14:9] since for Janus the main LNA is 110 * always LNA1. 111 */ 112 regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); 113 114 regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); 115 regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); 116 regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); 117 regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); 118 regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); 119 OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); 120 121 regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 122 regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); 123 regVal |= SM((ant_div_control1 >> 3), 124 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); 125 OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); 126 } 127 } 128 129 void 130 ar9285BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value) 131 { 132 struct ath_hal_5416 *ahp = AH5416(ah); 133 134 switch (type) { 135 case HAL_BT_COEX_ANTENNA_DIVERSITY: 136 if (AR_SREV_KITE(ah)) { 137 ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW; 138 if (value) 139 ahp->ah_btCoexFlag |= 140 HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; 141 else 142 ahp->ah_btCoexFlag &= 143 ~HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; 144 ar9285BTCoexAntennaDiversity(ah); 145 } 146 break; 147 default: 148 ar5416BTCoexSetParameter(ah, type, value); 149 break; 150 } 151 } 152 153 154