diff options
author | David S. Miller <davem@davemloft.net> | 2008-08-01 22:08:51 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-08-01 22:08:51 -0700 |
commit | e9e80ea5f2129e135e3a6fa260314b1c6d99b19a (patch) | |
tree | db20dc85b0e620ea3fcaf86a9026d6df7cb2e168 | |
parent | 2b12a4c524812fb3f6ee590a02e65b95c8c32229 (diff) | |
parent | 56decd3c5758b0d776c073f65f777beb7a05ac0a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
29 files changed, 1161 insertions, 408 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 91fc2c765d9..4c7ff61a1a9 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -649,6 +649,7 @@ config RTL8187 Trendnet TEW-424UB ASUS P5B Deluxe Toshiba Satellite Pro series of laptops + Asus Wireless Link Thanks to Realtek for their support! diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index ba35c30d203..9102eea3c8b 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -186,11 +186,13 @@ struct ath5k_srev_name { #define AR5K_SREV_RAD_2111 0x20 #define AR5K_SREV_RAD_5112 0x30 #define AR5K_SREV_RAD_5112A 0x35 +#define AR5K_SREV_RAD_5112B 0x36 #define AR5K_SREV_RAD_2112 0x40 #define AR5K_SREV_RAD_2112A 0x45 -#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */ -#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ -#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */ +#define AR5K_SREV_RAD_2112B 0x46 +#define AR5K_SREV_RAD_SC0 0x50 /* Found on 2413/2414 */ +#define AR5K_SREV_RAD_SC1 0x60 /* Found on 5413/5414 */ +#define AR5K_SREV_RAD_SC2 0xa0 /* Found on 2424-5/5424 */ #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ /* IEEE defs */ diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index ff3fad794b6..ebf19bc11f5 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2170,6 +2170,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) ath5k_hw_set_intr(ah, 0); sc->bmisscount = 0; + sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); if (sc->opmode == IEEE80211_IF_TYPE_STA) { sc->imask |= AR5K_INT_BMISS; diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 41d5fa34b54..6fa6c8e04ff 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -129,7 +129,7 @@ static struct reg regs[] = { REG_STRUCT_INIT(AR5K_CPC1), REG_STRUCT_INIT(AR5K_CPC2), REG_STRUCT_INIT(AR5K_CPC3), - REG_STRUCT_INIT(AR5K_CPCORN), + REG_STRUCT_INIT(AR5K_CPCOVF), REG_STRUCT_INIT(AR5K_RESET_CTL), REG_STRUCT_INIT(AR5K_SLEEP_CTL), REG_STRUCT_INIT(AR5K_INTPEND), diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index 2cf8d18b10e..ffc52939330 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -63,7 +63,6 @@ struct ath5k_softc; struct ath5k_hw; -struct ieee80211_hw_mode; struct sk_buff; struct ath5k_buf; diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 7ca87a55731..ad1a5b422c8 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -139,6 +139,8 @@ static int ath5k_hw_post(struct ath5k_hw *ah) for (c = 0; c < 2; c++) { cur_reg = regs[c]; + + /* Save previous value */ init_val = ath5k_hw_reg_read(ah, cur_reg); for (i = 0; i < 256; i++) { @@ -170,6 +172,10 @@ static int ath5k_hw_post(struct ath5k_hw *ah) var_pattern = 0x003b080f; ath5k_hw_reg_write(ah, var_pattern, cur_reg); } + + /* Restore previous value */ + ath5k_hw_reg_write(ah, init_val, cur_reg); + } return 0; @@ -287,67 +293,42 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) /* Identify the radio chip*/ if (ah->ah_version == AR5K_AR5210) { ah->ah_radio = AR5K_RF5110; + /* + * Register returns 0x0/0x04 for radio revision + * so ath5k_hw_radio_revision doesn't parse the value + * correctly. For now we are based on mac's srev to + * identify RF2425 radio. + */ + } else if (srev == AR5K_SREV_VER_AR2425) { + ah->ah_radio = AR5K_RF2425; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { ah->ah_radio = AR5K_RF5111; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { - ah->ah_radio = AR5K_RF5112; - - if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; - } else { - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - } - + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { ah->ah_radio = AR5K_RF2413; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { ah->ah_radio = AR5K_RF5413; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { - /* AR5424 */ if (srev >= AR5K_SREV_VER_AR5424) { ah->ah_radio = AR5K_RF5413; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; /* AR2424 */ } else { ah->ah_radio = AR5K_RF2413; /* For testing */ - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; } - - /* - * Register returns 0x4 for radio revision - * so ath5k_hw_radio_revision doesn't parse the value - * correctly. For now we are based on mac's srev to - * identify RF2425 radio. - */ - } else if (srev == AR5K_SREV_VER_AR2425) { - ah->ah_radio = AR5K_RF2425; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; } - ah->ah_phy = AR5K_PHY(0); /* - * Identify AR5212-based PCI-E cards - * And write some initial settings. - * - * (doing a "strings" on ndis driver - * -ar5211.sys- reveals the following - * pci-e related functions: - * - * pcieClockReq - * pcieRxErrNotify - * pcieL1SKPEnable - * pcieAspm - * pcieDisableAspmOnRfWake - * pciePowerSaveEnable - * - * I guess these point to ClockReq but - * i'm not sure.) + * Write PCI-E power save settings */ if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); @@ -369,10 +350,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) if (ret) goto err_free; + /* Write AR5K_PCICFG_UNK on 2112B and later chips */ + if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B || + srev > AR5K_SREV_VER_AR2413) { + ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG); + } + /* * Get card capabilities, values, ... */ - ret = ath5k_eeprom_init(ah); if (ret) { ATH5K_ERR(sc, "unable to init EEPROM\n"); @@ -843,27 +829,41 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, * Write some more initial register settings */ if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11)); + ath5k_hw_reg_write(ah, 0x0002a002, 0x982c); if (channel->hw_value == CHANNEL_G) if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413) ath5k_hw_reg_write(ah, 0x00f80d80, - AR5K_PHY(83)); + 0x994c); else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424) ath5k_hw_reg_write(ah, 0x00380140, - AR5K_PHY(83)); + 0x994c); else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425) ath5k_hw_reg_write(ah, 0x00fc0ec0, - AR5K_PHY(83)); + 0x994c); else /* 2425 */ ath5k_hw_reg_write(ah, 0x00fc0fc0, - AR5K_PHY(83)); + 0x994c); else - ath5k_hw_reg_write(ah, 0x00000000, - AR5K_PHY(83)); - - ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); - ath5k_hw_reg_write(ah, 0x0000000f, 0x8060); + ath5k_hw_reg_write(ah, 0x00000000, 0x994c); + + /* Some bits are disabled here, we know nothing about + * register 0xa228 yet, most of the times this ends up + * with a value 0x9b5 -haven't seen any dump with + * a different value- */ + /* Got this from decompiling binary HAL */ + data = ath5k_hw_reg_read(ah, 0xa228); + data &= 0xfffffdff; + ath5k_hw_reg_write(ah, data, 0xa228); + + data = ath5k_hw_reg_read(ah, 0xa228); + data &= 0xfffe03ff; + ath5k_hw_reg_write(ah, data, 0xa228); + data = 0; + + /* Just write 0x9b5 ? */ + /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */ + ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); ath5k_hw_reg_write(ah, 0x00000000, 0xa254); ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL); } @@ -879,6 +879,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, else data = 0xffb80d20; ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); + data = 0; } /* @@ -898,7 +899,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /* * Write RF registers - * TODO:Does this work on 5211 (5111) ? */ ret = ath5k_hw_rfregs(ah, channel, mode); if (ret) @@ -935,7 +935,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, return ret; /* Set antenna mode */ - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x44), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL, ah->ah_antenna[ee_mode][0], 0xfffffc06); /* @@ -965,15 +965,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), - AR5K_PHY(0x5a)); + AR5K_PHY_NFTHRES); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x11), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING, (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, 0xffffc07f); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x12), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN, (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, 0xfffc0fff); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x14), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE, (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), 0xffff0000); @@ -982,13 +982,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | - (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY(0x0d)); + (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x0a), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3, ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x19), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF, (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x49), 4, 0xffffff01); + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01); AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | @@ -1063,7 +1063,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); /* - * 5111/5112 Specific + * On 5211+ read activation -> rx delay + * and use it. */ if (ah->ah_version != AR5K_AR5210) { data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & @@ -1071,40 +1072,77 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, data = (channel->hw_value & CHANNEL_CCK) ? ((data << 2) / 22) : (data / 10); - udelay(100 + data); + udelay(100 + (2 * data)); + data = 0; } else { mdelay(1); } /* - * Enable calibration and wait until completion + * Perform ADC test (?) + */ + data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); + ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); + for (i = 0; i <= 20; i++) { + if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) + break; + udelay(200); + } + ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1); + data = 0; + + /* + * Start automatic gain calibration + * + * During AGC calibration RX path is re-routed to + * a signal detector so we don't receive anything. + * + * This method is used to calibrate some static offsets + * used together with on-the fly I/Q calibration (the + * one performed via ath5k_hw_phy_calibrate), that doesn't + * interrupt rx path. + * + * If we are in a noisy environment AGC calibration may time + * out. */ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL); + /* At the same time start I/Q calibration for QAM constellation + * -no need for CCK- */ + ah->ah_calibration = false; + if (!(mode == AR5K_MODE_11B)) { + ah->ah_calibration = true; + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_RUN); + } + + /* Wait for gain calibration to finish (we check for I/Q calibration + * during ath5k_phy_calibrate) */ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL, 0, false)) { - ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", + ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", channel->center_freq); return -EAGAIN; } + /* + * Start noise floor calibration + * + * If we run NF calibration before AGC, it always times out. + * Binary HAL starts NF and AGC calibration at the same time + * and only waits for AGC to finish. I believe that's wrong because + * during NF calibration, rx path is also routed to a detector, so if + * it doesn't finish we won't have RX. + * + * XXX: Find an interval that's OK for all cards... + */ ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); if (ret) return ret; - ah->ah_calibration = false; - - /* A and G modes can use QAM modulation which requires enabling - * I and Q calibration. Don't bother in B mode. */ - if (!(mode == AR5K_MODE_11B)) { - ah->ah_calibration = true; - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_RUN); - } - /* * Reset queues and start beacon timers at the end of the reset routine */ @@ -1154,6 +1192,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING); + + data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ; + data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ? + 0x00000f80 : 0x00001380 ; + ath5k_hw_reg_write(ah, data, AR5K_USEC_5211); + data = 0; } if (ah->ah_version == AR5K_AR5212) { @@ -1226,7 +1270,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration) { unsigned int i; - u32 staid; + u32 staid, data; ATH5K_TRACE(ah->ah_sc); staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); @@ -1238,7 +1282,8 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, case AR5K_PM_NETWORK_SLEEP: if (set_chip) ath5k_hw_reg_write(ah, - AR5K_SLEEP_CTL_SLE | sleep_duration, + AR5K_SLEEP_CTL_SLE_ALLOW | + sleep_duration, AR5K_SLEEP_CTL); staid |= AR5K_STA_ID1_PWR_SV; @@ -1253,13 +1298,24 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, break; case AR5K_PM_AWAKE: + + staid &= ~AR5K_STA_ID1_PWR_SV; + if (!set_chip) goto commit; - ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); + /* Preserve sleep duration */ + data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); + if( data & 0xffc00000 ){ + data = 0; + } else { + data = data & 0xfffcffff; + } + + ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); + udelay(15); - for (i = 5000; i > 0; i--) { + for (i = 50; i > 0; i--) { /* Check if the chip did wake up */ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_SPWR_DN) == 0) @@ -1267,15 +1323,13 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, /* Wait a bit and retry */ udelay(200); - ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); + ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); } /* Fail if the chip didn't wake up */ if (i <= 0) return -EIO; - staid &= ~AR5K_STA_ID1_PWR_SV; break; default: @@ -1304,6 +1358,7 @@ void ath5k_hw_start_rx(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); + ath5k_hw_reg_read(ah, AR5K_CR); } /* @@ -1390,6 +1445,7 @@ int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue) } /* Start queue */ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); + ath5k_hw_reg_read(ah, AR5K_CR); } else { /* Return if queue is disabled */ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) @@ -1687,6 +1743,7 @@ enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask) * (they will be re-enabled afterwards). */ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); + ath5k_hw_reg_read(ah, AR5K_IER); old_mask = ah->ah_imr; @@ -3363,11 +3420,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) ath5k_hw_reg_write(ah, ah->ah_turbo ? AR5K_INIT_PROTO_TIME_CNTRL_TURBO : AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); - /* Set PHY register 0x9844 (??) */ + /* Set AR5K_PHY_SETTLING */ ath5k_hw_reg_write(ah, ah->ah_turbo ? - (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 : - (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C, - AR5K_PHY(17)); + (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) + | 0x38 : + (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) + | 0x1C, + AR5K_PHY_SETTLING); /* Set Frame Control Register */ ath5k_hw_reg_write(ah, ah->ah_turbo ? (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | @@ -3488,7 +3547,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_TXE); + AR5K_QCU_MISC_RDY_VEOL_POLICY); } if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index 04c84e9da89..2806b21bf90 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -489,7 +489,7 @@ static const struct ath5k_ini ar5212_ini[] = { { AR5K_QUEUE_TXDP(9), 0x00000000 }, { AR5K_DCU_FP, 0x00000000 }, { AR5K_DCU_TXP, 0x00000000 }, - { AR5K_DCU_TX_FILTER, 0x00000000 }, + { AR5K_DCU_TX_FILTER_0_BASE, 0x00000000 }, /* Unknown table */ { 0x1078, 0x00000000 }, { 0x10b8, 0x00000000 }, @@ -679,7 +679,7 @@ static const struct ath5k_ini ar5212_ini[] = { { AR5K_PHY(645), 0x00106c10 }, { AR5K_PHY(646), 0x009c4060 }, { AR5K_PHY(647), 0x1483800a }, - /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */ + /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413/2425 */ { AR5K_PHY(648), 0x01831061 }, { AR5K_PHY(649), 0x00000400 }, /*{ AR5K_PHY(650), 0x000001b5 },*/ diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index afd8689e5c0..fa0d47faf57 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -1020,6 +1020,74 @@ static const struct ath5k_ini_rfgain rfgain_2413[] = { { AR5K_RF_GAIN(63), { 0x000000f9 } }, }; +/* Initial RF Gain settings for RF2425 */ +static const struct ath5k_ini_rfgain rfgain_2425[] = { + { AR5K_RF_GAIN(0), { 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x00000181 } }, + { AR5K_RF_GAIN(4), { 0x000001c1 } }, + { AR5K_RF_GAIN(5), { 0x00000001 } }, + { AR5K_RF_GAIN(6), { 0x00000041 } }, + { AR5K_RF_GAIN(7), { 0x00000081 } }, + { AR5K_RF_GAIN(8), { 0x00000188 } }, + { AR5K_RF_GAIN(9), { 0x000001c8 } }, + { AR5K_RF_GAIN(10), { 0x00000008 } }, + { AR5K_RF_GAIN(11), { 0x00000048 } }, + { AR5K_RF_GAIN(12), { 0x00000088 } }, + { AR5K_RF_GAIN(13), { 0x00000189 } }, + { AR5K_RF_GAIN(14), { 0x000001c9 } }, + { AR5K_RF_GAIN(15), { 0x00000009 } }, + { AR5K_RF_GAIN(16), { 0x00000049 } }, + { AR5K_RF_GAIN(17), { 0x00000089 } }, + { AR5K_RF_GAIN(18), { 0x000001b0 } }, + { AR5K_RF_GAIN(19), { 0x000001f0 } }, + { AR5K_RF_GAIN(20), { 0x00000030 } }, + { AR5K_RF_GAIN(21), { 0x00000070 } }, + { AR5K_RF_GAIN(22), { 0x00000171 } }, + { AR5K_RF_GAIN(23), { 0x000001b1 } }, + { AR5K_RF_GAIN(24), { 0x000001f1 } }, + { AR5K_RF_GAIN(25), { 0x00000031 } }, + { AR5K_RF_GAIN(26), { 0x00000071 } }, + { AR5K_RF_GAIN(27), { 0x000001b8 } }, + { AR5K_RF_GAIN(28), { 0x000001f8 } }, + { AR5K_RF_GAIN(29), { 0x00000038 } }, + { AR5K_RF_GAIN(30), { 0x00000078 } }, + { AR5K_RF_GAIN(31), { 0x000000b8 } }, + { AR5K_RF_GAIN(32), { 0x000001b9 } }, + { AR5K_RF_GAIN(33), { 0x000001f9 } }, + { AR5K_RF_GAIN(34), { 0x00000039 } }, + { AR5K_RF_GAIN(35), { 0x00000079 } }, + { AR5K_RF_GAIN(36), { 0x000000b9 } }, + { AR5K_RF_GAIN(37), { 0x000000f9 } }, + { AR5K_RF_GAIN(38), { 0x000000f9 } }, + { AR5K_RF_GAIN(39), { 0x000000f9 } }, + { AR5K_RF_GAIN(40), { 0x000000f9 } }, + { AR5K_RF_GAIN(41), { 0x000000f9 } }, + { AR5K_RF_GAIN(42), { 0x000000f9 } }, + { AR5K_RF_GAIN(43), { 0x000000f9 } }, + { AR5K_RF_GAIN(44), { 0x000000f9 } }, + { AR5K_RF_GAIN(45), { 0x000000f9 } }, + { AR5K_RF_GAIN(46), { 0x000000f9 } }, + { AR5K_RF_GAIN(47), { 0x000000f9 } }, + { AR5K_RF_GAIN(48), { 0x000000f9 } }, + { AR5K_RF_GAIN(49), { 0x000000f9 } }, + { AR5K_RF_GAIN(50), { 0x000000f9 } }, + { AR5K_RF_GAIN(51), { 0x000000f9 } }, + { AR5K_RF_GAIN(52), { 0x000000f9 } }, + { AR5K_RF_GAIN(53), { 0x000000f9 } }, + { AR5K_RF_GAIN(54), { 0x000000f9 } }, + { AR5K_RF_GAIN(55), { 0x000000f9 } }, + { AR5K_RF_GAIN(56), { 0x000000f9 } }, + { AR5K_RF_GAIN(57), { 0x000000f9 } }, + { AR5K_RF_GAIN(58), { 0x000000f9 } }, + { AR5K_RF_GAIN(59), { 0x000000f9 } }, + { AR5K_RF_GAIN(60), { 0x000000f9 } }, + { AR5K_RF_GAIN(61), { 0x000000f9 } }, + { AR5K_RF_GAIN(62), { 0x000000f9 } }, + { AR5K_RF_GAIN(63), { 0x000000f9 } }, +}; + static const struct ath5k_gain_opt rfgain_opt_5112 = { 1, 8, @@ -1588,8 +1656,8 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) freq = 0; /* only 2Ghz */ break; case AR5K_RF2425: - ath5k_rfg = rfgain_2413; - size = ARRAY_SIZE(rfgain_2413); + ath5k_rfg = rfgain_2425; + size = ARRAY_SIZE(rfgain_2425); freq = 0; /* only 2Ghz */ break; default: @@ -1830,9 +1898,6 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, data = data0 = data1 = data2 = 0; c = channel->center_freq; - /* - * Set the channel on the RF5112 or newer - */ if (c < 4800) { if (!((c - 2224) % 5)) { data0 = ((2 * (c - 704)) - 3040) / 10; @@ -1844,7 +1909,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, return -EINVAL; data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); - } else { + } else if ((c - (c % 5)) != 2 || c > 5435) { if (!(c % 20) && c >= 5120) { data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); data2 = ath5k_hw_bitswap(3, 2); @@ -1856,6 +1921,9 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, data2 = ath5k_hw_bitswap(1, 2); } else return -EINVAL; + } else { + data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data2 = ath5k_hw_bitswap(0, 2); } data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; @@ -1867,6 +1935,45 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, } /* + * Set the channel on the RF2425 + */ +static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u32 data, data0, data2; + u16 c; + + data = data0 = data2 = 0; + c = channel->center_freq; + + if (c < 4800) { + data0 = ath5k_hw_bitswap((c - 2272), 8); + data2 = 0; + /* ? 5GHz ? */ + } else if ((c - (c % 5)) != 2 || c > 5435) { + if (!(c % 20) && c < 5120) + data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); + else if (!(c % 10)) + data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); + else if (!(c % 5)) + data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); + else + return -EINVAL; + data2 = ath5k_hw_bitswap(1, 2); + } else { + data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data2 = ath5k_hw_bitswap(0, 2); + } + + data = (data0 << 4) | data2 << 2 | 0x1001; + + ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); + ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); + + return 0; +} + +/* * Set a channel on the radio chip */ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) @@ -1895,6 +2002,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) case AR5K_RF5111: ret = ath5k_hw_rf5111_channel(ah, channel); break; + case AR5K_RF2425: + ret = ath5k_hw_rf2425_channel(ah, channel); + break; default: ret = ath5k_hw_rf5112_channel(ah, channel); break; @@ -1903,6 +2013,15 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) if (ret) return ret; + /* Set JAPAN setting for channel 14 */ + if (channel->center_freq == 2484) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, + AR5K_PHY_CCKTXCTL_JAPAN); + } else { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, + AR5K_PHY_CCKTXCTL_WORLD); + } + ah->ah_current_channel.center_freq = channel->center_freq; ah->ah_current_channel.hw_value = channel->hw_value; ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; @@ -1933,6 +2052,8 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 * + * XXX: Since during noise floor calibration antennas are detached according to + * the patent, we should stop tx queues here. */ int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) @@ -1942,7 +2063,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) s32 noise_floor; /* - * Enable noise floor calibration and wait until completion + * Enable noise floor calibration */ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF); @@ -1952,7 +2073,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) if (ret) { ATH5K_ERR(ah->ah_sc, "noise floor calibration timeout (%uMHz)\n", freq); - return ret; + return -EAGAIN; } /* Wait until the noise floor is calibrated and read the value */ @@ -1974,7 +2095,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { ATH5K_ERR(ah->ah_sc, "noise floor calibration failed (%uMHz)\n", freq); - return -EIO; + return -EAGAIN; } ah->ah_noise_floor = noise_floor; @@ -2087,38 +2208,66 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, } /* - * Perform a PHY calibration on RF5111/5112 + * Perform a PHY calibration on RF5111/5112 and newer chips */ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u32 i_pwr, q_pwr; s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; + int i; ATH5K_TRACE(ah->ah_sc); if (!ah->ah_calibration || - ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) + ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) goto done; - ah->ah_calibration = false; + /* Calibration has finished, get the results and re-run */ |