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