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