diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/phy.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 833 |
1 files changed, 580 insertions, 253 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6284c389ba18..55441913344d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
| @@ -29,6 +29,95 @@ | |||
| 29 | #include "rfbuffer.h" | 29 | #include "rfbuffer.h" |
| 30 | #include "rfgain.h" | 30 | #include "rfgain.h" |
| 31 | 31 | ||
| 32 | |||
| 33 | /******************\ | ||
| 34 | * Helper functions * | ||
| 35 | \******************/ | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Get the PHY Chip revision | ||
| 39 | */ | ||
| 40 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
| 41 | { | ||
| 42 | unsigned int i; | ||
| 43 | u32 srev; | ||
| 44 | u16 ret; | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Set the radio chip access register | ||
| 48 | */ | ||
| 49 | switch (chan) { | ||
| 50 | case CHANNEL_2GHZ: | ||
| 51 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
| 52 | break; | ||
| 53 | case CHANNEL_5GHZ: | ||
| 54 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
| 55 | break; | ||
| 56 | default: | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | mdelay(2); | ||
| 61 | |||
| 62 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
| 63 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
| 64 | |||
| 65 | for (i = 0; i < 8; i++) | ||
| 66 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
| 67 | |||
| 68 | if (ah->ah_version == AR5K_AR5210) { | ||
| 69 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
| 70 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
| 71 | } else { | ||
| 72 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
| 73 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
| 74 | ((srev & 0x0f) << 4), 8); | ||
| 75 | } | ||
| 76 | |||
| 77 | /* Reset to the 5GHz mode */ | ||
| 78 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
| 79 | |||
| 80 | return ret; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Check if a channel is supported | ||
| 85 | */ | ||
| 86 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
| 87 | { | ||
| 88 | /* Check if the channel is in our supported range */ | ||
| 89 | if (flags & CHANNEL_2GHZ) { | ||
| 90 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
| 91 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
| 92 | return true; | ||
| 93 | } else if (flags & CHANNEL_5GHZ) | ||
| 94 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
| 95 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
| 96 | return true; | ||
| 97 | |||
| 98 | return false; | ||
| 99 | } | ||
| 100 | |||
| 101 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | ||
| 102 | struct ieee80211_channel *channel) | ||
| 103 | { | ||
| 104 | u8 refclk_freq; | ||
| 105 | |||
| 106 | if ((ah->ah_radio == AR5K_RF5112) || | ||
| 107 | (ah->ah_radio == AR5K_RF5413) || | ||
| 108 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
| 109 | refclk_freq = 40; | ||
| 110 | else | ||
| 111 | refclk_freq = 32; | ||
| 112 | |||
| 113 | if ((channel->center_freq % refclk_freq != 0) && | ||
| 114 | ((channel->center_freq % refclk_freq < 10) || | ||
| 115 | (channel->center_freq % refclk_freq > 22))) | ||
| 116 | return true; | ||
| 117 | else | ||
| 118 | return false; | ||
| 119 | } | ||
| 120 | |||
| 32 | /* | 121 | /* |
| 33 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER | 122 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER |
| 34 | */ | 123 | */ |
| @@ -110,12 +199,124 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
| 110 | return data; | 199 | return data; |
| 111 | } | 200 | } |
| 112 | 201 | ||
| 202 | /** | ||
| 203 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | ||
| 204 | * | ||
| 205 | * @ah: the &struct ath5k_hw | ||
| 206 | * @channel: the currently set channel upon reset | ||
| 207 | * | ||
| 208 | * Write the delta slope coefficient (used on pilot tracking ?) for OFDM | ||
| 209 | * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init. | ||
| 210 | * | ||
| 211 | * Since delta slope is floating point we split it on its exponent and | ||
| 212 | * mantissa and provide these values on hw. | ||
| 213 | * | ||
| 214 | * For more infos i think this patent is related | ||
| 215 | * http://www.freepatentsonline.com/7184495.html | ||
| 216 | */ | ||
| 217 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | ||
| 218 | struct ieee80211_channel *channel) | ||
| 219 | { | ||
| 220 | /* Get exponent and mantissa and set it */ | ||
| 221 | u32 coef_scaled, coef_exp, coef_man, | ||
| 222 | ds_coef_exp, ds_coef_man, clock; | ||
| 223 | |||
| 224 | BUG_ON(!(ah->ah_version == AR5K_AR5212) || | ||
| 225 | !(channel->hw_value & CHANNEL_OFDM)); | ||
| 226 | |||
| 227 | /* Get coefficient | ||
| 228 | * ALGO: coef = (5 * clock / carrier_freq) / 2 | ||
| 229 | * we scale coef by shifting clock value by 24 for | ||
| 230 | * better precision since we use integers */ | ||
| 231 | switch (ah->ah_bwmode) { | ||
| 232 | case AR5K_BWMODE_40MHZ: | ||
| 233 | clock = 40 * 2; | ||
| 234 | break; | ||
| 235 | case AR5K_BWMODE_10MHZ: | ||
| 236 | clock = 40 / 2; | ||
| 237 | break; | ||
| 238 | case AR5K_BWMODE_5MHZ: | ||
| 239 | clock = 40 / 4; | ||
| 240 | break; | ||
| 241 | default: | ||
| 242 | clock = 40; | ||
| 243 | break; | ||
| 244 | } | ||
| 245 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | ||
| 246 | |||
| 247 | /* Get exponent | ||
| 248 | * ALGO: coef_exp = 14 - highest set bit position */ | ||
| 249 | coef_exp = ilog2(coef_scaled); | ||
| 250 | |||
| 251 | /* Doesn't make sense if it's zero*/ | ||
| 252 | if (!coef_scaled || !coef_exp) | ||
| 253 | return -EINVAL; | ||
| 254 | |||
| 255 | /* Note: we've shifted coef_scaled by 24 */ | ||
| 256 | coef_exp = 14 - (coef_exp - 24); | ||
| 257 | |||
| 258 | |||
| 259 | /* Get mantissa (significant digits) | ||
| 260 | * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ | ||
| 261 | coef_man = coef_scaled + | ||
| 262 | (1 << (24 - coef_exp - 1)); | ||
| 263 | |||
| 264 | /* Calculate delta slope coefficient exponent | ||
| 265 | * and mantissa (remove scaling) and set them on hw */ | ||
| 266 | ds_coef_man = coef_man >> (24 - coef_exp); | ||
| 267 | ds_coef_exp = coef_exp - 16; | ||
| 268 | |||
| 269 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
| 270 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | ||
| 271 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
| 272 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
| 273 | |||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
| 278 | { | ||
| 279 | /*Just a try M.F.*/ | ||
| 280 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* | ||
| 286 | * Wait for synth to settle | ||
| 287 | */ | ||
| 288 | static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | ||
| 289 | struct ieee80211_channel *channel) | ||
| 290 | { | ||
| 291 | /* | ||
| 292 | * On 5211+ read activation -> rx delay | ||
| 293 | * and use it (100ns steps). | ||
| 294 | */ | ||
| 295 | if (ah->ah_version != AR5K_AR5210) { | ||
| 296 | u32 delay; | ||
| 297 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
| 298 | AR5K_PHY_RX_DELAY_M; | ||
| 299 | delay = (channel->hw_value & CHANNEL_CCK) ? | ||
| 300 | ((delay << 2) / 22) : (delay / 10); | ||
| 301 | if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) | ||
| 302 | delay = delay << 1; | ||
| 303 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ) | ||
| 304 | delay = delay << 2; | ||
| 305 | /* XXX: /2 on turbo ? Let's be safe | ||
| 306 | * for now */ | ||
| 307 | udelay(100 + delay); | ||
| 308 | } else { | ||
| 309 | mdelay(1); | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | |||
| 113 | /**********************\ | 314 | /**********************\ |
| 114 | * RF Gain optimization * | 315 | * RF Gain optimization * |
| 115 | \**********************/ | 316 | \**********************/ |
| 116 | 317 | ||
| 117 | /* | 318 | /* |
| 118 | * This code is used to optimize rf gain on different environments | 319 | * This code is used to optimize RF gain on different environments |
| 119 | * (temperature mostly) based on feedback from a power detector. | 320 | * (temperature mostly) based on feedback from a power detector. |
| 120 | * | 321 | * |
| 121 | * It's only used on RF5111 and RF5112, later RF chips seem to have | 322 | * It's only used on RF5111 and RF5112, later RF chips seem to have |
| @@ -134,11 +335,11 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
| 134 | * http://madwifi-project.org/ticket/1659 | 335 | * http://madwifi-project.org/ticket/1659 |
| 135 | * with various measurements and diagrams | 336 | * with various measurements and diagrams |
| 136 | * | 337 | * |
| 137 | * TODO: Deal with power drops due to probes by setting an apropriate | 338 | * TODO: Deal with power drops due to probes by setting an appropriate |
| 138 | * tx power on the probe packets ! Make this part of the calibration process. | 339 | * tx power on the probe packets ! Make this part of the calibration process. |
| 139 | */ | 340 | */ |
| 140 | 341 | ||
| 141 | /* Initialize ah_gain durring attach */ | 342 | /* Initialize ah_gain during attach */ |
| 142 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) | 343 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) |
| 143 | { | 344 | { |
| 144 | /* Initialize the gain optimization values */ | 345 | /* Initialize the gain optimization values */ |
| @@ -302,7 +503,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
| 302 | } | 503 | } |
| 303 | 504 | ||
| 304 | /* Perform gain_F adjustment by choosing the right set | 505 | /* Perform gain_F adjustment by choosing the right set |
| 305 | * of parameters from rf gain optimization ladder */ | 506 | * of parameters from RF gain optimization ladder */ |
| 306 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) | 507 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) |
| 307 | { | 508 | { |
| 308 | const struct ath5k_gain_opt *go; | 509 | const struct ath5k_gain_opt *go; |
| @@ -367,7 +568,7 @@ done: | |||
| 367 | return ret; | 568 | return ret; |
| 368 | } | 569 | } |
| 369 | 570 | ||
| 370 | /* Main callback for thermal rf gain calibration engine | 571 | /* Main callback for thermal RF gain calibration engine |
| 371 | * Check for a new gain reading and schedule an adjustment | 572 | * Check for a new gain reading and schedule an adjustment |
| 372 | * if needed. | 573 | * if needed. |
| 373 | * | 574 | * |
| @@ -433,13 +634,13 @@ done: | |||
| 433 | return ah->ah_gain.g_state; | 634 | return ah->ah_gain.g_state; |
| 434 | } | 635 | } |
| 435 | 636 | ||
| 436 | /* Write initial rf gain table to set the RF sensitivity | 637 | /* Write initial RF gain table to set the RF sensitivity |
| 437 | * this one works on all RF chips and has nothing to do | 638 | * this one works on all RF chips and has nothing to do |
| 438 | * with gain_F calibration */ | 639 | * with gain_F calibration */ |
| 439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | 640 | static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) |
| 440 | { | 641 | { |
| 441 | const struct ath5k_ini_rfgain *ath5k_rfg; | 642 | const struct ath5k_ini_rfgain *ath5k_rfg; |
| 442 | unsigned int i, size; | 643 | unsigned int i, size, index; |
| 443 | 644 | ||
| 444 | switch (ah->ah_radio) { | 645 | switch (ah->ah_radio) { |
| 445 | case AR5K_RF5111: | 646 | case AR5K_RF5111: |
| @@ -471,17 +672,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
| 471 | return -EINVAL; | 672 | return -EINVAL; |
| 472 | } | 673 | } |
| 473 | 674 | ||
| 474 | switch (freq) { | 675 | index = (band == IEEE80211_BAND_2GHZ) ? 1 : 0; |
| 475 | case AR5K_INI_RFGAIN_2GHZ: | ||
| 476 | case AR5K_INI_RFGAIN_5GHZ: | ||
| 477 | break; | ||
| 478 | default: | ||
| 479 | return -EINVAL; | ||
| 480 | } | ||
| 481 | 676 | ||
| 482 | for (i = 0; i < size; i++) { | 677 | for (i = 0; i < size; i++) { |
| 483 | AR5K_REG_WAIT(i); | 678 | AR5K_REG_WAIT(i); |
| 484 | ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], | 679 | ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[index], |
| 485 | (u32)ath5k_rfg[i].rfg_register); | 680 | (u32)ath5k_rfg[i].rfg_register); |
| 486 | } | 681 | } |
| 487 | 682 | ||
| @@ -494,12 +689,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
| 494 | * RF Registers setup * | 689 | * RF Registers setup * |
| 495 | \********************/ | 690 | \********************/ |
| 496 | 691 | ||
| 497 | |||
| 498 | /* | 692 | /* |
| 499 | * Setup RF registers by writing rf buffer on hw | 693 | * Setup RF registers by writing RF buffer on hw |
| 500 | */ | 694 | */ |
| 501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 695 | static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, |
| 502 | unsigned int mode) | 696 | struct ieee80211_channel *channel, unsigned int mode) |
| 503 | { | 697 | { |
| 504 | const struct ath5k_rf_reg *rf_regs; | 698 | const struct ath5k_rf_reg *rf_regs; |
| 505 | const struct ath5k_ini_rfbuffer *ini_rfb; | 699 | const struct ath5k_ini_rfbuffer *ini_rfb; |
| @@ -571,7 +765,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 571 | return -EINVAL; | 765 | return -EINVAL; |
| 572 | } | 766 | } |
| 573 | 767 | ||
| 574 | /* If it's the first time we set rf buffer, allocate | 768 | /* If it's the first time we set RF buffer, allocate |
| 575 | * ah->ah_rf_banks based on ah->ah_rf_banks_size | 769 | * ah->ah_rf_banks based on ah->ah_rf_banks_size |
| 576 | * we set above */ | 770 | * we set above */ |
| 577 | if (ah->ah_rf_banks == NULL) { | 771 | if (ah->ah_rf_banks == NULL) { |
| @@ -652,6 +846,11 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 652 | 846 | ||
| 653 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; | 847 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; |
| 654 | 848 | ||
| 849 | /* Set turbo mode (N/A on RF5413) */ | ||
| 850 | if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && | ||
| 851 | (ah->ah_radio != AR5K_RF5413)) | ||
| 852 | ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_TURBO, false); | ||
| 853 | |||
| 655 | /* Bank Modifications (chip-specific) */ | 854 | /* Bank Modifications (chip-specific) */ |
| 656 | if (ah->ah_radio == AR5K_RF5111) { | 855 | if (ah->ah_radio == AR5K_RF5111) { |
| 657 | 856 | ||
| @@ -691,7 +890,23 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 691 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], | 890 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], |
| 692 | AR5K_RF_PLO_SEL, true); | 891 | AR5K_RF_PLO_SEL, true); |
| 693 | 892 | ||
| 694 | /* TODO: Half/quarter channel support */ | 893 | /* Tweak power detectors for half/quarter rate support */ |
| 894 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || | ||
| 895 | ah->ah_bwmode == AR5K_BWMODE_10MHZ) { | ||
| 896 | u8 wait_i; | ||
| 897 | |||
| 898 | ath5k_hw_rfb_op(ah, rf_regs, 0x1f, | ||
| 899 | AR5K_RF_WAIT_S, true); | ||
| 900 | |||
| 901 | wait_i = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? | ||
| 902 | 0x1f : 0x10; | ||
| 903 | |||
| 904 | ath5k_hw_rfb_op(ah, rf_regs, wait_i, | ||
| 905 | AR5K_RF_WAIT_I, true); | ||
| 906 | ath5k_hw_rfb_op(ah, rf_regs, 3, | ||
| 907 | AR5K_RF_MAX_TIME, true); | ||
| 908 | |||
| 909 | } | ||
| 695 | } | 910 | } |
| 696 | 911 | ||
| 697 | if (ah->ah_radio == AR5K_RF5112) { | 912 | if (ah->ah_radio == AR5K_RF5112) { |
| @@ -789,8 +1004,20 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 789 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], | 1004 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], |
| 790 | AR5K_RF_GAIN_I, true); | 1005 | AR5K_RF_GAIN_I, true); |
| 791 | 1006 | ||
| 792 | /* TODO: Half/quarter channel support */ | 1007 | /* Tweak power detector for half/quarter rates */ |
| 1008 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || | ||
| 1009 | ah->ah_bwmode == AR5K_BWMODE_10MHZ) { | ||
| 1010 | u8 pd_delay; | ||
| 1011 | |||
| 1012 | pd_delay = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? | ||
| 1013 | 0xf : 0x8; | ||
| 1014 | |||
| 1015 | ath5k_hw_rfb_op(ah, rf_regs, pd_delay, | ||
| 1016 | AR5K_RF_PD_PERIOD_A, true); | ||
| 1017 | ath5k_hw_rfb_op(ah, rf_regs, 0xf, | ||
| 1018 | AR5K_RF_PD_DELAY_A, true); | ||
| 793 | 1019 | ||
| 1020 | } | ||
| 794 | } | 1021 | } |
| 795 | 1022 | ||
| 796 | if (ah->ah_radio == AR5K_RF5413 && | 1023 | if (ah->ah_radio == AR5K_RF5413 && |
| @@ -822,25 +1049,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 822 | \**************************/ | 1049 | \**************************/ |
| 823 | 1050 | ||
| 824 | /* | 1051 | /* |
| 825 | * Check if a channel is supported | 1052 | * Conversion needed for RF5110 |
| 826 | */ | ||
| 827 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
| 828 | { | ||
| 829 | /* Check if the channel is in our supported range */ | ||
| 830 | if (flags & CHANNEL_2GHZ) { | ||
| 831 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
| 832 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
| 833 | return true; | ||
| 834 | } else if (flags & CHANNEL_5GHZ) | ||
| 835 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
| 836 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
| 837 | return true; | ||
| 838 | |||
| 839 | return false; | ||
| 840 | } | ||
| 841 | |||
| 842 | /* | ||
| 843 | * Convertion needed for RF5110 | ||
| 844 | */ | 1053 | */ |
| 845 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | 1054 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) |
| 846 | { | 1055 | { |
| @@ -879,7 +1088,7 @@ static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, | |||
| 879 | } | 1088 | } |
| 880 | 1089 | ||
| 881 | /* | 1090 | /* |
| 882 | * Convertion needed for 5111 | 1091 | * Conversion needed for 5111 |
| 883 | */ | 1092 | */ |
| 884 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, | 1093 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, |
| 885 | struct ath5k_athchan_2ghz *athchan) | 1094 | struct ath5k_athchan_2ghz *athchan) |
| @@ -1045,7 +1254,8 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | |||
| 1045 | /* | 1254 | /* |
| 1046 | * Set a channel on the radio chip | 1255 | * Set a channel on the radio chip |
| 1047 | */ | 1256 | */ |
| 1048 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 1257 | static int ath5k_hw_channel(struct ath5k_hw *ah, |
| 1258 | struct ieee80211_channel *channel) | ||
| 1049 | { | 1259 | { |
| 1050 | int ret; | 1260 | int ret; |
| 1051 | /* | 1261 | /* |
| @@ -1071,6 +1281,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
| 1071 | case AR5K_RF5111: | 1281 | case AR5K_RF5111: |
| 1072 | ret = ath5k_hw_rf5111_channel(ah, channel); | 1282 | ret = ath5k_hw_rf5111_channel(ah, channel); |
| 1073 | break; | 1283 | break; |
| 1284 | case AR5K_RF2317: | ||
| 1074 | case AR5K_RF2425: | 1285 | case AR5K_RF2425: |
| 1075 | ret = ath5k_hw_rf2425_channel(ah, channel); | 1286 | ret = ath5k_hw_rf2425_channel(ah, channel); |
| 1076 | break; | 1287 | break; |
| @@ -1092,7 +1303,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
| 1092 | } | 1303 | } |
| 1093 | 1304 | ||
| 1094 | ah->ah_current_channel = channel; | 1305 | ah->ah_current_channel = channel; |
| 1095 | ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; | ||
| 1096 | 1306 | ||
| 1097 | return 0; | 1307 | return 0; |
| 1098 | } | 1308 | } |
| @@ -1101,18 +1311,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
| 1101 | PHY calibration | 1311 | PHY calibration |
| 1102 | \*****************/ | 1312 | \*****************/ |
| 1103 | 1313 | ||
| 1104 | static int sign_extend(int val, const int nbits) | ||
| 1105 | { | ||
| 1106 | int order = BIT(nbits-1); | ||
| 1107 | return (val ^ order) - order; | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) | 1314 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) |
| 1111 | { | 1315 | { |
| 1112 | s32 val; | 1316 | s32 val; |
| 1113 | 1317 | ||
| 1114 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); | 1318 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); |
| 1115 | return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); | 1319 | return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); |
| 1116 | } | 1320 | } |
| 1117 | 1321 | ||
| 1118 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) | 1322 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) |
| @@ -1180,22 +1384,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
| 1180 | return; | 1384 | return; |
| 1181 | } | 1385 | } |
| 1182 | 1386 | ||
| 1183 | switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { | 1387 | ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); |
| 1184 | case CHANNEL_A: | ||
| 1185 | case CHANNEL_T: | ||
| 1186 | case CHANNEL_XR: | ||
| 1187 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
| 1188 | break; | ||
| 1189 | case CHANNEL_G: | ||
| 1190 | case CHANNEL_TG: | ||
| 1191 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
| 1192 | break; | ||
| 1193 | default: | ||
| 1194 | case CHANNEL_B: | ||
| 1195 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
| 1196 | break; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | 1388 | ||
| 1200 | /* completed NF calibration, test threshold */ | 1389 | /* completed NF calibration, test threshold */ |
| 1201 | nf = ath5k_hw_read_measured_noise_floor(ah); | 1390 | nf = ath5k_hw_read_measured_noise_floor(ah); |
| @@ -1257,7 +1446,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
| 1257 | * Disable beacons and RX/TX queues, wait | 1446 | * Disable beacons and RX/TX queues, wait |
| 1258 | */ | 1447 | */ |
| 1259 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, | 1448 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, |
| 1260 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | 1449 | AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); |
| 1261 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); | 1450 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); |
| 1262 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); | 1451 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); |
| 1263 | 1452 | ||
| @@ -1336,7 +1525,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
| 1336 | * Re-enable RX/TX and beacons | 1525 | * Re-enable RX/TX and beacons |
| 1337 | */ | 1526 | */ |
| 1338 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, | 1527 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, |
| 1339 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | 1528 | AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); |
| 1340 | ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); | 1529 | ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); |
| 1341 | 1530 | ||
| 1342 | return 0; | 1531 | return 0; |
| @@ -1377,7 +1566,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | |||
| 1377 | 1566 | ||
| 1378 | /* protect against divide by 0 and loss of sign bits */ | 1567 | /* protect against divide by 0 and loss of sign bits */ |
| 1379 | if (i_coffd == 0 || q_coffd < 2) | 1568 | if (i_coffd == 0 || q_coffd < 2) |
| 1380 | return -1; | 1569 | return 0; |
| 1381 | 1570 | ||
| 1382 | i_coff = (-iq_corr) / i_coffd; | 1571 | i_coff = (-iq_corr) / i_coffd; |
| 1383 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | 1572 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ |
| @@ -1424,31 +1613,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
| 1424 | return ret; | 1613 | return ret; |
| 1425 | } | 1614 | } |
| 1426 | 1615 | ||
| 1616 | |||
| 1427 | /***************************\ | 1617 | /***************************\ |
| 1428 | * Spur mitigation functions * | 1618 | * Spur mitigation functions * |
| 1429 | \***************************/ | 1619 | \***************************/ |
| 1430 | 1620 | ||
| 1431 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1621 | static void |
| 1432 | struct ieee80211_channel *channel) | ||
| 1433 | { | ||
| 1434 | u8 refclk_freq; | ||
| 1435 | |||
| 1436 | if ((ah->ah_radio == AR5K_RF5112) || | ||
| 1437 | (ah->ah_radio == AR5K_RF5413) || | ||
| 1438 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
| 1439 | refclk_freq = 40; | ||
| 1440 | else | ||
| 1441 | refclk_freq = 32; | ||
| 1442 | |||
| 1443 | if ((channel->center_freq % refclk_freq != 0) && | ||
| 1444 | ((channel->center_freq % refclk_freq < 10) || | ||
| 1445 | (channel->center_freq % refclk_freq > 22))) | ||
| 1446 | return true; | ||
| 1447 | else | ||
| 1448 | return false; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | void | ||
| 1452 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | 1622 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, |
| 1453 | struct ieee80211_channel *channel) | 1623 | struct ieee80211_channel *channel) |
| 1454 | { | 1624 | { |
| @@ -1477,7 +1647,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
| 1477 | spur_chan_fbin = AR5K_EEPROM_NO_SPUR; | 1647 | spur_chan_fbin = AR5K_EEPROM_NO_SPUR; |
| 1478 | spur_detection_window = AR5K_SPUR_CHAN_WIDTH; | 1648 | spur_detection_window = AR5K_SPUR_CHAN_WIDTH; |
| 1479 | /* XXX: Half/Quarter channels ?*/ | 1649 | /* XXX: Half/Quarter channels ?*/ |
| 1480 | if (channel->hw_value & CHANNEL_TURBO) | 1650 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
| 1481 | spur_detection_window *= 2; | 1651 | spur_detection_window *= 2; |
| 1482 | 1652 | ||
| 1483 | for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { | 1653 | for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { |
| @@ -1506,32 +1676,43 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
| 1506 | * Calculate deltas: | 1676 | * Calculate deltas: |
| 1507 | * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 | 1677 | * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 |
| 1508 | * spur_delta_phase -> spur_offset / chip_freq << 11 | 1678 | * spur_delta_phase -> spur_offset / chip_freq << 11 |
| 1509 | * Note: Both values have 100KHz resolution | 1679 | * Note: Both values have 100Hz resolution |
| 1510 | */ | 1680 | */ |
| 1511 | /* XXX: Half/Quarter rate channels ? */ | 1681 | switch (ah->ah_bwmode) { |
| 1512 | switch (channel->hw_value) { | 1682 | case AR5K_BWMODE_40MHZ: |
| 1513 | case CHANNEL_A: | ||
| 1514 | /* Both sample_freq and chip_freq are 40MHz */ | ||
| 1515 | spur_delta_phase = (spur_offset << 17) / 25; | ||
| 1516 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
| 1517 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
| 1518 | break; | ||
| 1519 | case CHANNEL_G: | ||
| 1520 | /* sample_freq -> 40MHz chip_freq -> 44MHz | ||
| 1521 | * (for b compatibility) */ | ||
| 1522 | spur_freq_sigma_delta = (spur_offset << 8) / 55; | ||
| 1523 | spur_delta_phase = (spur_offset << 17) / 25; | ||
| 1524 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
| 1525 | break; | ||
| 1526 | case CHANNEL_T: | ||
| 1527 | case CHANNEL_TG: | ||
| 1528 | /* Both sample_freq and chip_freq are 80MHz */ | 1683 | /* Both sample_freq and chip_freq are 80MHz */ |
| 1529 | spur_delta_phase = (spur_offset << 16) / 25; | 1684 | spur_delta_phase = (spur_offset << 16) / 25; |
| 1530 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | 1685 | spur_freq_sigma_delta = (spur_delta_phase >> 10); |
| 1531 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; | 1686 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz * 2; |
| 1532 | break; | 1687 | break; |
| 1688 | case AR5K_BWMODE_10MHZ: | ||
| 1689 | /* Both sample_freq and chip_freq are 20MHz (?) */ | ||
| 1690 | spur_delta_phase = (spur_offset << 18) / 25; | ||
| 1691 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
| 1692 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; | ||
| 1693 | case AR5K_BWMODE_5MHZ: | ||
| 1694 | /* Both sample_freq and chip_freq are 10MHz (?) */ | ||
| 1695 | spur_delta_phase = (spur_offset << 19) / 25; | ||
| 1696 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
| 1697 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; | ||
| 1533 | default: | 1698 | default: |
| 1534 | return; | 1699 | if (channel->hw_value == CHANNEL_A) { |
| 1700 | /* Both sample_freq and chip_freq are 40MHz */ | ||
| 1701 | spur_delta_phase = (spur_offset << 17) / 25; | ||
| 1702 | spur_freq_sigma_delta = | ||
| 1703 | (spur_delta_phase >> 10); | ||
| 1704 | symbol_width = | ||
| 1705 | AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
| 1706 | } else { | ||
| 1707 | /* sample_freq -> 40MHz chip_freq -> 44MHz | ||
| 1708 | * (for b compatibility) */ | ||
| 1709 | spur_delta_phase = (spur_offset << 17) / 25; | ||
| 1710 | spur_freq_sigma_delta = | ||
| 1711 | (spur_offset << 8) / 55; | ||
| 1712 | symbol_width = | ||
| 1713 | AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
| 1714 | } | ||
| 1715 | break; | ||
| 1535 | } | 1716 | } |
| 1536 | 1717 | ||
| 1537 | /* Calculate pilot and magnitude masks */ | 1718 | /* Calculate pilot and magnitude masks */ |
| @@ -1582,7 +1763,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
| 1582 | else if (curr_sym_off >= 31 && curr_sym_off <= 46) | 1763 | else if (curr_sym_off >= 31 && curr_sym_off <= 46) |
| 1583 | mag_mask[2] |= | 1764 | mag_mask[2] |= |
| 1584 | plt_mag_map << (curr_sym_off - 31) * 2; | 1765 | plt_mag_map << (curr_sym_off - 31) * 2; |
| 1585 | else if (curr_sym_off >= 46 && curr_sym_off <= 53) | 1766 | else if (curr_sym_off >= 47 && curr_sym_off <= 53) |
| 1586 | mag_mask[3] |= | 1767 | mag_mask[3] |= |
| 1587 | plt_mag_map << (curr_sym_off - 47) * 2; | 1768 | plt_mag_map << (curr_sym_off - 47) * 2; |
| 1588 | 1769 | ||
| @@ -1671,63 +1852,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
| 1671 | } | 1852 | } |
| 1672 | } | 1853 | } |
| 1673 | 1854 | ||
| 1674 | /********************\ | ||
| 1675 | Misc PHY functions | ||
| 1676 | \********************/ | ||
| 1677 | |||
| 1678 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
| 1679 | { | ||
| 1680 | /*Just a try M.F.*/ | ||
| 1681 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
| 1682 | |||
| 1683 | return 0; | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | /* | ||
| 1687 | * Get the PHY Chip revision | ||
| 1688 | */ | ||
| 1689 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
| 1690 | { | ||
| 1691 | unsigned int i; | ||
| 1692 | u32 srev; | ||
| 1693 | u16 ret; | ||
| 1694 | |||
| 1695 | /* | ||
| 1696 | * Set the radio chip access register | ||
| 1697 | */ | ||
| 1698 | switch (chan) { | ||
| 1699 | case CHANNEL_2GHZ: | ||
| 1700 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
| 1701 | break; | ||
| 1702 | case CHANNEL_5GHZ: | ||
| 1703 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
| 1704 | break; | ||
| 1705 | default: | ||
| 1706 | return 0; | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | mdelay(2); | ||
| 1710 | |||
| 1711 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
| 1712 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
| 1713 | |||
| 1714 | for (i = 0; i < 8; i++) | ||
| 1715 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
| 1716 | |||
| 1717 | if (ah->ah_version == AR5K_AR5210) { | ||
| 1718 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
| 1719 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
| 1720 | } else { | ||
| 1721 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
| 1722 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
| 1723 | ((srev & 0x0f) << 4), 8); | ||
| 1724 | } | ||
| 1725 | |||
| 1726 | /* Reset to the 5GHz mode */ | ||
| 1727 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
| 1728 | |||
| 1729 | return ret; | ||
| 1730 | } | ||
| 1731 | 1855 | ||
| 1732 | /*****************\ | 1856 | /*****************\ |
| 1733 | * Antenna control * | 1857 | * Antenna control * |
| @@ -1821,7 +1945,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
| 1821 | struct ieee80211_channel *channel = ah->ah_current_channel; | 1945 | struct ieee80211_channel *channel = ah->ah_current_channel; |
| 1822 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; | 1946 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; |
| 1823 | bool use_def_for_sg; | 1947 | bool use_def_for_sg; |
| 1824 | u8 def_ant, tx_ant, ee_mode; | 1948 | int ee_mode; |
| 1949 | u8 def_ant, tx_ant; | ||
| 1825 | u32 sta_id1 = 0; | 1950 | u32 sta_id1 = 0; |
| 1826 | 1951 | ||
| 1827 | /* if channel is not initialized yet we can't set the antennas | 1952 | /* if channel is not initialized yet we can't set the antennas |
| @@ -1833,20 +1958,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
| 1833 | 1958 | ||
| 1834 | def_ant = ah->ah_def_ant; | 1959 | def_ant = ah->ah_def_ant; |
| 1835 | 1960 | ||
| 1836 | switch (channel->hw_value & CHANNEL_MODES) { | 1961 | ee_mode = ath5k_eeprom_mode_from_channel(channel); |
| 1837 | case CHANNEL_A: | 1962 | if (ee_mode < 0) { |
| 1838 | case CHANNEL_T: | ||
| 1839 | case CHANNEL_XR: | ||
| 1840 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
| 1841 | break; | ||
| 1842 | case CHANNEL_G: | ||
| 1843 | case CHANNEL_TG: | ||
| 1844 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
| 1845 | break; | ||
| 1846 | case CHANNEL_B: | ||
| 1847 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
| 1848 | break; | ||
| 1849 | default: | ||
| 1850 | ATH5K_ERR(ah->ah_sc, | 1963 | ATH5K_ERR(ah->ah_sc, |
| 1851 | "invalid channel: %d\n", channel->center_freq); | 1964 | "invalid channel: %d\n", channel->center_freq); |
| 1852 | return; | 1965 | return; |
| @@ -2088,7 +2201,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax, | |||
| 2088 | /* | 2201 | /* |
| 2089 | * Get the surrounding per-channel power calibration piers | 2202 | * Get the surrounding per-channel power calibration piers |
| 2090 | * for a given frequency so that we can interpolate between | 2203 | * for a given frequency so that we can interpolate between |
| 2091 | * them and come up with an apropriate dataset for our current | 2204 | * them and come up with an appropriate dataset for our current |
| 2092 | * channel. | 2205 | * channel. |
| 2093 | */ | 2206 | */ |
| 2094 | static void | 2207 | static void |
| @@ -2274,20 +2387,20 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, | |||
| 2274 | 2387 | ||
| 2275 | switch (channel->hw_value & CHANNEL_MODES) { | 2388 | switch (channel->hw_value & CHANNEL_MODES) { |
| 2276 | case CHANNEL_A: | 2389 | case CHANNEL_A: |
| 2277 | ctl_mode |= AR5K_CTL_11A; | 2390 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
| 2391 | ctl_mode |= AR5K_CTL_TURBO; | ||
| 2392 | else | ||
| 2393 | ctl_mode |= AR5K_CTL_11A; | ||
| 2278 | break; | 2394 | break; |
| 2279 | case CHANNEL_G: | 2395 | case CHANNEL_G: |
| 2280 | ctl_mode |= AR5K_CTL_11G; | 2396 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
| 2397 | ctl_mode |= AR5K_CTL_TURBOG; | ||
| 2398 | else | ||
| 2399 | ctl_mode |= AR5K_CTL_11G; | ||
| 2281 | break; | 2400 | break; |
| 2282 | case CHANNEL_B: | 2401 | case CHANNEL_B: |
| 2283 | ctl_mode |= AR5K_CTL_11B; | 2402 | ctl_mode |= AR5K_CTL_11B; |
| 2284 | break; | 2403 | break; |
| 2285 | case CHANNEL_T: | ||
| 2286 | ctl_mode |= AR5K_CTL_TURBO; | ||
| 2287 | break; | ||
| 2288 | case CHANNEL_TG: | ||
| 2289 | ctl_mode |= AR5K_CTL_TURBOG; | ||
| 2290 | break; | ||
| 2291 | case CHANNEL_XR: | 2404 | case CHANNEL_XR: |
| 2292 | /* Fall through */ | 2405 | /* Fall through */ |
| 2293 | default: | 2406 | default: |
| @@ -2481,7 +2594,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, | |||
| 2481 | 2594 | ||
| 2482 | /* Write PCDAC values on hw */ | 2595 | /* Write PCDAC values on hw */ |
| 2483 | static void | 2596 | static void |
| 2484 | ath5k_setup_pcdac_table(struct ath5k_hw *ah) | 2597 | ath5k_write_pcdac_table(struct ath5k_hw *ah) |
| 2485 | { | 2598 | { |
| 2486 | u8 *pcdac_out = ah->ah_txpower.txp_pd_table; | 2599 | u8 *pcdac_out = ah->ah_txpower.txp_pd_table; |
| 2487 | int i; | 2600 | int i; |
| @@ -2505,7 +2618,7 @@ ath5k_setup_pcdac_table(struct ath5k_hw *ah) | |||
| 2505 | /* | 2618 | /* |
| 2506 | * Set the gain boundaries and create final Power to PDADC table | 2619 | * Set the gain boundaries and create final Power to PDADC table |
| 2507 | * | 2620 | * |
| 2508 | * We can have up to 4 pd curves, we need to do a simmilar process | 2621 | * We can have up to 4 pd curves, we need to do a similar process |
| 2509 | * as we do for RF5112. This time we don't have an edge_flag but we | 2622 | * as we do for RF5112. This time we don't have an edge_flag but we |
| 2510 | * set the gain boundaries on a separate register. | 2623 | * set the gain boundaries on a separate register. |
| 2511 | */ | 2624 | */ |
| @@ -2630,10 +2743,12 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, | |||
| 2630 | 2743 | ||
| 2631 | /* Write PDADC values on hw */ | 2744 | /* Write PDADC values on hw */ |
| 2632 | static void | 2745 | static void |
| 2633 | ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, | 2746 | ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) |
| 2634 | u8 pdcurves, u8 *pdg_to_idx) | ||
| 2635 | { | 2747 | { |
| 2748 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
| 2636 | u8 *pdadc_out = ah->ah_txpower.txp_pd_table; | 2749 | u8 *pdadc_out = ah->ah_txpower.txp_pd_table; |
| 2750 | u8 *pdg_to_idx = ee->ee_pdc_to_idx[ee_mode]; | ||
| 2751 | u8 pdcurves = ee->ee_pd_gains[ee_mode]; | ||
| 2637 | u32 reg; | 2752 | u32 reg; |
| 2638 | u8 i; | 2753 | u8 i; |
| 2639 | 2754 | ||
| @@ -2711,13 +2826,13 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2711 | u32 target = channel->center_freq; | 2826 | u32 target = channel->center_freq; |
| 2712 | int pdg, i; | 2827 | int pdg, i; |
| 2713 | 2828 | ||
| 2714 | /* Get surounding freq piers for this channel */ | 2829 | /* Get surrounding freq piers for this channel */ |
| 2715 | ath5k_get_chan_pcal_surrounding_piers(ah, channel, | 2830 | ath5k_get_chan_pcal_surrounding_piers(ah, channel, |
| 2716 | &pcinfo_L, | 2831 | &pcinfo_L, |
| 2717 | &pcinfo_R); | 2832 | &pcinfo_R); |
| 2718 | 2833 | ||
| 2719 | /* Loop over pd gain curves on | 2834 | /* Loop over pd gain curves on |
| 2720 | * surounding freq piers by index */ | 2835 | * surrounding freq piers by index */ |
| 2721 | for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { | 2836 | for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { |
| 2722 | 2837 | ||
| 2723 | /* Fill curves in reverse order | 2838 | /* Fill curves in reverse order |
| @@ -2808,7 +2923,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2808 | } | 2923 | } |
| 2809 | 2924 | ||
| 2810 | /* Interpolate between curves | 2925 | /* Interpolate between curves |
| 2811 | * of surounding freq piers to | 2926 | * of surrounding freq piers to |
| 2812 | * get the final curve for this | 2927 | * get the final curve for this |
| 2813 | * pd gain. Re-use tmpL for interpolation | 2928 | * pd gain. Re-use tmpL for interpolation |
| 2814 | * output */ | 2929 | * output */ |
| @@ -2832,7 +2947,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2832 | 2947 | ||
| 2833 | /* Fill min and max power levels for this | 2948 | /* Fill min and max power levels for this |
| 2834 | * channel by interpolating the values on | 2949 | * channel by interpolating the values on |
| 2835 | * surounding channels to complete the dataset */ | 2950 | * surrounding channels to complete the dataset */ |
| 2836 | ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, | 2951 | ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, |
| 2837 | (s16) pcinfo_L->freq, | 2952 | (s16) pcinfo_L->freq, |
| 2838 | (s16) pcinfo_R->freq, | 2953 | (s16) pcinfo_R->freq, |
| @@ -2843,8 +2958,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2843 | (s16) pcinfo_R->freq, | 2958 | (s16) pcinfo_R->freq, |
| 2844 | pcinfo_L->max_pwr, pcinfo_R->max_pwr); | 2959 | pcinfo_L->max_pwr, pcinfo_R->max_pwr); |
| 2845 | 2960 | ||
| 2846 | /* We are ready to go, fill PCDAC/PDADC | 2961 | /* Fill PCDAC/PDADC table */ |
| 2847 | * table and write settings on hardware */ | ||
| 2848 | switch (type) { | 2962 | switch (type) { |
| 2849 | case AR5K_PWRTABLE_LINEAR_PCDAC: | 2963 | case AR5K_PWRTABLE_LINEAR_PCDAC: |
| 2850 | /* For RF5112 we can have one or two curves | 2964 | /* For RF5112 we can have one or two curves |
| @@ -2857,9 +2971,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2857 | * match max power value with max | 2971 | * match max power value with max |
| 2858 | * table index */ | 2972 | * table index */ |
| 2859 | ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); | 2973 | ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); |
| 2860 | |||
| 2861 | /* Write settings on hw */ | ||
| 2862 | ath5k_setup_pcdac_table(ah); | ||
| 2863 | break; | 2974 | break; |
| 2864 | case AR5K_PWRTABLE_PWR_TO_PCDAC: | 2975 | case AR5K_PWRTABLE_PWR_TO_PCDAC: |
| 2865 | /* We are done for RF5111 since it has only | 2976 | /* We are done for RF5111 since it has only |
| @@ -2869,9 +2980,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2869 | /* No rate powertable adjustment for RF5111 */ | 2980 | /* No rate powertable adjustment for RF5111 */ |
| 2870 | ah->ah_txpower.txp_min_idx = 0; | 2981 | ah->ah_txpower.txp_min_idx = 0; |
| 2871 | ah->ah_txpower.txp_offset = 0; | 2982 | ah->ah_txpower.txp_offset = 0; |
| 2872 | |||
| 2873 | /* Write settings on hw */ | ||
| 2874 | ath5k_setup_pcdac_table(ah); | ||
| 2875 | break; | 2983 | break; |
| 2876 | case AR5K_PWRTABLE_PWR_TO_PDADC: | 2984 | case AR5K_PWRTABLE_PWR_TO_PDADC: |
| 2877 | /* Set PDADC boundaries and fill | 2985 | /* Set PDADC boundaries and fill |
| @@ -2879,9 +2987,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2879 | ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, | 2987 | ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, |
| 2880 | ee->ee_pd_gains[ee_mode]); | 2988 | ee->ee_pd_gains[ee_mode]); |
| 2881 | 2989 | ||
| 2882 | /* Write settings on hw */ | ||
| 2883 | ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); | ||
| 2884 | |||
| 2885 | /* Set txp.offset, note that table_min | 2990 | /* Set txp.offset, note that table_min |
| 2886 | * can be negative */ | 2991 | * can be negative */ |
| 2887 | ah->ah_txpower.txp_offset = table_min[0]; | 2992 | ah->ah_txpower.txp_offset = table_min[0]; |
| @@ -2890,9 +2995,20 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
| 2890 | return -EINVAL; | 2995 | return -EINVAL; |
| 2891 | } | 2996 | } |
| 2892 | 2997 | ||
| 2998 | ah->ah_txpower.txp_setup = true; | ||
| 2999 | |||
| 2893 | return 0; | 3000 | return 0; |
| 2894 | } | 3001 | } |
| 2895 | 3002 | ||
| 3003 | /* Write power table for current channel to hw */ | ||
| 3004 | static void | ||
| 3005 | ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) | ||
| 3006 | { | ||
| 3007 | if (type == AR5K_PWRTABLE_PWR_TO_PDADC) | ||
| 3008 | ath5k_write_pwr_to_pdadc_table(ah, ee_mode); | ||
| 3009 | else | ||
| 3010 | ath5k_write_pcdac_table(ah); | ||
| 3011 | } | ||
| 2896 | 3012 | ||
| 2897 | /* | 3013 | /* |
| 2898 | * Per-rate tx power setting | 3014 | * Per-rate tx power setting |
| @@ -2981,19 +3097,21 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, | |||
| 2981 | 3097 | ||
| 2982 | /* Min/max in 0.25dB units */ | 3098 | /* Min/max in 0.25dB units */ |
| 2983 | ah->ah_txpower.txp_min_pwr = 2 * rates[7]; | 3099 | ah->ah_txpower.txp_min_pwr = 2 * rates[7]; |
| 2984 | ah->ah_txpower.txp_max_pwr = 2 * rates[0]; | 3100 | ah->ah_txpower.txp_cur_pwr = 2 * rates[0]; |
| 2985 | ah->ah_txpower.txp_ofdm = rates[7]; | 3101 | ah->ah_txpower.txp_ofdm = rates[7]; |
| 2986 | } | 3102 | } |
| 2987 | 3103 | ||
| 2988 | 3104 | ||
| 2989 | /* | 3105 | /* |
| 2990 | * Set transmition power | 3106 | * Set transmission power |
| 2991 | */ | 3107 | */ |
| 2992 | int | 3108 | static int |
| 2993 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 3109 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
| 2994 | u8 ee_mode, u8 txpower) | 3110 | u8 txpower) |
| 2995 | { | 3111 | { |
| 2996 | struct ath5k_rate_pcal_info rate_info; | 3112 | struct ath5k_rate_pcal_info rate_info; |
| 3113 | struct ieee80211_channel *curr_channel = ah->ah_current_channel; | ||
| 3114 | int ee_mode; | ||
| 2997 | u8 type; | 3115 | u8 type; |
| 2998 | int ret; | 3116 | int ret; |
| 2999 | 3117 | ||
| @@ -3002,14 +3120,18 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 3002 | return -EINVAL; | 3120 | return -EINVAL; |
| 3003 | } | 3121 | } |
| 3004 | 3122 | ||
| 3005 | /* Reset TX power values */ | 3123 | ee_mode = ath5k_eeprom_mode_from_channel(channel); |
| 3006 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | 3124 | if (ee_mode < 0) { |
| 3007 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 3125 | ATH5K_ERR(ah->ah_sc, |
| 3008 | ah->ah_txpower.txp_min_pwr = 0; | 3126 | "invalid channel: %d\n", channel->center_freq); |
| 3009 | ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; | 3127 | return -EINVAL; |
| 3128 | } | ||
| 3010 | 3129 | ||
| 3011 | /* Initialize TX power table */ | 3130 | /* Initialize TX power table */ |
| 3012 | switch (ah->ah_radio) { | 3131 | switch (ah->ah_radio) { |
| 3132 | case AR5K_RF5110: | ||
| 3133 | /* TODO */ | ||
| 3134 | return 0; | ||
| 3013 | case AR5K_RF5111: | 3135 | case AR5K_RF5111: |
| 3014 | type = AR5K_PWRTABLE_PWR_TO_PCDAC; | 3136 | type = AR5K_PWRTABLE_PWR_TO_PCDAC; |
| 3015 | break; | 3137 | break; |
| @@ -3027,24 +3149,37 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 3027 | return -EINVAL; | 3149 | return -EINVAL; |
| 3028 | } | 3150 | } |
| 3029 | 3151 | ||
| 3030 | /* FIXME: Only on channel/mode change */ | 3152 | /* |
| 3031 | ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); | 3153 | * If we don't change channel/mode skip tx powertable calculation |
| 3032 | if (ret) | 3154 | * and use the cached one. |
| 3033 | return ret; | 3155 | */ |
| 3156 | if (!ah->ah_txpower.txp_setup || | ||
| 3157 | (channel->hw_value != curr_channel->hw_value) || | ||
| 3158 | (channel->center_freq != curr_channel->center_freq)) { | ||
| 3159 | /* Reset TX power values */ | ||
| 3160 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | ||
| 3161 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | ||
| 3162 | |||
| 3163 | /* Calculate the powertable */ | ||
| 3164 | ret = ath5k_setup_channel_powertable(ah, channel, | ||
| 3165 | ee_mode, type); | ||
| 3166 | if (ret) | ||
| 3167 | return ret; | ||
| 3168 | } | ||
| 3169 | |||
| 3170 | /* Write table on hw */ | ||
| 3171 | ath5k_write_channel_powertable(ah, ee_mode, type); | ||
| 3034 | 3172 | ||
| 3035 | /* Limit max power if we have a CTL available */ | 3173 | /* Limit max power if we have a CTL available */ |
| 3036 | ath5k_get_max_ctl_power(ah, channel); | 3174 | ath5k_get_max_ctl_power(ah, channel); |
| 3037 | 3175 | ||
| 3038 | /* FIXME: Tx power limit for this regdomain | ||
| 3039 | * XXX: Mac80211/CRDA will do that anyway ? */ | ||
| 3040 | |||
| 3041 | /* FIXME: Antenna reduction stuff */ | 3176 | /* FIXME: Antenna reduction stuff */ |
| 3042 | 3177 | ||
| 3043 | /* FIXME: Limit power on turbo modes */ | 3178 | /* FIXME: Limit power on turbo modes */ |
| 3044 | 3179 | ||
| 3045 | /* FIXME: TPC scale reduction */ | 3180 | /* FIXME: TPC scale reduction */ |
| 3046 | 3181 | ||
| 3047 | /* Get surounding channels for per-rate power table | 3182 | /* Get surrounding channels for per-rate power table |
| 3048 | * calibration */ | 3183 | * calibration */ |
| 3049 | ath5k_get_rate_pcal_data(ah, channel, &rate_info); | 3184 | ath5k_get_rate_pcal_data(ah, channel, &rate_info); |
| 3050 | 3185 | ||
| @@ -3088,31 +3223,223 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
| 3088 | 3223 | ||
| 3089 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | 3224 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) |
| 3090 | { | 3225 | { |
| 3091 | /*Just a try M.F.*/ | 3226 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, |
| 3092 | struct ieee80211_channel *channel = ah->ah_current_channel; | 3227 | "changing txpower to %d\n", txpower); |
| 3093 | u8 ee_mode; | ||
| 3094 | 3228 | ||
| 3095 | switch (channel->hw_value & CHANNEL_MODES) { | 3229 | return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); |
| 3096 | case CHANNEL_A: | 3230 | } |
| 3097 | case CHANNEL_T: | 3231 | |
| 3098 | case CHANNEL_XR: | 3232 | /*************\ |
| 3099 | ee_mode = AR5K_EEPROM_MODE_11A; | 3233 | Init function |
| 3100 | break; | 3234 | \*************/ |
| 3101 | case CHANNEL_G: | 3235 | |
| 3102 | case CHANNEL_TG: | 3236 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
| 3103 | ee_mode = AR5K_EEPROM_MODE_11G; | 3237 | u8 mode, bool fast) |
| 3104 | break; | 3238 | { |
| 3105 | case CHANNEL_B: | 3239 | struct ieee80211_channel *curr_channel; |
| 3106 | ee_mode = AR5K_EEPROM_MODE_11B; | 3240 | int ret, i; |
| 3107 | break; | 3241 | u32 phy_tst1; |
| 3108 | default: | 3242 | ret = 0; |
| 3109 | ATH5K_ERR(ah->ah_sc, | 3243 | |
| 3110 | "invalid channel: %d\n", channel->center_freq); | 3244 | /* |
| 3245 | * Sanity check for fast flag | ||
| 3246 | * Don't try fast channel change when changing modulation | ||
| 3247 | * mode/band. We check for chip compatibility on | ||
| 3248 | * ath5k_hw_reset. | ||
| 3249 | */ | ||
| 3250 | curr_channel = ah->ah_current_channel; | ||
| 3251 | if (fast && (channel->hw_value != curr_channel->hw_value)) | ||
| 3111 | return -EINVAL; | 3252 | return -EINVAL; |
| 3253 | |||
| 3254 | /* | ||
| 3255 | * On fast channel change we only set the synth parameters | ||
| 3256 | * while PHY is running, enable calibration and skip the rest. | ||
| 3257 | */ | ||
| 3258 | if (fast) { | ||
| 3259 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
| 3260 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
| 3261 | for (i = 0; i < 100; i++) { | ||
| 3262 | if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT)) | ||
| 3263 | break; | ||
| 3264 | udelay(5); | ||
| 3265 | } | ||
| 3266 | /* Failed */ | ||
| 3267 | if (i >= 100) | ||
| 3268 | return -EIO; | ||
| 3269 | |||
| 3270 | /* Set channel and wait for synth */ | ||
| 3271 | ret = ath5k_hw_channel(ah, channel); | ||
| 3272 | if (ret) | ||
| 3273 | return ret; | ||
| 3274 | |||
| 3275 | ath5k_hw_wait_for_synth(ah, channel); | ||
| 3112 | } | 3276 | } |
| 3113 | 3277 | ||
| 3114 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, | 3278 | /* |
| 3115 | "changing txpower to %d\n", txpower); | 3279 | * Set TX power |
| 3280 | * | ||
| 3281 | * Note: We need to do that before we set | ||
| 3282 | * RF buffer settings on 5211/5212+ so that we | ||
| 3283 | * properly set curve indices. | ||
| 3284 | */ | ||
| 3285 | ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ? | ||
| 3286 | ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER); | ||
| 3287 | if (ret) | ||
| 3288 | return ret; | ||
| 3289 | |||
| 3290 | /* Write OFDM timings on 5212*/ | ||
| 3291 | if (ah->ah_version == AR5K_AR5212 && | ||
| 3292 | channel->hw_value & CHANNEL_OFDM) { | ||
| 3293 | |||
| 3294 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
| 3295 | if (ret) | ||
| 3296 | return ret; | ||
| 3297 | |||
| 3298 | /* Spur info is available only from EEPROM versions | ||
| 3299 | * greater than 5.3, but the EEPROM routines will use | ||
| 3300 | * static values for older versions */ | ||
| 3301 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
| 3302 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
| 3303 | channel); | ||
| 3304 | } | ||
| 3305 | |||
| 3306 | /* If we used fast channel switching | ||
| 3307 | * we are done, release RF bus and | ||
| 3308 | * fire up NF calibration. | ||
| 3309 | * | ||
| 3310 | * Note: Only NF calibration due to | ||
| 3311 | * channel change, not AGC calibration | ||
| 3312 | * since AGC is still running ! | ||
| 3313 | */ | ||
| 3314 | if (fast) { | ||
| 3315 | /* | ||
| 3316 | * Release RF Bus grant | ||
| 3317 | */ | ||
| 3318 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
| 3319 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
| 3320 | |||
| 3321 | /* | ||
| 3322 | * Start NF calibration | ||
| 3323 | */ | ||
| 3324 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
| 3325 | AR5K_PHY_AGCCTL_NF); | ||
| 3116 | 3326 | ||
| 3117 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); | 3327 | return ret; |
| 3328 | } | ||
| 3329 | |||
| 3330 | /* | ||
| 3331 | * For 5210 we do all initialization using | ||
| 3332 | * initvals, so we don't have to modify | ||
| 3333 | * any settings (5210 also only supports | ||
| 3334 | * a/aturbo modes) | ||
| 3335 | */ | ||
| 3336 | if (ah->ah_version != AR5K_AR5210) { | ||
| 3337 | |||
| 3338 | /* | ||
| 3339 | * Write initial RF gain settings | ||
| 3340 | * This should work for both 5111/5112 | ||
| 3341 | */ | ||
| 3342 | ret = ath5k_hw_rfgain_init(ah, channel->band); | ||
| 3343 | if (ret) | ||
| 3344 | return ret; | ||
| 3345 | |||
| 3346 | mdelay(1); | ||
| 3347 | |||
| 3348 | /* | ||
| 3349 | * Write RF buffer | ||
| 3350 | */ | ||
| 3351 | ret = ath5k_hw_rfregs_init(ah, channel, mode); | ||
| 3352 | if (ret) | ||
| 3353 | return ret; | ||
| 3354 | |||
| 3355 | /*Enable/disable 802.11b mode on 5111 | ||
| 3356 | (enable 2111 frequency converter + CCK)*/ | ||
| 3357 | if (ah->ah_radio == AR5K_RF5111) { | ||
| 3358 | if (mode == AR5K_MODE_11B) | ||
| 3359 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
| 3360 | AR5K_TXCFG_B_MODE); | ||
| 3361 | else | ||
| 3362 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
| 3363 | AR5K_TXCFG_B_MODE); | ||
| 3364 | } | ||
| 3365 | |||
| 3366 | } else if (ah->ah_version == AR5K_AR5210) { | ||
| 3367 | mdelay(1); | ||
| 3368 | /* Disable phy and wait */ | ||
| 3369 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
| 3370 | mdelay(1); | ||
| 3371 | } | ||
| 3372 | |||
| 3373 | /* Set channel on PHY */ | ||
| 3374 | ret = ath5k_hw_channel(ah, channel); | ||
| 3375 | if (ret) | ||
| 3376 | return ret; | ||
| 3377 | |||
| 3378 | /* | ||
| 3379 | * Enable the PHY and wait until completion | ||
| 3380 | * This includes BaseBand and Synthesizer | ||
| 3381 | * activation. | ||
| 3382 | */ | ||
| 3383 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
| 3384 | |||
| 3385 | ath5k_hw_wait_for_synth(ah, channel); | ||
| 3386 | |||
| 3387 | /* | ||
| 3388 | * Perform ADC test to see if baseband is ready | ||
| 3389 | * Set tx hold and check adc test register | ||
| 3390 | */ | ||
| 3391 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
| 3392 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
| 3393 | for (i = 0; i <= 20; i++) { | ||
| 3394 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
| 3395 | break; | ||
| 3396 | udelay(200); | ||
| 3397 | } | ||
| 3398 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
| 3399 | |||
| 3400 | /* | ||
| 3401 | * Start automatic gain control calibration | ||
| 3402 | * | ||
| 3403 | * During AGC calibration RX path is re-routed to | ||
| 3404 | * a power detector so we don't receive anything. | ||
| 3405 | * | ||
| 3406 | * This method is used to calibrate some static offsets | ||
| 3407 | * used together with on-the fly I/Q calibration (the | ||
| 3408 | * one performed via ath5k_hw_phy_calibrate), which doesn't | ||
| 3409 | * interrupt rx path. | ||
| 3410 | * | ||
| 3411 | * While rx path is re-routed to the power detector we also | ||
| 3412 | * start a noise floor calibration to measure the | ||
| 3413 | * card's noise floor (the noise we measure when we are not | ||
| 3414 | * transmitting or receiving anything). | ||
| 3415 | * | ||
| 3416 | * If we are in a noisy environment, AGC calibration may time | ||
| 3417 | * out and/or noise floor calibration might timeout. | ||
| 3418 | */ | ||
| 3419 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
| 3420 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); | ||
| 3421 | |||
| 3422 | /* At the same time start I/Q calibration for QAM constellation | ||
| 3423 | * -no need for CCK- */ | ||
| 3424 | ah->ah_calibration = false; | ||
| 3425 | if (!(mode == AR5K_MODE_11B)) { | ||
| 3426 | ah->ah_calibration = true; | ||
| 3427 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
| 3428 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
| 3429 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
| 3430 | AR5K_PHY_IQ_RUN); | ||
| 3431 | } | ||
| 3432 | |||
| 3433 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
| 3434 | * during ath5k_phy_calibrate) */ | ||
| 3435 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
| 3436 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
| 3437 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
| 3438 | channel->center_freq); | ||
| 3439 | } | ||
| 3440 | |||
| 3441 | /* Restore antenna mode */ | ||
| 3442 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
| 3443 | |||
| 3444 | return ret; | ||
| 3118 | } | 3445 | } |
