xref: /onnv-gate/usr/src/uts/common/io/arn/arn_phy.c (revision 9999:d5e89571de4e)
1*9999SWang.Lin@Sun.COM /*
2*9999SWang.Lin@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3*9999SWang.Lin@Sun.COM  * Use is subject to license terms.
4*9999SWang.Lin@Sun.COM  */
5*9999SWang.Lin@Sun.COM 
6*9999SWang.Lin@Sun.COM /*
7*9999SWang.Lin@Sun.COM  * Copyright (c) 2008 Atheros Communications Inc.
8*9999SWang.Lin@Sun.COM  *
9*9999SWang.Lin@Sun.COM  * Permission to use, copy, modify, and/or distribute this software for any
10*9999SWang.Lin@Sun.COM  * purpose with or without fee is hereby granted, provided that the above
11*9999SWang.Lin@Sun.COM  * copyright notice and this permission notice appear in all copies.
12*9999SWang.Lin@Sun.COM  *
13*9999SWang.Lin@Sun.COM  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14*9999SWang.Lin@Sun.COM  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15*9999SWang.Lin@Sun.COM  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16*9999SWang.Lin@Sun.COM  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17*9999SWang.Lin@Sun.COM  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18*9999SWang.Lin@Sun.COM  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19*9999SWang.Lin@Sun.COM  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20*9999SWang.Lin@Sun.COM  */
21*9999SWang.Lin@Sun.COM 
22*9999SWang.Lin@Sun.COM #include "arn_core.h"
23*9999SWang.Lin@Sun.COM #include "arn_hw.h"
24*9999SWang.Lin@Sun.COM #include "arn_reg.h"
25*9999SWang.Lin@Sun.COM #include "arn_phy.h"
26*9999SWang.Lin@Sun.COM 
27*9999SWang.Lin@Sun.COM /* ARGSUSED */
28*9999SWang.Lin@Sun.COM void
ath9k_hw_write_regs(struct ath_hal * ah,uint32_t modesIndex,uint32_t freqIndex,int regWrites)29*9999SWang.Lin@Sun.COM ath9k_hw_write_regs(struct ath_hal *ah, uint32_t modesIndex, uint32_t freqIndex,
30*9999SWang.Lin@Sun.COM 		    int regWrites)
31*9999SWang.Lin@Sun.COM {
32*9999SWang.Lin@Sun.COM 	struct ath_hal_5416 *ahp = AH5416(ah);
33*9999SWang.Lin@Sun.COM 
34*9999SWang.Lin@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
35*9999SWang.Lin@Sun.COM 	REG_WRITE_ARRAY(&ahp->ah_iniBB_RfGain, freqIndex, regWrites);
36*9999SWang.Lin@Sun.COM }
37*9999SWang.Lin@Sun.COM 
38*9999SWang.Lin@Sun.COM boolean_t
ath9k_hw_set_channel(struct ath_hal * ah,struct ath9k_channel * chan)39*9999SWang.Lin@Sun.COM ath9k_hw_set_channel(struct ath_hal *ah, struct ath9k_channel *chan)
40*9999SWang.Lin@Sun.COM {
41*9999SWang.Lin@Sun.COM 	uint32_t channelSel = 0;
42*9999SWang.Lin@Sun.COM 	uint32_t bModeSynth = 0;
43*9999SWang.Lin@Sun.COM 	uint32_t aModeRefSel = 0;
44*9999SWang.Lin@Sun.COM 	uint32_t reg32 = 0;
45*9999SWang.Lin@Sun.COM 	uint16_t freq;
46*9999SWang.Lin@Sun.COM 	struct chan_centers centers;
47*9999SWang.Lin@Sun.COM 
48*9999SWang.Lin@Sun.COM 	ath9k_hw_get_channel_centers(ah, chan, &centers);
49*9999SWang.Lin@Sun.COM 	freq = centers.synth_center;
50*9999SWang.Lin@Sun.COM 
51*9999SWang.Lin@Sun.COM 	if (freq < 4800) {
52*9999SWang.Lin@Sun.COM 		uint32_t txctl;
53*9999SWang.Lin@Sun.COM 
54*9999SWang.Lin@Sun.COM 		if (((freq - 2192) % 5) == 0) {
55*9999SWang.Lin@Sun.COM 			channelSel = ((freq - 672) * 2 - 3040) / 10;
56*9999SWang.Lin@Sun.COM 			bModeSynth = 0;
57*9999SWang.Lin@Sun.COM 		} else if (((freq - 2224) % 5) == 0) {
58*9999SWang.Lin@Sun.COM 			channelSel = ((freq - 704) * 2 - 3040) / 10;
59*9999SWang.Lin@Sun.COM 			bModeSynth = 1;
60*9999SWang.Lin@Sun.COM 		} else {
61*9999SWang.Lin@Sun.COM 			arn_problem("%s: invalid channel %u MHz\n",
62*9999SWang.Lin@Sun.COM 			    __func__, freq);
63*9999SWang.Lin@Sun.COM 			return (B_FALSE);
64*9999SWang.Lin@Sun.COM 		}
65*9999SWang.Lin@Sun.COM 
66*9999SWang.Lin@Sun.COM 		channelSel = (channelSel << 2) & 0xff;
67*9999SWang.Lin@Sun.COM 		channelSel = ath9k_hw_reverse_bits(channelSel, 8);
68*9999SWang.Lin@Sun.COM 
69*9999SWang.Lin@Sun.COM 		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
70*9999SWang.Lin@Sun.COM 		if (freq == 2484) {
71*9999SWang.Lin@Sun.COM 
72*9999SWang.Lin@Sun.COM 			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
73*9999SWang.Lin@Sun.COM 			    txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
74*9999SWang.Lin@Sun.COM 		} else {
75*9999SWang.Lin@Sun.COM 			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
76*9999SWang.Lin@Sun.COM 			    txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
77*9999SWang.Lin@Sun.COM 		}
78*9999SWang.Lin@Sun.COM 
79*9999SWang.Lin@Sun.COM 	} else if ((freq % 20) == 0 && freq >= 5120) {
80*9999SWang.Lin@Sun.COM 		channelSel =
81*9999SWang.Lin@Sun.COM 		    ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
82*9999SWang.Lin@Sun.COM 		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
83*9999SWang.Lin@Sun.COM 	} else if ((freq % 10) == 0) {
84*9999SWang.Lin@Sun.COM 		channelSel =
85*9999SWang.Lin@Sun.COM 		    ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
86*9999SWang.Lin@Sun.COM 		if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
87*9999SWang.Lin@Sun.COM 			aModeRefSel = ath9k_hw_reverse_bits(2, 2);
88*9999SWang.Lin@Sun.COM 		else
89*9999SWang.Lin@Sun.COM 			aModeRefSel = ath9k_hw_reverse_bits(1, 2);
90*9999SWang.Lin@Sun.COM 	} else if ((freq % 5) == 0) {
91*9999SWang.Lin@Sun.COM 		channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
92*9999SWang.Lin@Sun.COM 		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
93*9999SWang.Lin@Sun.COM 	} else {
94*9999SWang.Lin@Sun.COM 		arn_problem("%s: invalid channel %u MHz\n", __func__, freq);
95*9999SWang.Lin@Sun.COM 		return (B_FALSE);
96*9999SWang.Lin@Sun.COM 	}
97*9999SWang.Lin@Sun.COM 
98*9999SWang.Lin@Sun.COM 	reg32 =
99*9999SWang.Lin@Sun.COM 	    (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
100*9999SWang.Lin@Sun.COM 	    (1 << 5) | 0x1;
101*9999SWang.Lin@Sun.COM 
102*9999SWang.Lin@Sun.COM 	REG_WRITE(ah, AR_PHY(0x37), reg32);
103*9999SWang.Lin@Sun.COM 
104*9999SWang.Lin@Sun.COM 	ah->ah_curchan = chan;
105*9999SWang.Lin@Sun.COM 
106*9999SWang.Lin@Sun.COM 	AH5416(ah)->ah_curchanRadIndex = -1;
107*9999SWang.Lin@Sun.COM 
108*9999SWang.Lin@Sun.COM 	return (B_TRUE);
109*9999SWang.Lin@Sun.COM }
110*9999SWang.Lin@Sun.COM 
111*9999SWang.Lin@Sun.COM boolean_t
ath9k_hw_ar9280_set_channel(struct ath_hal * ah,struct ath9k_channel * chan)112*9999SWang.Lin@Sun.COM ath9k_hw_ar9280_set_channel(struct ath_hal *ah,
113*9999SWang.Lin@Sun.COM     struct ath9k_channel *chan)
114*9999SWang.Lin@Sun.COM {
115*9999SWang.Lin@Sun.COM 	uint16_t bMode, fracMode, aModeRefSel = 0;
116*9999SWang.Lin@Sun.COM 	uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
117*9999SWang.Lin@Sun.COM 	struct chan_centers centers;
118*9999SWang.Lin@Sun.COM 	uint32_t refDivA = 24;
119*9999SWang.Lin@Sun.COM 
120*9999SWang.Lin@Sun.COM 	ath9k_hw_get_channel_centers(ah, chan, &centers);
121*9999SWang.Lin@Sun.COM 	freq = centers.synth_center;
122*9999SWang.Lin@Sun.COM 
123*9999SWang.Lin@Sun.COM 	reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
124*9999SWang.Lin@Sun.COM 	reg32 &= 0xc0000000;
125*9999SWang.Lin@Sun.COM 
126*9999SWang.Lin@Sun.COM 	if (freq < 4800) {
127*9999SWang.Lin@Sun.COM 		uint32_t txctl;
128*9999SWang.Lin@Sun.COM 
129*9999SWang.Lin@Sun.COM 		bMode = 1;
130*9999SWang.Lin@Sun.COM 		fracMode = 1;
131*9999SWang.Lin@Sun.COM 		aModeRefSel = 0;
132*9999SWang.Lin@Sun.COM 		channelSel = (freq * 0x10000) / 15;
133*9999SWang.Lin@Sun.COM 
134*9999SWang.Lin@Sun.COM 		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
135*9999SWang.Lin@Sun.COM 		if (freq == 2484) {
136*9999SWang.Lin@Sun.COM 
137*9999SWang.Lin@Sun.COM 			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
138*9999SWang.Lin@Sun.COM 			    txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
139*9999SWang.Lin@Sun.COM 		} else {
140*9999SWang.Lin@Sun.COM 			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
141*9999SWang.Lin@Sun.COM 			    txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
142*9999SWang.Lin@Sun.COM 		}
143*9999SWang.Lin@Sun.COM 	} else {
144*9999SWang.Lin@Sun.COM 		bMode = 0;
145*9999SWang.Lin@Sun.COM 		fracMode = 0;
146*9999SWang.Lin@Sun.COM 
147*9999SWang.Lin@Sun.COM 		if ((freq % 20) == 0) {
148*9999SWang.Lin@Sun.COM 			aModeRefSel = 3;
149*9999SWang.Lin@Sun.COM 		} else if ((freq % 10) == 0) {
150*9999SWang.Lin@Sun.COM 			aModeRefSel = 2;
151*9999SWang.Lin@Sun.COM 		} else {
152*9999SWang.Lin@Sun.COM 			aModeRefSel = 0;
153*9999SWang.Lin@Sun.COM 
154*9999SWang.Lin@Sun.COM 			fracMode = 1;
155*9999SWang.Lin@Sun.COM 			refDivA = 1;
156*9999SWang.Lin@Sun.COM 			channelSel = (freq * 0x8000) / 15;
157*9999SWang.Lin@Sun.COM 
158*9999SWang.Lin@Sun.COM 			REG_RMW_FIELD(ah, AR_AN_SYNTH9,
159*9999SWang.Lin@Sun.COM 			    AR_AN_SYNTH9_REFDIVA, refDivA);
160*9999SWang.Lin@Sun.COM 		}
161*9999SWang.Lin@Sun.COM 		if (!fracMode) {
162*9999SWang.Lin@Sun.COM 			ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
163*9999SWang.Lin@Sun.COM 			channelSel = ndiv & 0x1ff;
164*9999SWang.Lin@Sun.COM 			channelFrac = (ndiv & 0xfffffe00) * 2;
165*9999SWang.Lin@Sun.COM 			channelSel = (channelSel << 17) | channelFrac;
166*9999SWang.Lin@Sun.COM 		}
167*9999SWang.Lin@Sun.COM 	}
168*9999SWang.Lin@Sun.COM 
169*9999SWang.Lin@Sun.COM 	reg32 = reg32 |
170*9999SWang.Lin@Sun.COM 	    (bMode << 29) |
171*9999SWang.Lin@Sun.COM 	    (fracMode << 28) | (aModeRefSel << 26) | (channelSel);
172*9999SWang.Lin@Sun.COM 
173*9999SWang.Lin@Sun.COM 	REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
174*9999SWang.Lin@Sun.COM 
175*9999SWang.Lin@Sun.COM 	ah->ah_curchan = chan;
176*9999SWang.Lin@Sun.COM 
177*9999SWang.Lin@Sun.COM 	AH5416(ah)->ah_curchanRadIndex = -1;
178*9999SWang.Lin@Sun.COM 
179*9999SWang.Lin@Sun.COM 	return (B_TRUE);
180*9999SWang.Lin@Sun.COM }
181*9999SWang.Lin@Sun.COM 
182*9999SWang.Lin@Sun.COM static void
ath9k_phy_modify_rx_buffer(uint32_t * rfBuf,uint32_t reg32,uint32_t numBits,uint32_t firstBit,uint32_t column)183*9999SWang.Lin@Sun.COM ath9k_phy_modify_rx_buffer(uint32_t *rfBuf, uint32_t reg32,
184*9999SWang.Lin@Sun.COM     uint32_t numBits, uint32_t firstBit, uint32_t column)
185*9999SWang.Lin@Sun.COM {
186*9999SWang.Lin@Sun.COM 	uint32_t tmp32, mask, arrayEntry, lastBit;
187*9999SWang.Lin@Sun.COM 	int32_t bitPosition, bitsLeft;
188*9999SWang.Lin@Sun.COM 
189*9999SWang.Lin@Sun.COM 	tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
190*9999SWang.Lin@Sun.COM 	arrayEntry = (firstBit - 1) / 8;
191*9999SWang.Lin@Sun.COM 	bitPosition = (firstBit - 1) % 8;
192*9999SWang.Lin@Sun.COM 	bitsLeft = numBits;
193*9999SWang.Lin@Sun.COM 	while (bitsLeft > 0) {
194*9999SWang.Lin@Sun.COM 		lastBit = (bitPosition + bitsLeft > 8) ?
195*9999SWang.Lin@Sun.COM 		    8 : bitPosition + bitsLeft;
196*9999SWang.Lin@Sun.COM 		mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
197*9999SWang.Lin@Sun.COM 		    (column * 8);
198*9999SWang.Lin@Sun.COM 		rfBuf[arrayEntry] &= ~mask;
199*9999SWang.Lin@Sun.COM 		rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
200*9999SWang.Lin@Sun.COM 		    (column * 8)) & mask;
201*9999SWang.Lin@Sun.COM 		bitsLeft -= 8 - bitPosition;
202*9999SWang.Lin@Sun.COM 		tmp32 = tmp32 >> (8 - bitPosition);
203*9999SWang.Lin@Sun.COM 		bitPosition = 0;
204*9999SWang.Lin@Sun.COM 		arrayEntry++;
205*9999SWang.Lin@Sun.COM 	}
206*9999SWang.Lin@Sun.COM }
207*9999SWang.Lin@Sun.COM 
208*9999SWang.Lin@Sun.COM boolean_t
ath9k_hw_set_rf_regs(struct ath_hal * ah,struct ath9k_channel * chan,uint16_t modesIndex)209*9999SWang.Lin@Sun.COM ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan,
210*9999SWang.Lin@Sun.COM     uint16_t modesIndex)
211*9999SWang.Lin@Sun.COM {
212*9999SWang.Lin@Sun.COM 	struct ath_hal_5416 *ahp = AH5416(ah);
213*9999SWang.Lin@Sun.COM 
214*9999SWang.Lin@Sun.COM 	uint32_t eepMinorRev;
215*9999SWang.Lin@Sun.COM 	uint32_t ob5GHz = 0, db5GHz = 0;
216*9999SWang.Lin@Sun.COM 	uint32_t ob2GHz = 0, db2GHz = 0;
217*9999SWang.Lin@Sun.COM 	/* LINTED E_FUNC_SET_NOT_USED */
218*9999SWang.Lin@Sun.COM 	int regWrites = 0;
219*9999SWang.Lin@Sun.COM 
220*9999SWang.Lin@Sun.COM 	if (AR_SREV_9280_10_OR_LATER(ah))
221*9999SWang.Lin@Sun.COM 		return (B_TRUE);
222*9999SWang.Lin@Sun.COM 
223*9999SWang.Lin@Sun.COM 	eepMinorRev = ath9k_hw_get_eeprom(ah, EEP_MINOR_REV);
224*9999SWang.Lin@Sun.COM 
225*9999SWang.Lin@Sun.COM 	RF_BANK_SETUP(ahp->ah_analogBank0Data, &ahp->ah_iniBank0, 1);
226*9999SWang.Lin@Sun.COM 
227*9999SWang.Lin@Sun.COM 	RF_BANK_SETUP(ahp->ah_analogBank1Data, &ahp->ah_iniBank1, 1);
228*9999SWang.Lin@Sun.COM 
229*9999SWang.Lin@Sun.COM 	RF_BANK_SETUP(ahp->ah_analogBank2Data, &ahp->ah_iniBank2, 1);
230*9999SWang.Lin@Sun.COM 
231*9999SWang.Lin@Sun.COM 	RF_BANK_SETUP(ahp->ah_analogBank3Data, &ahp->ah_iniBank3,
232*9999SWang.Lin@Sun.COM 	    modesIndex);
233*9999SWang.Lin@Sun.COM 	{
234*9999SWang.Lin@Sun.COM 		int i;
235*9999SWang.Lin@Sun.COM 		for (i = 0; i < ahp->ah_iniBank6TPC.ia_rows; i++) {
236*9999SWang.Lin@Sun.COM 			ahp->ah_analogBank6Data[i] =
237*9999SWang.Lin@Sun.COM 			    INI_RA(&ahp->ah_iniBank6TPC, i, modesIndex);
238*9999SWang.Lin@Sun.COM 		}
239*9999SWang.Lin@Sun.COM 	}
240*9999SWang.Lin@Sun.COM 
241*9999SWang.Lin@Sun.COM 	if (eepMinorRev >= 2) {
242*9999SWang.Lin@Sun.COM 		if (IS_CHAN_2GHZ(chan)) {
243*9999SWang.Lin@Sun.COM 			ob2GHz = ath9k_hw_get_eeprom(ah, EEP_OB_2);
244*9999SWang.Lin@Sun.COM 			db2GHz = ath9k_hw_get_eeprom(ah, EEP_DB_2);
245*9999SWang.Lin@Sun.COM 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
246*9999SWang.Lin@Sun.COM 			    ob2GHz, 3, 197, 0);
247*9999SWang.Lin@Sun.COM 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
248*9999SWang.Lin@Sun.COM 			    db2GHz, 3, 194, 0);
249*9999SWang.Lin@Sun.COM 		} else {
250*9999SWang.Lin@Sun.COM 			ob5GHz = ath9k_hw_get_eeprom(ah, EEP_OB_5);
251*9999SWang.Lin@Sun.COM 			db5GHz = ath9k_hw_get_eeprom(ah, EEP_DB_5);
252*9999SWang.Lin@Sun.COM 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
253*9999SWang.Lin@Sun.COM 			    ob5GHz, 3, 203, 0);
254*9999SWang.Lin@Sun.COM 			ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
255*9999SWang.Lin@Sun.COM 			    db5GHz, 3, 200, 0);
256*9999SWang.Lin@Sun.COM 		}
257*9999SWang.Lin@Sun.COM 	}
258*9999SWang.Lin@Sun.COM 
259*9999SWang.Lin@Sun.COM 	RF_BANK_SETUP(ahp->ah_analogBank7Data, &ahp->ah_iniBank7, 1);
260*9999SWang.Lin@Sun.COM 
261*9999SWang.Lin@Sun.COM 	REG_WRITE_RF_ARRAY(&ahp->ah_iniBank0, ahp->ah_analogBank0Data,
262*9999SWang.Lin@Sun.COM 	    regWrites);
263*9999SWang.Lin@Sun.COM 
264*9999SWang.Lin@Sun.COM 	REG_WRITE_RF_ARRAY(&ahp->ah_iniBank1, ahp->ah_analogBank1Data,
265*9999SWang.Lin@Sun.COM 	    regWrites);
266*9999SWang.Lin@Sun.COM 
267*9999SWang.Lin@Sun.COM 	REG_WRITE_RF_ARRAY(&ahp->ah_iniBank2, ahp->ah_analogBank2Data,
268*9999SWang.Lin@Sun.COM 	    regWrites);
269*9999SWang.Lin@Sun.COM 
270*9999SWang.Lin@Sun.COM 	REG_WRITE_RF_ARRAY(&ahp->ah_iniBank3, ahp->ah_analogBank3Data,
271*9999SWang.Lin@Sun.COM 	    regWrites);
272*9999SWang.Lin@Sun.COM 
273*9999SWang.Lin@Sun.COM 	REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6TPC, ahp->ah_analogBank6Data,
274*9999SWang.Lin@Sun.COM 	    regWrites);
275*9999SWang.Lin@Sun.COM 
276*9999SWang.Lin@Sun.COM 	REG_WRITE_RF_ARRAY(&ahp->ah_iniBank7, ahp->ah_analogBank7Data,
277*9999SWang.Lin@Sun.COM 	    regWrites);
278*9999SWang.Lin@Sun.COM 
279*9999SWang.Lin@Sun.COM 	return (B_TRUE);
280*9999SWang.Lin@Sun.COM }
281*9999SWang.Lin@Sun.COM 
282*9999SWang.Lin@Sun.COM void
ath9k_hw_rfdetach(struct ath_hal * ah)283*9999SWang.Lin@Sun.COM ath9k_hw_rfdetach(struct ath_hal *ah)
284*9999SWang.Lin@Sun.COM {
285*9999SWang.Lin@Sun.COM 	struct ath_hal_5416 *ahp = AH5416(ah);
286*9999SWang.Lin@Sun.COM 
287*9999SWang.Lin@Sun.COM 	if (ahp->ah_analogBank0Data != NULL) {
288*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_analogBank0Data,
289*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank0.ia_rows));
290*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank0Data = NULL;
291*9999SWang.Lin@Sun.COM 	}
292*9999SWang.Lin@Sun.COM 	if (ahp->ah_analogBank1Data != NULL) {
293*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_analogBank1Data,
294*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank1.ia_rows));
295*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank1Data = NULL;
296*9999SWang.Lin@Sun.COM 	}
297*9999SWang.Lin@Sun.COM 	if (ahp->ah_analogBank2Data != NULL) {
298*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_analogBank2Data,
299*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank2.ia_rows));
300*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank2Data = NULL;
301*9999SWang.Lin@Sun.COM 	}
302*9999SWang.Lin@Sun.COM 	if (ahp->ah_analogBank3Data != NULL) {
303*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_analogBank3Data,
304*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank3.ia_rows));
305*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank3Data = NULL;
306*9999SWang.Lin@Sun.COM 	}
307*9999SWang.Lin@Sun.COM 	if (ahp->ah_analogBank6Data != NULL) {
308*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_analogBank6Data,
309*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank6.ia_rows));
310*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank6Data = NULL;
311*9999SWang.Lin@Sun.COM 	}
312*9999SWang.Lin@Sun.COM 	if (ahp->ah_analogBank6TPCData != NULL) {
313*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_analogBank6TPCData,
314*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank6TPC.ia_rows));
315*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank6TPCData = NULL;
316*9999SWang.Lin@Sun.COM 	}
317*9999SWang.Lin@Sun.COM 	if (ahp->ah_analogBank7Data != NULL) {
318*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_analogBank7Data,
319*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank7.ia_rows));
320*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank7Data = NULL;
321*9999SWang.Lin@Sun.COM 	}
322*9999SWang.Lin@Sun.COM 	if (ahp->ah_addac5416_21 != NULL) {
323*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_addac5416_21,
324*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniAddac.ia_rows *
325*9999SWang.Lin@Sun.COM 		    ahp->ah_iniAddac.ia_columns));
326*9999SWang.Lin@Sun.COM 		ahp->ah_addac5416_21 = NULL;
327*9999SWang.Lin@Sun.COM 	}
328*9999SWang.Lin@Sun.COM 	if (ahp->ah_bank6Temp != NULL) {
329*9999SWang.Lin@Sun.COM 		kmem_free(ahp->ah_bank6Temp,
330*9999SWang.Lin@Sun.COM 		    (sizeof (uint32_t) * ahp->ah_iniBank6.ia_rows));
331*9999SWang.Lin@Sun.COM 		ahp->ah_bank6Temp = NULL;
332*9999SWang.Lin@Sun.COM 	}
333*9999SWang.Lin@Sun.COM }
334*9999SWang.Lin@Sun.COM 
335*9999SWang.Lin@Sun.COM boolean_t
ath9k_hw_init_rf(struct ath_hal * ah,int * status)336*9999SWang.Lin@Sun.COM ath9k_hw_init_rf(struct ath_hal *ah, int *status)
337*9999SWang.Lin@Sun.COM {
338*9999SWang.Lin@Sun.COM 	struct ath_hal_5416 *ahp = AH5416(ah);
339*9999SWang.Lin@Sun.COM 
340*9999SWang.Lin@Sun.COM 	if (!AR_SREV_9280_10_OR_LATER(ah)) {
341*9999SWang.Lin@Sun.COM 
342*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank0Data =
343*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
344*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank0.ia_rows), KM_SLEEP);
345*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank1Data =
346*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
347*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank1.ia_rows), KM_SLEEP);
348*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank2Data =
349*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
350*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank2.ia_rows), KM_SLEEP);
351*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank3Data =
352*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
353*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank3.ia_rows), KM_SLEEP);
354*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank6Data =
355*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
356*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank6.ia_rows), KM_SLEEP);
357*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank6TPCData =
358*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
359*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank6TPC.ia_rows), KM_SLEEP);
360*9999SWang.Lin@Sun.COM 		ahp->ah_analogBank7Data =
361*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
362*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank7.ia_rows), KM_SLEEP);
363*9999SWang.Lin@Sun.COM 
364*9999SWang.Lin@Sun.COM 		if (ahp->ah_analogBank0Data == NULL ||
365*9999SWang.Lin@Sun.COM 		    ahp->ah_analogBank1Data == NULL ||
366*9999SWang.Lin@Sun.COM 		    ahp->ah_analogBank2Data == NULL ||
367*9999SWang.Lin@Sun.COM 		    ahp->ah_analogBank3Data == NULL ||
368*9999SWang.Lin@Sun.COM 		    ahp->ah_analogBank6Data == NULL ||
369*9999SWang.Lin@Sun.COM 		    ahp->ah_analogBank6TPCData == NULL ||
370*9999SWang.Lin@Sun.COM 		    ahp->ah_analogBank7Data == NULL) {
371*9999SWang.Lin@Sun.COM 			ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): "
372*9999SWang.Lin@Sun.COM 			    "cannot allocate RF banks\n"));
373*9999SWang.Lin@Sun.COM 			*status = ENOMEM;
374*9999SWang.Lin@Sun.COM 			return (B_FALSE);
375*9999SWang.Lin@Sun.COM 		}
376*9999SWang.Lin@Sun.COM 
377*9999SWang.Lin@Sun.COM 		ahp->ah_addac5416_21 =
378*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
379*9999SWang.Lin@Sun.COM 		    ahp->ah_iniAddac.ia_rows *
380*9999SWang.Lin@Sun.COM 		    ahp->ah_iniAddac.ia_columns), KM_SLEEP);
381*9999SWang.Lin@Sun.COM 		if (ahp->ah_addac5416_21 == NULL) {
382*9999SWang.Lin@Sun.COM 			ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): "
383*9999SWang.Lin@Sun.COM 			    "cannot allocate ah_addac5416_21\n"));
384*9999SWang.Lin@Sun.COM 			*status = ENOMEM;
385*9999SWang.Lin@Sun.COM 			return (B_FALSE);
386*9999SWang.Lin@Sun.COM 		}
387*9999SWang.Lin@Sun.COM 
388*9999SWang.Lin@Sun.COM 		ahp->ah_bank6Temp =
389*9999SWang.Lin@Sun.COM 		    kmem_zalloc((sizeof (uint32_t) *
390*9999SWang.Lin@Sun.COM 		    ahp->ah_iniBank6.ia_rows), KM_SLEEP);
391*9999SWang.Lin@Sun.COM 		if (ahp->ah_bank6Temp == NULL) {
392*9999SWang.Lin@Sun.COM 			ARN_DBG((ARN_DBG_FATAL, "arn: ath9k_hw_init_rf(): "
393*9999SWang.Lin@Sun.COM 			    "cannot allocate ah_bank6Temp\n"));
394*9999SWang.Lin@Sun.COM 			*status = ENOMEM;
395*9999SWang.Lin@Sun.COM 			return (B_FALSE);
396*9999SWang.Lin@Sun.COM 		}
397*9999SWang.Lin@Sun.COM 	}
398*9999SWang.Lin@Sun.COM 
399*9999SWang.Lin@Sun.COM 	return (B_TRUE);
400*9999SWang.Lin@Sun.COM }
401*9999SWang.Lin@Sun.COM 
402*9999SWang.Lin@Sun.COM /* ARGSUSED */
403*9999SWang.Lin@Sun.COM void
ath9k_hw_decrease_chain_power(struct ath_hal * ah,struct ath9k_channel * chan)404*9999SWang.Lin@Sun.COM ath9k_hw_decrease_chain_power(struct ath_hal *ah, struct ath9k_channel *chan)
405*9999SWang.Lin@Sun.COM {
406*9999SWang.Lin@Sun.COM 	/* LINTED E_FUNC_SET_NOT_USED */
407*9999SWang.Lin@Sun.COM 	int i, regWrites = 0;
408*9999SWang.Lin@Sun.COM 	struct ath_hal_5416 *ahp = AH5416(ah);
409*9999SWang.Lin@Sun.COM 	uint32_t bank6SelMask;
410*9999SWang.Lin@Sun.COM 	uint32_t *bank6Temp = ahp->ah_bank6Temp;
411*9999SWang.Lin@Sun.COM 
412*9999SWang.Lin@Sun.COM 	switch (ahp->ah_diversityControl) {
413*9999SWang.Lin@Sun.COM 	case ATH9K_ANT_FIXED_A:
414*9999SWang.Lin@Sun.COM 		bank6SelMask =
415*9999SWang.Lin@Sun.COM 		    (ahp-> ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_0 :
416*9999SWang.Lin@Sun.COM 		    REDUCE_CHAIN_1;
417*9999SWang.Lin@Sun.COM 		break;
418*9999SWang.Lin@Sun.COM 	case ATH9K_ANT_FIXED_B:
419*9999SWang.Lin@Sun.COM 		bank6SelMask =
420*9999SWang.Lin@Sun.COM 		    (ahp-> ah_antennaSwitchSwap & ANTSWAP_AB) ? REDUCE_CHAIN_1 :
421*9999SWang.Lin@Sun.COM 		    REDUCE_CHAIN_0;
422*9999SWang.Lin@Sun.COM 		break;
423*9999SWang.Lin@Sun.COM 	case ATH9K_ANT_VARIABLE:
424*9999SWang.Lin@Sun.COM 	default:
425*9999SWang.Lin@Sun.COM 		return;
426*9999SWang.Lin@Sun.COM 	}
427*9999SWang.Lin@Sun.COM 
428*9999SWang.Lin@Sun.COM 	for (i = 0; i < ahp->ah_iniBank6.ia_rows; i++)
429*9999SWang.Lin@Sun.COM 		bank6Temp[i] = ahp->ah_analogBank6Data[i];
430*9999SWang.Lin@Sun.COM 
431*9999SWang.Lin@Sun.COM 	REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask);
432*9999SWang.Lin@Sun.COM 
433*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0);
434*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0);
435*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0);
436*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0);
437*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0);
438*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0);
439*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0);
440*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0);
441*9999SWang.Lin@Sun.COM 	ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0);
442*9999SWang.Lin@Sun.COM 
443*9999SWang.Lin@Sun.COM 	REG_WRITE_RF_ARRAY(&ahp->ah_iniBank6, bank6Temp, regWrites);
444*9999SWang.Lin@Sun.COM 
445*9999SWang.Lin@Sun.COM 	REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053);
446*9999SWang.Lin@Sun.COM #ifdef ALTER_SWITCH
447*9999SWang.Lin@Sun.COM 	REG_WRITE(ah, PHY_SWITCH_CHAIN_0,
448*9999SWang.Lin@Sun.COM 	    (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38)
449*9999SWang.Lin@Sun.COM 	    | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38));
450*9999SWang.Lin@Sun.COM #endif
451*9999SWang.Lin@Sun.COM }
452