diff options
author | Nick Kossifidis <mick@madwifi-project.org> | 2009-02-08 23:06:34 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-13 13:44:45 -0500 |
commit | 8892e4ec62f1553d36c88e613890aa4d7c5a372e (patch) | |
tree | 3f7976379576a11d05d1723f3bcf8a03f821413a /drivers/net/wireless/ath5k/phy.c | |
parent | 6f3b414aca060a847e243f676b8601731938eb48 (diff) |
ath5k: Update RF Buffer handling
* Use the new way to modify rf buffer and put some rf buffer
documentation on rfbufer.h
* Merge all rf regs functions to one
* Sync with legacy HAL and Sam's HAL
* Set gain_F settings so that gain_F optimization engine works
on RF5111/RF5112 (note that both HALs only use step 0 for RF5111
and they don't use gain_F optimization for this chip, code is
there but is never used)
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/phy.c')
-rw-r--r-- | drivers/net/wireless/ath5k/phy.c | 571 |
1 files changed, 298 insertions, 273 deletions
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 2543a718fe3f..81f5bebc48b1 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -32,48 +32,80 @@ | |||
32 | /* | 32 | /* |
33 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER | 33 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER |
34 | */ | 34 | */ |
35 | static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits, | 35 | static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, |
36 | u32 first, u32 col, bool set) | 36 | const struct ath5k_rf_reg *rf_regs, |
37 | u32 val, u8 reg_id, bool set) | ||
37 | { | 38 | { |
38 | u32 mask, entry, last, data, shift, position; | 39 | const struct ath5k_rf_reg *rfreg = NULL; |
39 | s32 left; | 40 | u8 offset, bank, num_bits, col, position; |
41 | u16 entry; | ||
42 | u32 mask, data, last_bit, bits_shifted, first_bit; | ||
43 | u32 *rfb; | ||
44 | s32 bits_left; | ||
40 | int i; | 45 | int i; |
41 | 46 | ||
42 | data = 0; | 47 | data = 0; |
48 | rfb = ah->ah_rf_banks; | ||
43 | 49 | ||
44 | if (rf == NULL) | 50 | for (i = 0; i < ah->ah_rf_regs_count; i++) { |
51 | if (rf_regs[i].index == reg_id) { | ||
52 | rfreg = &rf_regs[i]; | ||
53 | break; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | if (rfb == NULL || rfreg == NULL) { | ||
58 | ATH5K_PRINTF("Rf register not found!\n"); | ||
45 | /* should not happen */ | 59 | /* should not happen */ |
46 | return 0; | 60 | return 0; |
61 | } | ||
62 | |||
63 | bank = rfreg->bank; | ||
64 | num_bits = rfreg->field.len; | ||
65 | first_bit = rfreg->field.pos; | ||
66 | col = rfreg->field.col; | ||
67 | |||
68 | /* first_bit is an offset from bank's | ||
69 | * start. Since we have all banks on | ||
70 | * the same array, we use this offset | ||
71 | * to mark each bank's start */ | ||
72 | offset = ah->ah_offset[bank]; | ||
47 | 73 | ||
48 | if (!(col <= 3 && bits <= 32 && first + bits <= 319)) { | 74 | /* Boundary check */ |
75 | if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) { | ||
49 | ATH5K_PRINTF("invalid values at offset %u\n", offset); | 76 | ATH5K_PRINTF("invalid values at offset %u\n", offset); |
50 | return 0; | 77 | return 0; |
51 | } | 78 | } |
52 | 79 | ||
53 | entry = ((first - 1) / 8) + offset; | 80 | entry = ((first_bit - 1) / 8) + offset; |
54 | position = (first - 1) % 8; | 81 | position = (first_bit - 1) % 8; |
55 | 82 | ||
56 | if (set) | 83 | if (set) |
57 | data = ath5k_hw_bitswap(reg, bits); | 84 | data = ath5k_hw_bitswap(val, num_bits); |
85 | |||
86 | for (bits_shifted = 0, bits_left = num_bits; bits_left > 0; | ||
87 | position = 0, entry++) { | ||
88 | |||
89 | last_bit = (position + bits_left > 8) ? 8 : | ||
90 | position + bits_left; | ||
58 | 91 | ||
59 | for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) { | 92 | mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) << |
60 | last = (position + left > 8) ? 8 : position + left; | 93 | (col * 8); |
61 | mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8); | ||
62 | 94 | ||
63 | if (set) { | 95 | if (set) { |
64 | rf[entry] &= ~mask; | 96 | rfb[entry] &= ~mask; |
65 | rf[entry] |= ((data << position) << (col * 8)) & mask; | 97 | rfb[entry] |= ((data << position) << (col * 8)) & mask; |
66 | data >>= (8 - position); | 98 | data >>= (8 - position); |
67 | } else { | 99 | } else { |
68 | data = (((rf[entry] & mask) >> (col * 8)) >> position) | 100 | data |= (((rfb[entry] & mask) >> (col * 8)) >> position) |
69 | << shift; | 101 | << bits_shifted; |
70 | shift += last - position; | 102 | bits_shifted += last_bit - position; |
71 | } | 103 | } |
72 | 104 | ||
73 | left -= 8 - position; | 105 | bits_left -= 8 - position; |
74 | } | 106 | } |
75 | 107 | ||
76 | data = set ? 1 : ath5k_hw_bitswap(data, bits); | 108 | data = set ? 1 : ath5k_hw_bitswap(data, num_bits); |
77 | 109 | ||
78 | return data; | 110 | return data; |
79 | } | 111 | } |
@@ -167,6 +199,7 @@ static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) | |||
167 | u32 *rf; | 199 | u32 *rf; |
168 | const struct ath5k_gain_opt *go; | 200 | const struct ath5k_gain_opt *go; |
169 | const struct ath5k_gain_opt_step *g_step; | 201 | const struct ath5k_gain_opt_step *g_step; |
202 | const struct ath5k_rf_reg *rf_regs; | ||
170 | 203 | ||
171 | /* Only RF5112 Rev. 2 supports it */ | 204 | /* Only RF5112 Rev. 2 supports it */ |
172 | if ((ah->ah_radio != AR5K_RF5112) || | 205 | if ((ah->ah_radio != AR5K_RF5112) || |
@@ -174,6 +207,8 @@ static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) | |||
174 | return 0; | 207 | return 0; |
175 | 208 | ||
176 | go = &rfgain_opt_5112; | 209 | go = &rfgain_opt_5112; |
210 | rf_regs = rf_regs_5112a; | ||
211 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); | ||
177 | 212 | ||
178 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; | 213 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; |
179 | 214 | ||
@@ -184,11 +219,11 @@ static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) | |||
184 | ah->ah_gain.g_f_corr = 0; | 219 | ah->ah_gain.g_f_corr = 0; |
185 | 220 | ||
186 | /* No VGA (Variable Gain Amplifier) override, skip */ | 221 | /* No VGA (Variable Gain Amplifier) override, skip */ |
187 | if (ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0, false) != 1) | 222 | if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1) |
188 | return 0; | 223 | return 0; |
189 | 224 | ||
190 | /* Mix gain stepping */ | 225 | /* Mix gain stepping */ |
191 | step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 4, 32, 0, false); | 226 | step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false); |
192 | 227 | ||
193 | /* Mix gain override */ | 228 | /* Mix gain override */ |
194 | mix = g_step->gos_param[0]; | 229 | mix = g_step->gos_param[0]; |
@@ -217,6 +252,7 @@ static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) | |||
217 | * their detection window) so we must ignore it */ | 252 | * their detection window) so we must ignore it */ |
218 | static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | 253 | static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) |
219 | { | 254 | { |
255 | const struct ath5k_rf_reg *rf_regs; | ||
220 | u32 step, mix_ovr, level[4]; | 256 | u32 step, mix_ovr, level[4]; |
221 | u32 *rf; | 257 | u32 *rf; |
222 | 258 | ||
@@ -226,8 +262,13 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
226 | rf = ah->ah_rf_banks; | 262 | rf = ah->ah_rf_banks; |
227 | 263 | ||
228 | if (ah->ah_radio == AR5K_RF5111) { | 264 | if (ah->ah_radio == AR5K_RF5111) { |
229 | step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 6, 37, 0, | 265 | |
230 | false); | 266 | rf_regs = rf_regs_5111; |
267 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); | ||
268 | |||
269 | step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP, | ||
270 | false); | ||
271 | |||
231 | level[0] = 0; | 272 | level[0] = 0; |
232 | level[1] = (step == 63) ? 50 : step + 4; | 273 | level[1] = (step == 63) ? 50 : step + 4; |
233 | level[2] = (step != 63) ? 64 : level[0]; | 274 | level[2] = (step != 63) ? 64 : level[0]; |
@@ -238,8 +279,13 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
238 | ah->ah_gain.g_low = level[0] + | 279 | ah->ah_gain.g_low = level[0] + |
239 | (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0); | 280 | (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0); |
240 | } else { | 281 | } else { |
241 | mix_ovr = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0, | 282 | |
242 | false); | 283 | rf_regs = rf_regs_5112; |
284 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); | ||
285 | |||
286 | mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, | ||
287 | false); | ||
288 | |||
243 | level[0] = level[2] = 0; | 289 | level[0] = level[2] = 0; |
244 | 290 | ||
245 | if (mix_ovr == 1) { | 291 | if (mix_ovr == 1) { |
@@ -451,341 +497,320 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
451 | * RF Registers setup * | 497 | * RF Registers setup * |
452 | \********************/ | 498 | \********************/ |
453 | 499 | ||
500 | |||
454 | /* | 501 | /* |
455 | * Read EEPROM Calibration data, modify RF Banks and Initialize RF5111 | 502 | * Setup RF registers by writing rf buffer on hw |
456 | */ | 503 | */ |
457 | static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah, | 504 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
458 | struct ieee80211_channel *channel, unsigned int mode) | 505 | unsigned int mode) |
459 | { | 506 | { |
507 | const struct ath5k_rf_reg *rf_regs; | ||
508 | const struct ath5k_ini_rfbuffer *ini_rfb; | ||
509 | const struct ath5k_gain_opt *go = NULL; | ||
510 | const struct ath5k_gain_opt_step *g_step; | ||
460 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 511 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
461 | u32 *rf; | 512 | u8 ee_mode = 0; |
462 | const unsigned int rf_size = ARRAY_SIZE(rfb_5111); | 513 | u32 *rfb; |
463 | unsigned int i; | 514 | int i, obdb = -1, bank = -1; |
464 | int obdb = -1, bank = -1; | ||
465 | u32 ee_mode; | ||
466 | 515 | ||
467 | AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX); | 516 | switch (ah->ah_radio) { |
517 | case AR5K_RF5111: | ||
518 | rf_regs = rf_regs_5111; | ||
519 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); | ||
520 | ini_rfb = rfb_5111; | ||
521 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111); | ||
522 | go = &rfgain_opt_5111; | ||
523 | break; | ||
524 | case AR5K_RF5112: | ||
525 | if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { | ||
526 | rf_regs = rf_regs_5112a; | ||
527 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); | ||
528 | ini_rfb = rfb_5112a; | ||
529 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a); | ||
530 | } else { | ||
531 | rf_regs = rf_regs_5112; | ||
532 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); | ||
533 | ini_rfb = rfb_5112; | ||
534 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112); | ||
535 | } | ||
536 | go = &rfgain_opt_5112; | ||
537 | break; | ||
538 | case AR5K_RF2413: | ||
539 | rf_regs = rf_regs_2413; | ||
540 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413); | ||
541 | ini_rfb = rfb_2413; | ||
542 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413); | ||
543 | break; | ||
544 | case AR5K_RF2316: | ||
545 | rf_regs = rf_regs_2316; | ||
546 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316); | ||
547 | ini_rfb = rfb_2316; | ||
548 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316); | ||
549 | break; | ||
550 | case AR5K_RF5413: | ||
551 | rf_regs = rf_regs_5413; | ||
552 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413); | ||
553 | ini_rfb = rfb_5413; | ||
554 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413); | ||
555 | break; | ||
556 | case AR5K_RF2317: | ||
557 | rf_regs = rf_regs_2425; | ||
558 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); | ||
559 | ini_rfb = rfb_2317; | ||
560 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317); | ||
561 | break; | ||
562 | case AR5K_RF2425: | ||
563 | rf_regs = rf_regs_2425; | ||
564 | ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); | ||
565 | if (ah->ah_mac_srev < AR5K_SREV_AR2417) { | ||
566 | ini_rfb = rfb_2425; | ||
567 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425); | ||
568 | } else { | ||
569 | ini_rfb = rfb_2417; | ||
570 | ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417); | ||
571 | } | ||
572 | break; | ||
573 | default: | ||
574 | return -EINVAL; | ||
575 | } | ||
468 | 576 | ||
469 | rf = ah->ah_rf_banks; | 577 | /* If it's the first time we set rf buffer, allocate |
578 | * ah->ah_rf_banks based on ah->ah_rf_banks_size | ||
579 | * we set above */ | ||
580 | if (ah->ah_rf_banks == NULL) { | ||
581 | ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size, | ||
582 | GFP_KERNEL); | ||
583 | if (ah->ah_rf_banks == NULL) { | ||
584 | ATH5K_ERR(ah->ah_sc, "out of memory\n"); | ||
585 | return -ENOMEM; | ||
586 | } | ||
587 | } | ||
470 | 588 | ||
471 | /* Copy values to modify them */ | 589 | /* Copy values to modify them */ |
472 | for (i = 0; i < rf_size; i++) { | 590 | rfb = ah->ah_rf_banks; |
473 | if (rfb_5111[i].rfb_bank >= AR5K_RF5111_INI_RF_MAX_BANKS) { | 591 | |
592 | for (i = 0; i < ah->ah_rf_banks_size; i++) { | ||
593 | if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) { | ||
474 | ATH5K_ERR(ah->ah_sc, "invalid bank\n"); | 594 | ATH5K_ERR(ah->ah_sc, "invalid bank\n"); |
475 | return -EINVAL; | 595 | return -EINVAL; |
476 | } | 596 | } |
477 | 597 | ||
478 | if (bank != rfb_5111[i].rfb_bank) { | 598 | /* Bank changed, write down the offset */ |
479 | bank = rfb_5111[i].rfb_bank; | 599 | if (bank != ini_rfb[i].rfb_bank) { |
600 | bank = ini_rfb[i].rfb_bank; | ||
480 | ah->ah_offset[bank] = i; | 601 | ah->ah_offset[bank] = i; |
481 | } | 602 | } |
482 | 603 | ||
483 | rf[i] = rfb_5111[i].rfb_mode_data[mode]; | 604 | rfb[i] = ini_rfb[i].rfb_mode_data[mode]; |
484 | } | 605 | } |
485 | 606 | ||
486 | /* Modify bank 0 */ | 607 | /* Set Output and Driver bias current (OB/DB) */ |
487 | if (channel->hw_value & CHANNEL_2GHZ) { | 608 | if (channel->hw_value & CHANNEL_2GHZ) { |
609 | |||
488 | if (channel->hw_value & CHANNEL_CCK) | 610 | if (channel->hw_value & CHANNEL_CCK) |
489 | ee_mode = AR5K_EEPROM_MODE_11B; | 611 | ee_mode = AR5K_EEPROM_MODE_11B; |
490 | else | 612 | else |
491 | ee_mode = AR5K_EEPROM_MODE_11G; | 613 | ee_mode = AR5K_EEPROM_MODE_11G; |
492 | obdb = 0; | ||
493 | 614 | ||
494 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0], | 615 | /* For RF511X/RF211X combination we |
495 | ee->ee_ob[ee_mode][obdb], 3, 119, 0, true)) | 616 | * use b_OB and b_DB parameters stored |
496 | return -EINVAL; | 617 | * in eeprom on ee->ee_ob[ee_mode][0] |
618 | * | ||
619 | * For all other chips we use OB/DB for 2Ghz | ||
620 | * stored in the b/g modal section just like | ||
621 | * 802.11a on ee->ee_ob[ee_mode][1] */ | ||
622 | if ((ah->ah_radio == AR5K_RF5111) || | ||
623 | (ah->ah_radio == AR5K_RF5112)) | ||
624 | obdb = 0; | ||
625 | else | ||
626 | obdb = 1; | ||
497 | 627 | ||
498 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0], | 628 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], |
499 | ee->ee_ob[ee_mode][obdb], 3, 122, 0, true)) | 629 | AR5K_RF_OB_2GHZ, true); |
500 | return -EINVAL; | ||
501 | 630 | ||
502 | obdb = 1; | 631 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], |
503 | /* Modify bank 6 */ | 632 | AR5K_RF_DB_2GHZ, true); |
504 | } else { | 633 | |
505 | /* For 11a, Turbo and XR */ | 634 | /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */ |
635 | } else if ((channel->hw_value & CHANNEL_5GHZ) || | ||
636 | (ah->ah_radio == AR5K_RF5111)) { | ||
637 | |||
638 | /* For 11a, Turbo and XR we need to choose | ||
639 | * OB/DB based on frequency range */ | ||
506 | ee_mode = AR5K_EEPROM_MODE_11A; | 640 | ee_mode = AR5K_EEPROM_MODE_11A; |
507 | obdb = channel->center_freq >= 5725 ? 3 : | 641 | obdb = channel->center_freq >= 5725 ? 3 : |
508 | (channel->center_freq >= 5500 ? 2 : | 642 | (channel->center_freq >= 5500 ? 2 : |
509 | (channel->center_freq >= 5260 ? 1 : | 643 | (channel->center_freq >= 5260 ? 1 : |
510 | (channel->center_freq > 4000 ? 0 : -1))); | 644 | (channel->center_freq > 4000 ? 0 : -1))); |
511 | 645 | ||
512 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 646 | if (obdb < 0) |
513 | ee->ee_pwd_84, 1, 51, 3, true)) | ||
514 | return -EINVAL; | 647 | return -EINVAL; |
515 | 648 | ||
516 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 649 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], |
517 | ee->ee_pwd_90, 1, 45, 3, true)) | 650 | AR5K_RF_OB_5GHZ, true); |
518 | return -EINVAL; | ||
519 | } | ||
520 | 651 | ||
521 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 652 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], |
522 | !ee->ee_xpd[ee_mode], 1, 95, 0, true)) | 653 | AR5K_RF_DB_5GHZ, true); |
523 | return -EINVAL; | 654 | } |
524 | 655 | ||
525 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 656 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; |
526 | ee->ee_x_gain[ee_mode], 4, 96, 0, true)) | ||
527 | return -EINVAL; | ||
528 | 657 | ||
529 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ? | 658 | /* Bank Modifications (chip-specific) */ |
530 | ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, true)) | 659 | if (ah->ah_radio == AR5K_RF5111) { |
531 | return -EINVAL; | ||
532 | 660 | ||
533 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ? | 661 | /* Set gain_F settings according to current step */ |
534 | ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, true)) | 662 | if (channel->hw_value & CHANNEL_OFDM) { |
535 | return -EINVAL; | ||
536 | 663 | ||
537 | /* Modify bank 7 */ | 664 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, |
538 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7], | 665 | AR5K_PHY_FRAME_CTL_TX_CLIP, |
539 | ee->ee_i_gain[ee_mode], 6, 29, 0, true)) | 666 | g_step->gos_param[0]); |
540 | return -EINVAL; | ||
541 | 667 | ||
542 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7], | 668 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], |
543 | ee->ee_xpd[ee_mode], 1, 4, 0, true)) | 669 | AR5K_RF_PWD_90, true); |
544 | return -EINVAL; | ||
545 | 670 | ||
546 | /* Write RF values */ | 671 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], |
547 | for (i = 0; i < rf_size; i++) { | 672 | AR5K_RF_PWD_84, true); |
548 | AR5K_REG_WAIT(i); | ||
549 | ath5k_hw_reg_write(ah, rf[i], rfb_5111[i].rfb_ctrl_register); | ||
550 | } | ||
551 | 673 | ||
552 | ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; | 674 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], |
675 | AR5K_RF_RFGAIN_SEL, true); | ||
553 | 676 | ||
554 | return 0; | 677 | /* We programmed gain_F parameters, switch back |
555 | } | 678 | * to active state */ |
679 | ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; | ||
556 | 680 | ||
557 | /* | 681 | } |
558 | * Read EEPROM Calibration data, modify RF Banks and Initialize RF5112 | ||
559 | */ | ||
560 | static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, | ||
561 | struct ieee80211_channel *channel, unsigned int mode) | ||
562 | { | ||
563 | const struct ath5k_ini_rfbuffer *rf_ini; | ||
564 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
565 | u32 *rf; | ||
566 | unsigned int rf_size, i; | ||
567 | int obdb = -1, bank = -1; | ||
568 | u32 ee_mode; | ||
569 | 682 | ||
570 | AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX); | 683 | /* Bank 6/7 setup */ |
571 | 684 | ||
572 | rf = ah->ah_rf_banks; | 685 | ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode], |
686 | AR5K_RF_PWD_XPD, true); | ||
573 | 687 | ||
574 | if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { | 688 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode], |
575 | rf_ini = rfb_5112a; | 689 | AR5K_RF_XPD_GAIN, true); |
576 | rf_size = ARRAY_SIZE(rfb_5112a); | ||
577 | } else { | ||
578 | rf_ini = rfb_5112; | ||
579 | rf_size = ARRAY_SIZE(rfb_5112); | ||
580 | } | ||
581 | 690 | ||
582 | /* Copy values to modify them */ | 691 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], |
583 | for (i = 0; i < rf_size; i++) { | 692 | AR5K_RF_GAIN_I, true); |
584 | if (rf_ini[i].rfb_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) { | ||
585 | ATH5K_ERR(ah->ah_sc, "invalid bank\n"); | ||
586 | return -EINVAL; | ||
587 | } | ||
588 | 693 | ||
589 | if (bank != rf_ini[i].rfb_bank) { | 694 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], |
590 | bank = rf_ini[i].rfb_bank; | 695 | AR5K_RF_PLO_SEL, true); |
591 | ah->ah_offset[bank] = i; | ||
592 | } | ||
593 | 696 | ||
594 | rf[i] = rf_ini[i].rfb_mode_data[mode]; | 697 | /* TODO: Half/quarter channel support */ |
595 | } | 698 | } |
596 | 699 | ||
597 | /* Modify bank 6 */ | 700 | if (ah->ah_radio == AR5K_RF5112) { |
598 | if (channel->hw_value & CHANNEL_2GHZ) { | ||
599 | if (channel->hw_value & CHANNEL_OFDM) | ||
600 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
601 | else | ||
602 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
603 | obdb = 0; | ||
604 | 701 | ||
605 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 702 | /* Set gain_F settings according to current step */ |
606 | ee->ee_ob[ee_mode][obdb], 3, 287, 0, true)) | 703 | if (channel->hw_value & CHANNEL_OFDM) { |
607 | return -EINVAL; | ||
608 | 704 | ||
609 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 705 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0], |
610 | ee->ee_ob[ee_mode][obdb], 3, 290, 0, true)) | 706 | AR5K_RF_MIXGAIN_OVR, true); |
611 | return -EINVAL; | ||
612 | } else { | ||
613 | /* For 11a, Turbo and XR */ | ||
614 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
615 | obdb = channel->center_freq >= 5725 ? 3 : | ||
616 | (channel->center_freq >= 5500 ? 2 : | ||
617 | (channel->center_freq >= 5260 ? 1 : | ||
618 | (channel->center_freq > 4000 ? 0 : -1))); | ||
619 | 707 | ||
620 | if (obdb == -1) | 708 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], |
621 | return -EINVAL; | 709 | AR5K_RF_PWD_138, true); |
622 | 710 | ||
623 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 711 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], |
624 | ee->ee_ob[ee_mode][obdb], 3, 279, 0, true)) | 712 | AR5K_RF_PWD_137, true); |
625 | return -EINVAL; | ||
626 | 713 | ||
627 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 714 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], |
628 | ee->ee_ob[ee_mode][obdb], 3, 282, 0, true)) | 715 | AR5K_RF_PWD_136, true); |
629 | return -EINVAL; | ||
630 | } | ||
631 | 716 | ||
632 | ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 717 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4], |
633 | ee->ee_x_gain[ee_mode], 2, 270, 0, true); | 718 | AR5K_RF_PWD_132, true); |
634 | ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | ||
635 | ee->ee_x_gain[ee_mode], 2, 257, 0, true); | ||
636 | 719 | ||
637 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], | 720 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5], |
638 | ee->ee_xpd[ee_mode], 1, 302, 0, true)) | 721 | AR5K_RF_PWD_131, true); |
639 | return -EINVAL; | ||
640 | 722 | ||
641 | /* Modify bank 7 */ | 723 | ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6], |
642 | if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7], | 724 | AR5K_RF_PWD_130, true); |
643 | ee->ee_i_gain[ee_mode], 6, 14, 0, true)) | ||
644 | return -EINVAL; | ||
645 | 725 | ||
646 | /* Write RF values */ | 726 | /* We programmed gain_F parameters, switch back |
647 | for (i = 0; i < rf_size; i++) | 727 | * to active state */ |
648 | ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rfb_ctrl_register); | 728 | ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; |
729 | } | ||
649 | 730 | ||
731 | /* Bank 6/7 setup */ | ||
650 | 732 | ||
651 | ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; | 733 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], |
734 | AR5K_RF_XPD_SEL, true); | ||
652 | 735 | ||
653 | return 0; | 736 | if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { |
654 | } | 737 | /* Rev. 1 supports only one xpd */ |
738 | ath5k_hw_rfb_op(ah, rf_regs, | ||
739 | ee->ee_x_gain[ee_mode], | ||
740 | AR5K_RF_XPD_GAIN, true); | ||
655 | 741 | ||
656 | /* | 742 | } else { |
657 | * Initialize RF5413/5414 and future chips | 743 | /* TODO: Set high and low gain bits */ |
658 | * (until we come up with a better solution) | 744 | ath5k_hw_rfb_op(ah, rf_regs, |
659 | */ | 745 | ee->ee_x_gain[ee_mode], |
660 | static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, | 746 | AR5K_RF_PD_GAIN_LO, true); |
661 | struct ieee80211_channel *channel, unsigned int mode) | 747 | ath5k_hw_rfb_op(ah, rf_regs, |
662 | { | 748 | ee->ee_x_gain[ee_mode], |
663 | const struct ath5k_ini_rfbuffer *rf_ini; | 749 | AR5K_RF_PD_GAIN_HI, true); |
664 | u32 *rf; | ||
665 | unsigned int rf_size, i; | ||
666 | int bank = -1; | ||
667 | 750 | ||
668 | AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX); | 751 | /* Lower synth voltage on Rev 2 */ |
752 | ath5k_hw_rfb_op(ah, rf_regs, 2, | ||
753 | AR5K_RF_HIGH_VC_CP, true); | ||
669 | 754 | ||
670 | rf = ah->ah_rf_banks; | 755 | ath5k_hw_rfb_op(ah, rf_regs, 2, |
756 | AR5K_RF_MID_VC_CP, true); | ||
671 | 757 | ||
672 | switch (ah->ah_radio) { | 758 | ath5k_hw_rfb_op(ah, rf_regs, 2, |
673 | case AR5K_RF5413: | 759 | AR5K_RF_LOW_VC_CP, true); |
674 | rf_ini = rfb_5413; | ||
675 | rf_size = ARRAY_SIZE(rfb_5413); | ||
676 | break; | ||
677 | case AR5K_RF2413: | ||
678 | rf_ini = rfb_2413; | ||
679 | rf_size = ARRAY_SIZE(rfb_2413); | ||
680 | 760 | ||
681 | if (mode < 2) { | 761 | ath5k_hw_rfb_op(ah, rf_regs, 2, |
682 | ATH5K_ERR(ah->ah_sc, | 762 | AR5K_RF_PUSH_UP, true); |
683 | "invalid channel mode: %i\n", mode); | ||
684 | return -EINVAL; | ||
685 | } | ||
686 | 763 | ||
687 | break; | 764 | /* Decrease power consumption on 5213+ BaseBand */ |
688 | case AR5K_RF2425: | 765 | if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { |
689 | rf_ini = rfb_2425; | 766 | ath5k_hw_rfb_op(ah, rf_regs, 1, |
690 | rf_size = ARRAY_SIZE(rfb_2425); | 767 | AR5K_RF_PAD2GND, true); |
691 | 768 | ||
692 | if (mode < 2) { | 769 | ath5k_hw_rfb_op(ah, rf_regs, 1, |
693 | ATH5K_ERR(ah->ah_sc, | 770 | AR5K_RF_XB2_LVL, true); |
694 | "invalid channel mode: %i\n", mode); | ||
695 | return -EINVAL; | ||
696 | } | ||
697 | 771 | ||
698 | break; | 772 | ath5k_hw_rfb_op(ah, rf_regs, 1, |
699 | default: | 773 | AR5K_RF_XB5_LVL, true); |
700 | return -EINVAL; | ||
701 | } | ||
702 | 774 | ||
703 | /* Copy values to modify them */ | 775 | ath5k_hw_rfb_op(ah, rf_regs, 1, |
704 | for (i = 0; i < rf_size; i++) { | 776 | AR5K_RF_PWD_167, true); |
705 | if (rf_ini[i].rfb_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) { | ||
706 | ATH5K_ERR(ah->ah_sc, "invalid bank\n"); | ||
707 | return -EINVAL; | ||
708 | } | ||
709 | 777 | ||
710 | if (bank != rf_ini[i].rfb_bank) { | 778 | ath5k_hw_rfb_op(ah, rf_regs, 1, |
711 | bank = rf_ini[i].rfb_bank; | 779 | AR5K_RF_PWD_166, true); |
712 | ah->ah_offset[bank] = i; | 780 | } |
713 | } | 781 | } |
714 | 782 | ||
715 | rf[i] = rf_ini[i].rfb_mode_data[mode]; | 783 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], |
716 | } | 784 | AR5K_RF_GAIN_I, true); |
717 | 785 | ||
718 | /* | 786 | /* TODO: Half/quarter channel support */ |
719 | * After compairing dumps from different cards | ||
720 | * we get the same RF_BUFFER settings (diff returns | ||
721 | * 0 lines). It seems that RF_BUFFER settings are static | ||
722 | * and are written unmodified (no EEPROM stuff | ||
723 | * is used because calibration data would be | ||
724 | * different between different cards and would result | ||
725 | * different RF_BUFFER settings) | ||
726 | */ | ||
727 | 787 | ||
728 | /* Write RF values */ | 788 | } |
729 | for (i = 0; i < rf_size; i++) | ||
730 | ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rfb_ctrl_register); | ||
731 | 789 | ||
732 | return 0; | 790 | if (ah->ah_radio == AR5K_RF5413 && |
733 | } | 791 | channel->hw_value & CHANNEL_2GHZ) { |
734 | 792 | ||
735 | /* | 793 | ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE, |
736 | * Initialize RF | 794 | true); |
737 | */ | ||
738 | int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
739 | unsigned int mode) | ||
740 | { | ||
741 | int (*func)(struct ath5k_hw *, struct ieee80211_channel *, unsigned int); | ||
742 | int ret; | ||
743 | 795 | ||
744 | switch (ah->ah_radio) { | 796 | /* Set optimum value for early revisions (on pci-e chips) */ |
745 | case AR5K_RF5111: | 797 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424 && |
746 | ah->ah_rf_banks_size = sizeof(rfb_5111); | 798 | ah->ah_mac_srev < AR5K_SREV_AR5413) |
747 | func = ath5k_hw_rf5111_rfregs; | 799 | ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3), |
748 | break; | 800 | AR5K_RF_PWD_ICLOBUF_2G, true); |
749 | case AR5K_RF5112: | ||
750 | if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) | ||
751 | ah->ah_rf_banks_size = sizeof(rfb_5112a); | ||
752 | else | ||
753 | ah->ah_rf_banks_size = sizeof(rfb_5112); | ||
754 | func = ath5k_hw_rf5112_rfregs; | ||
755 | break; | ||
756 | case AR5K_RF5413: | ||
757 | ah->ah_rf_banks_size = sizeof(rfb_5413); | ||
758 | func = ath5k_hw_rf5413_rfregs; | ||
759 | break; | ||
760 | case AR5K_RF2413: | ||
761 | ah->ah_rf_banks_size = sizeof(rfb_2413); | ||
762 | func = ath5k_hw_rf5413_rfregs; | ||
763 | break; | ||
764 | case AR5K_RF2425: | ||
765 | ah->ah_rf_banks_size = sizeof(rfb_2425); | ||
766 | func = ath5k_hw_rf5413_rfregs; | ||
767 | break; | ||
768 | default: | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | 801 | ||
772 | if (ah->ah_rf_banks == NULL) { | ||
773 | /* XXX do extra checks? */ | ||
774 | ah->ah_rf_banks = kmalloc(ah->ah_rf_banks_size, GFP_KERNEL); | ||
775 | if (ah->ah_rf_banks == NULL) { | ||
776 | ATH5K_ERR(ah->ah_sc, "out of memory\n"); | ||
777 | return -ENOMEM; | ||
778 | } | ||
779 | } | 802 | } |
780 | 803 | ||
781 | ret = func(ah, channel, mode); | 804 | /* Write RF banks on hw */ |
805 | for (i = 0; i < ah->ah_rf_banks_size; i++) { | ||
806 | AR5K_REG_WAIT(i); | ||
807 | ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register); | ||
808 | } | ||
782 | 809 | ||
783 | return ret; | 810 | return 0; |
784 | } | 811 | } |
785 | 812 | ||
786 | 813 | ||
787 | |||
788 | |||
789 | /**************************\ | 814 | /**************************\ |
790 | PHY/RF channel functions | 815 | PHY/RF channel functions |
791 | \**************************/ | 816 | \**************************/ |