1237611Sadrian/* 2237611Sadrian * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 3237611Sadrian * Copyright (c) 2002-2005 Atheros Communications, Inc. 4237611Sadrian * Copyright (c) 2008-2010, Atheros Communications Inc. 5237611Sadrian * 6237611Sadrian * Permission to use, copy, modify, and/or distribute this software for any 7237611Sadrian * purpose with or without fee is hereby granted, provided that the above 8237611Sadrian * copyright notice and this permission notice appear in all copies. 9237611Sadrian * 10237611Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11237611Sadrian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12237611Sadrian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13237611Sadrian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14237611Sadrian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15237611Sadrian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16237611Sadrian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17237611Sadrian * 18237611Sadrian * $FreeBSD$ 19237611Sadrian */ 20237611Sadrian 21237611Sadrian#include "opt_ah.h" 22237611Sadrian 23237611Sadrian#include "ah.h" 24237611Sadrian#include "ah_internal.h" 25237611Sadrian#include "ah_devid.h" 26237611Sadrian#ifdef AH_DEBUG 27243841Sadrian#include "ah_desc.h" /* NB: for HAL_PHYERR* */ 28237611Sadrian#endif 29237611Sadrian 30237611Sadrian#include "ar5416/ar5416.h" 31237611Sadrian#include "ar5416/ar5416reg.h" 32237611Sadrian#include "ar5416/ar5416phy.h" 33237611Sadrian#include "ar5416/ar5416desc.h" /* AR5416_CONTTXMODE */ 34237611Sadrian 35237611Sadrian#include "ar9002/ar9285phy.h" 36237611Sadrian#include "ar9002/ar9285.h" 37237611Sadrian 38237611Sadrian/* 39237611Sadrian * This is specific to Kite. 40237611Sadrian * 41237611Sadrian * Kiwi and others don't have antenna diversity like this. 42237611Sadrian */ 43237611Sadrianvoid 44237611Sadrianar9285BTCoexAntennaDiversity(struct ath_hal *ah) 45237611Sadrian{ 46237611Sadrian struct ath_hal_5416 *ahp = AH5416(ah); 47237611Sadrian u_int32_t regVal; 48237611Sadrian u_int8_t ant_div_control1, ant_div_control2; 49237611Sadrian 50251483Sadrian HALDEBUG(ah, HAL_DEBUG_BT_COEX, 51251483Sadrian "%s: btCoexFlag: ALLOW=%d, ENABLE=%d\n", 52251483Sadrian __func__, 53251483Sadrian !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW), 54251483Sadrian !! (ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE)); 55251483Sadrian 56243841Sadrian if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) || 57243841Sadrian (AH5212(ah)->ah_diversity != HAL_ANT_VARIABLE)) { 58243841Sadrian if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE) && 59248182Sadrian (AH5212(ah)->ah_antControl == HAL_ANT_VARIABLE)) { 60243841Sadrian /* Enable antenna diversity */ 61243841Sadrian ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE; 62243841Sadrian ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE; 63237611Sadrian 64243841Sadrian /* Don't disable BT ant to allow BB to control SWCOM */ 65243841Sadrian ahp->ah_btCoexMode2 &= (~(AR_BT_DISABLE_BT_ANT)); 66243841Sadrian OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 67237611Sadrian 68243841Sadrian /* Program the correct SWCOM table */ 69243841Sadrian OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 70243841Sadrian HAL_BT_COEX_ANT_DIV_SWITCH_COM); 71243841Sadrian OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); 72248182Sadrian } else if (AH5212(ah)->ah_antControl == HAL_ANT_FIXED_B) { 73243841Sadrian /* Disable antenna diversity. Use antenna B(LNA2) only. */ 74243841Sadrian ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B; 75243841Sadrian ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B; 76237611Sadrian 77243841Sadrian /* Disable BT ant to allow concurrent BT and WLAN receive */ 78243841Sadrian ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; 79243841Sadrian OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 80237611Sadrian 81243841Sadrian /* 82243841Sadrian * Program SWCOM table to make sure RF switch always parks 83243841Sadrian * at WLAN side 84243841Sadrian */ 85243841Sadrian OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 86243841Sadrian HAL_BT_COEX_ANT_DIV_SWITCH_COM); 87243841Sadrian OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0x60000000, 0xf0000000); 88243841Sadrian } else { 89243841Sadrian /* Disable antenna diversity. Use antenna A(LNA1) only */ 90243841Sadrian ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A; 91243841Sadrian ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A; 92237611Sadrian 93243841Sadrian /* Disable BT ant to allow concurrent BT and WLAN receive */ 94243841Sadrian ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; 95243841Sadrian OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); 96237611Sadrian 97243841Sadrian /* 98243841Sadrian * Program SWCOM table to make sure RF switch always 99243841Sadrian * parks at BT side 100243841Sadrian */ 101243841Sadrian OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0); 102243841Sadrian OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); 103243841Sadrian } 104237611Sadrian 105243841Sadrian regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); 106243841Sadrian regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); 107243841Sadrian /* 108243841Sadrian * Clear ant_fast_div_bias [14:9] since for Janus the main LNA is 109243841Sadrian * always LNA1. 110243841Sadrian */ 111243841Sadrian regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); 112237611Sadrian 113243841Sadrian regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); 114243841Sadrian regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); 115243841Sadrian regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); 116243841Sadrian regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); 117243841Sadrian regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); 118243841Sadrian OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); 119237611Sadrian 120243841Sadrian regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); 121243841Sadrian regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); 122243841Sadrian regVal |= SM((ant_div_control1 >> 3), 123243841Sadrian AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); 124243841Sadrian OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); 125237611Sadrian } 126237611Sadrian} 127237611Sadrian 128237611Sadrianvoid 129237611Sadrianar9285BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value) 130237611Sadrian{ 131237611Sadrian struct ath_hal_5416 *ahp = AH5416(ah); 132237611Sadrian 133237611Sadrian switch (type) { 134237611Sadrian case HAL_BT_COEX_ANTENNA_DIVERSITY: 135237611Sadrian if (AR_SREV_KITE(ah)) { 136237611Sadrian ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW; 137237611Sadrian if (value) 138237611Sadrian ahp->ah_btCoexFlag |= 139237611Sadrian HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; 140237611Sadrian else 141237611Sadrian ahp->ah_btCoexFlag &= 142237611Sadrian ~HAL_BT_COEX_FLAG_ANT_DIV_ENABLE; 143237611Sadrian ar9285BTCoexAntennaDiversity(ah); 144237611Sadrian } 145237611Sadrian break; 146237611Sadrian default: 147237611Sadrian ar5416BTCoexSetParameter(ah, type, value); 148237611Sadrian break; 149237611Sadrian } 150237611Sadrian} 151237611Sadrian 152237611Sadrian 153