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