ar9285_btcoex.c revision 243841
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: head/sys/dev/ath/ath_hal/ar9002/ar9285_btcoex.c 243841 2012-12-04 00:01:24Z adrian $
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 */
43void
44ar9285BTCoexAntennaDiversity(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	if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) ||
51	    (AH5212(ah)->ah_diversity != HAL_ANT_VARIABLE)) {
52	if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE) &&
53	     (AH5212(ah)->ah_diversity == HAL_ANT_VARIABLE)) {
54		/* Enable antenna diversity */
55		ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE;
56		ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE;
57
58		/* Don't disable BT ant to allow BB to control SWCOM */
59		ahp->ah_btCoexMode2 &= (~(AR_BT_DISABLE_BT_ANT));
60		OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);
61
62		/* Program the correct SWCOM table */
63		OS_REG_WRITE(ah, AR_PHY_SWITCH_COM,
64		    HAL_BT_COEX_ANT_DIV_SWITCH_COM);
65		OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
66	} else if (AH5212(ah)->ah_diversity == HAL_ANT_FIXED_B) {
67		/* Disable antenna diversity. Use antenna B(LNA2) only. */
68		ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B;
69		ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B;
70
71		/* Disable BT ant to allow concurrent BT and WLAN receive */
72		ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT;
73		OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);
74
75		/*
76		 * Program SWCOM table to make sure RF switch always parks
77		 * at WLAN side
78		 */
79		OS_REG_WRITE(ah, AR_PHY_SWITCH_COM,
80		    HAL_BT_COEX_ANT_DIV_SWITCH_COM);
81		OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0x60000000, 0xf0000000);
82	} else {
83		/* Disable antenna diversity. Use antenna A(LNA1) only */
84		ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A;
85		ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A;
86
87		/* Disable BT ant to allow concurrent BT and WLAN receive */
88		ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT;
89		OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2);
90
91		/*
92		 * Program SWCOM table to make sure RF switch always
93		 * parks at BT side
94		 */
95		OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0);
96		OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000);
97	}
98
99	regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
100	regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
101	/*
102	 * Clear ant_fast_div_bias [14:9] since for Janus the main LNA is
103	 * always LNA1.
104	 */
105	regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS));
106
107	regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL);
108	regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF);
109	regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
110	regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB);
111	regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
112	OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
113
114	regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT);
115	regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
116	regVal |= SM((ant_div_control1 >> 3),
117	    AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
118	OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
119    }
120}
121
122void
123ar9285BTCoexSetParameter(struct ath_hal *ah, u_int32_t type, u_int32_t value)
124{
125	struct ath_hal_5416 *ahp = AH5416(ah);
126
127	switch (type) {
128	case HAL_BT_COEX_ANTENNA_DIVERSITY:
129		if (AR_SREV_KITE(ah)) {
130			ahp->ah_btCoexFlag |= HAL_BT_COEX_FLAG_ANT_DIV_ALLOW;
131			if (value)
132				ahp->ah_btCoexFlag |=
133				    HAL_BT_COEX_FLAG_ANT_DIV_ENABLE;
134			else
135				ahp->ah_btCoexFlag &=
136				    ~HAL_BT_COEX_FLAG_ANT_DIV_ENABLE;
137			ar9285BTCoexAntennaDiversity(ah);
138		}
139		break;
140	default:
141		ar5416BTCoexSetParameter(ah, type, value);
142		break;
143	}
144}
145
146
147