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