diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/phy.c | 166 |
2 files changed, 170 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 48b6c71144a7..007b41426b27 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -148,6 +148,15 @@ enum wireless_mode { | |||
148 | ATH9K_MODE_MAX, | 148 | ATH9K_MODE_MAX, |
149 | }; | 149 | }; |
150 | 150 | ||
151 | /** | ||
152 | * ath9k_ant_setting - transmit antenna settings | ||
153 | * | ||
154 | * Configures the antenna setting to use for transmit. | ||
155 | * | ||
156 | * @ATH9K_ANT_VARIABLE: this means transmit on all active antennas | ||
157 | * @ATH9K_ANT_FIXED_A: this means transmit on the first antenna only | ||
158 | * @ATH9K_ANT_FIXED_B: this means transmit on the second antenna only | ||
159 | */ | ||
151 | enum ath9k_ant_setting { | 160 | enum ath9k_ant_setting { |
152 | ATH9K_ANT_VARIABLE = 0, | 161 | ATH9K_ANT_VARIABLE = 0, |
153 | ATH9K_ANT_FIXED_A, | 162 | ATH9K_ANT_FIXED_A, |
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index 72a17c43a5a0..9e515033b878 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c | |||
@@ -14,8 +14,44 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | /** | ||
18 | * DOC: Programming Atheros 802.11n analog front end radios | ||
19 | * | ||
20 | * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express | ||
21 | * devices have either an external AR2133 analog front end radio for single | ||
22 | * band 2.4 GHz communication or an AR5133 analog front end radio for dual | ||
23 | * band 2.4 GHz / 5 GHz communication. | ||
24 | * | ||
25 | * All devices after the AR5416 and AR5418 family starting with the AR9280 | ||
26 | * have their analog front radios, MAC/BB and host PCIe/USB interface embedded | ||
27 | * into a single-chip and require less programming. | ||
28 | * | ||
29 | * The following single-chips exist with a respective embedded radio: | ||
30 | * | ||
31 | * AR9280 - 11n dual-band 2x2 MIMO for PCIe | ||
32 | * AR9281 - 11n single-band 1x2 MIMO for PCIe | ||
33 | * AR9285 - 11n single-band 1x1 for PCIe | ||
34 | * AR9287 - 11n single-band 2x2 MIMO for PCIe | ||
35 | * | ||
36 | * AR9220 - 11n dual-band 2x2 MIMO for PCI | ||
37 | * AR9223 - 11n single-band 2x2 MIMO for PCI | ||
38 | * | ||
39 | * AR9287 - 11n single-band 1x1 MIMO for USB | ||
40 | */ | ||
41 | |||
17 | #include "hw.h" | 42 | #include "hw.h" |
18 | 43 | ||
44 | /** | ||
45 | * ath9k_hw_write_regs - ?? | ||
46 | * | ||
47 | * @ah: atheros hardware structure | ||
48 | * @modesIndex: | ||
49 | * @freqIndex: | ||
50 | * @regWrites: | ||
51 | * | ||
52 | * Used for both the chipsets with an external AR2133/AR5133 radios and | ||
53 | * single-chip devices. | ||
54 | */ | ||
19 | void | 55 | void |
20 | ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, | 56 | ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, |
21 | int regWrites) | 57 | int regWrites) |
@@ -23,6 +59,15 @@ ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, | |||
23 | REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); | 59 | REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); |
24 | } | 60 | } |
25 | 61 | ||
62 | /** | ||
63 | * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios | ||
64 | * @ah: atheros hardware stucture | ||
65 | * @chan: | ||
66 | * | ||
67 | * For the external AR2133/AR5133 radios, takes the MHz channel value and set | ||
68 | * the channel value. Assumes writes enabled to analog bus and bank6 register | ||
69 | * cache in ah->analogBank6Data. | ||
70 | */ | ||
26 | bool | 71 | bool |
27 | ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | 72 | ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) |
28 | { | 73 | { |
@@ -97,6 +142,27 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
97 | return true; | 142 | return true; |
98 | } | 143 | } |
99 | 144 | ||
145 | /** | ||
146 | * ath9k_hw_ar9280_set_channel - set channel on single-chip device | ||
147 | * @ah: atheros hardware structure | ||
148 | * @chan: | ||
149 | * | ||
150 | * This is the function to change channel on single-chip devices, that is | ||
151 | * all devices after ar9280. | ||
152 | * | ||
153 | * This function takes the channel value in MHz and sets | ||
154 | * hardware channel value. Assumes writes have been enabled to analog bus. | ||
155 | * | ||
156 | * Actual Expression, | ||
157 | * | ||
158 | * For 2GHz channel, | ||
159 | * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) | ||
160 | * (freq_ref = 40MHz) | ||
161 | * | ||
162 | * For 5GHz channel, | ||
163 | * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) | ||
164 | * (freq_ref = 40MHz/(24>>amodeRefSel)) | ||
165 | */ | ||
100 | void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | 166 | void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, |
101 | struct ath9k_channel *chan) | 167 | struct ath9k_channel *chan) |
102 | { | 168 | { |
@@ -111,7 +177,7 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | |||
111 | reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); | 177 | reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); |
112 | reg32 &= 0xc0000000; | 178 | reg32 &= 0xc0000000; |
113 | 179 | ||
114 | if (freq < 4800) { | 180 | if (freq < 4800) { /* 2 GHz, fractional mode */ |
115 | u32 txctl; | 181 | u32 txctl; |
116 | int regWrites = 0; | 182 | int regWrites = 0; |
117 | 183 | ||
@@ -122,6 +188,7 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | |||
122 | 188 | ||
123 | if (AR_SREV_9287_11_OR_LATER(ah)) { | 189 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
124 | if (freq == 2484) { | 190 | if (freq == 2484) { |
191 | /* Enable channel spreading for channel 14 */ | ||
125 | REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, | 192 | REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, |
126 | 1, regWrites); | 193 | 1, regWrites); |
127 | } else { | 194 | } else { |
@@ -155,10 +222,15 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | |||
155 | case 1: | 222 | case 1: |
156 | default: | 223 | default: |
157 | aModeRefSel = 0; | 224 | aModeRefSel = 0; |
225 | /* | ||
226 | * Enable 2G (fractional) mode for channels | ||
227 | * which are 5MHz spaced. | ||
228 | */ | ||
158 | fracMode = 1; | 229 | fracMode = 1; |
159 | refDivA = 1; | 230 | refDivA = 1; |
160 | channelSel = (freq * 0x8000) / 15; | 231 | channelSel = (freq * 0x8000) / 15; |
161 | 232 | ||
233 | /* RefDivA setting */ | ||
162 | REG_RMW_FIELD(ah, AR_AN_SYNTH9, | 234 | REG_RMW_FIELD(ah, AR_AN_SYNTH9, |
163 | AR_AN_SYNTH9_REFDIVA, refDivA); | 235 | AR_AN_SYNTH9_REFDIVA, refDivA); |
164 | 236 | ||
@@ -182,6 +254,17 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | |||
182 | ah->curchan_rad_index = -1; | 254 | ah->curchan_rad_index = -1; |
183 | } | 255 | } |
184 | 256 | ||
257 | /** | ||
258 | * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters | ||
259 | * @rfbuf: | ||
260 | * @reg32: | ||
261 | * @numBits: | ||
262 | * @firstBit: | ||
263 | * @column: | ||
264 | * | ||
265 | * Performs analog "swizzling" of parameters into their location. | ||
266 | * Used on external AR2133/AR5133 radios. | ||
267 | */ | ||
185 | static void | 268 | static void |
186 | ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, | 269 | ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, |
187 | u32 numBits, u32 firstBit, | 270 | u32 numBits, u32 firstBit, |
@@ -209,6 +292,18 @@ ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, | |||
209 | } | 292 | } |
210 | } | 293 | } |
211 | 294 | ||
295 | /* * | ||
296 | * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM | ||
297 | * @ah: atheros hardware structure | ||
298 | * @chan: | ||
299 | * @modesIndex: | ||
300 | * | ||
301 | * Used for the external AR2133/AR5133 radios. | ||
302 | * | ||
303 | * Reads the EEPROM header info from the device structure and programs | ||
304 | * all rf registers. This routine requires access to the analog | ||
305 | * rf device. This is not required for single-chip devices. | ||
306 | */ | ||
212 | bool | 307 | bool |
213 | ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, | 308 | ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, |
214 | u16 modesIndex) | 309 | u16 modesIndex) |
@@ -218,17 +313,27 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
218 | u32 ob2GHz = 0, db2GHz = 0; | 313 | u32 ob2GHz = 0, db2GHz = 0; |
219 | int regWrites = 0; | 314 | int regWrites = 0; |
220 | 315 | ||
316 | /* | ||
317 | * Software does not need to program bank data | ||
318 | * for single chip devices, that is AR9280 or anything | ||
319 | * after that. | ||
320 | */ | ||
221 | if (AR_SREV_9280_10_OR_LATER(ah)) | 321 | if (AR_SREV_9280_10_OR_LATER(ah)) |
222 | return true; | 322 | return true; |
223 | 323 | ||
324 | /* Setup rf parameters */ | ||
224 | eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); | 325 | eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); |
225 | 326 | ||
327 | /* Setup Bank 0 Write */ | ||
226 | RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); | 328 | RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); |
227 | 329 | ||
330 | /* Setup Bank 1 Write */ | ||
228 | RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); | 331 | RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); |
229 | 332 | ||
333 | /* Setup Bank 2 Write */ | ||
230 | RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); | 334 | RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); |
231 | 335 | ||
336 | /* Setup Bank 6 Write */ | ||
232 | RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, | 337 | RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, |
233 | modesIndex); | 338 | modesIndex); |
234 | { | 339 | { |
@@ -239,6 +344,7 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
239 | } | 344 | } |
240 | } | 345 | } |
241 | 346 | ||
347 | /* Only the 5 or 2 GHz OB/DB need to be set for a mode */ | ||
242 | if (eepMinorRev >= 2) { | 348 | if (eepMinorRev >= 2) { |
243 | if (IS_CHAN_2GHZ(chan)) { | 349 | if (IS_CHAN_2GHZ(chan)) { |
244 | ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); | 350 | ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); |
@@ -257,8 +363,10 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
257 | } | 363 | } |
258 | } | 364 | } |
259 | 365 | ||
366 | /* Setup Bank 7 Setup */ | ||
260 | RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); | 367 | RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); |
261 | 368 | ||
369 | /* Write Analog registers */ | ||
262 | REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, | 370 | REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, |
263 | regWrites); | 371 | regWrites); |
264 | REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, | 372 | REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, |
@@ -275,6 +383,11 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
275 | return true; | 383 | return true; |
276 | } | 384 | } |
277 | 385 | ||
386 | /** | ||
387 | * ath9k_hw_rf_free - Free memory for analog bank scratch buffers | ||
388 | * @ah: atheros hardware struture | ||
389 | * For the external AR2133/AR5133 radios. | ||
390 | */ | ||
278 | void | 391 | void |
279 | ath9k_hw_rf_free(struct ath_hw *ah) | 392 | ath9k_hw_rf_free(struct ath_hw *ah) |
280 | { | 393 | { |
@@ -295,6 +408,13 @@ ath9k_hw_rf_free(struct ath_hw *ah) | |||
295 | #undef ATH_FREE_BANK | 408 | #undef ATH_FREE_BANK |
296 | } | 409 | } |
297 | 410 | ||
411 | /** | ||
412 | * ath9k_hw_init_rf - initialize external radio structures | ||
413 | * @ah: atheros hardware structure | ||
414 | * @status: | ||
415 | * | ||
416 | * Only required for older devices with external AR2133/AR5133 radios. | ||
417 | */ | ||
298 | bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) | 418 | bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) |
299 | { | 419 | { |
300 | struct ath_common *common = ath9k_hw_common(ah); | 420 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -360,6 +480,33 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) | |||
360 | return true; | 480 | return true; |
361 | } | 481 | } |
362 | 482 | ||
483 | /** | ||
484 | * ath9k_hw_decrease_chain_power() | ||
485 | * | ||
486 | * @ah: atheros hardware structure | ||
487 | * @chan: | ||
488 | * | ||
489 | * Only used on the AR5416 and AR5418 with the external AR2133/AR5133 radios. | ||
490 | * | ||
491 | * Sets a chain internal RF path to the lowest output power. Any | ||
492 | * further writes to bank6 after this setting will override these | ||
493 | * changes. Thus this function must be the last function in the | ||
494 | * sequence to modify bank 6. | ||
495 | * | ||
496 | * This function must be called after ar5416SetRfRegs() which is | ||
497 | * called from ath9k_hw_process_ini() due to swizzling of bank 6. | ||
498 | * Depends on ah->analogBank6Data being initialized by | ||
499 | * ath9k_hw_set_rf_regs() | ||
500 | * | ||
501 | * Additional additive reduction in power - | ||
502 | * change chain's switch table so chain's tx state is actually the rx | ||
503 | * state value. May produce different results in 2GHz/5GHz as well as | ||
504 | * board to board but in general should be a reduction. | ||
505 | * | ||
506 | * Activated by #ifdef ALTER_SWITCH. Not tried yet. If so, must be | ||
507 | * called after ah->eep_ops->set_board_values() due to RMW of | ||
508 | * PHY_SWITCH_CHAIN_0. | ||
509 | */ | ||
363 | void | 510 | void |
364 | ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) | 511 | ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) |
365 | { | 512 | { |
@@ -371,26 +518,35 @@ ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) | |||
371 | case ATH9K_ANT_FIXED_A: | 518 | case ATH9K_ANT_FIXED_A: |
372 | bank6SelMask = | 519 | bank6SelMask = |
373 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? | 520 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? |
374 | REDUCE_CHAIN_0 : REDUCE_CHAIN_1; | 521 | REDUCE_CHAIN_0 : /* swapped, reduce chain 0 */ |
522 | REDUCE_CHAIN_1; /* normal, select chain 1/2 to reduce */ | ||
375 | break; | 523 | break; |
376 | case ATH9K_ANT_FIXED_B: | 524 | case ATH9K_ANT_FIXED_B: |
377 | bank6SelMask = | 525 | bank6SelMask = |
378 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? | 526 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? |
379 | REDUCE_CHAIN_1 : REDUCE_CHAIN_0; | 527 | REDUCE_CHAIN_1 : /* swapped, reduce chain 1/2 */ |
528 | REDUCE_CHAIN_0; /* normal, select chain 0 to reduce */ | ||
380 | break; | 529 | break; |
381 | case ATH9K_ANT_VARIABLE: | 530 | case ATH9K_ANT_VARIABLE: |
382 | return; | 531 | return; /* do not change anything */ |
383 | break; | 532 | break; |
384 | default: | 533 | default: |
385 | return; | 534 | return; /* do not change anything */ |
386 | break; | 535 | break; |
387 | } | 536 | } |
388 | 537 | ||
389 | for (i = 0; i < ah->iniBank6.ia_rows; i++) | 538 | for (i = 0; i < ah->iniBank6.ia_rows; i++) |
390 | bank6Temp[i] = ah->analogBank6Data[i]; | 539 | bank6Temp[i] = ah->analogBank6Data[i]; |
391 | 540 | ||
541 | /* Write Bank 5 to switch Bank 6 write to selected chain only */ | ||
392 | REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); | 542 | REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); |
393 | 543 | ||
544 | /* | ||
545 | * Modify Bank6 selected chain to use lowest amplification. | ||
546 | * Modifies the parameters to a value of 1. | ||
547 | * Depends on existing bank 6 values to be cached in | ||
548 | * ah->analogBank6Data | ||
549 | */ | ||
394 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); | 550 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); |
395 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); | 551 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); |
396 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); | 552 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); |