From: Felix Fietkau Date: Sat, 9 Jul 2016 15:26:44 +0200 Subject: [PATCH] ath9k_hw: issue external reset for QCA955x The RTC interface on the SoC needs to be reset along with the rest of the WMAC. Signed-off-by: Felix Fietkau --- --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1311,39 +1311,56 @@ void ath9k_hw_get_delta_slope_vals(struc *coef_exponent = coef_exp - 16; } -/* AR9330 WAR: - * call external reset function to reset WMAC if: - * - doing a cold reset - * - we have pending frames in the TX queues. - */ -static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) +static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type) { - int i, npend = 0; + int i; - for (i = 0; i < AR_NUM_QCU; i++) { - npend = ath9k_hw_numtxpending(ah, i); - if (npend) - break; - } - - if (ah->external_reset && - (npend || type == ATH9K_RESET_COLD)) { - int reset_err = 0; - - ath_dbg(ath9k_hw_common(ah), RESET, - "reset MAC via external reset\n"); - - reset_err = ah->external_reset(); - if (reset_err) { - ath_err(ath9k_hw_common(ah), - "External reset failed, err=%d\n", - reset_err); - return false; + if (type == ATH9K_RESET_COLD) + return true; + + if (AR_SREV_9550(ah)) + return true; + + /* AR9330 WAR: + * call external reset function to reset WMAC if: + * - doing a cold reset + * - we have pending frames in the TX queues. + */ + if (AR_SREV_9330(ah)) { + for (i = 0; i < AR_NUM_QCU; i++) { + if (ath9k_hw_numtxpending(ah, i)) + return true; } + } + + return false; +} + +static bool ath9k_hw_external_reset(struct ath_hw *ah, int type) +{ + int err; + + if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type)) + return true; + + ath_dbg(ath9k_hw_common(ah), RESET, + "reset MAC via external reset\n"); - REG_WRITE(ah, AR_RTC_RESET(ah), 1); + err = ah->external_reset(); + if (err) { + ath_err(ath9k_hw_common(ah), + "External reset failed, err=%d\n", err); + return false; } + if (AR_SREV_9550(ah)) { + REG_WRITE(ah, AR_RTC_RESET(ah), 0); + udelay(10); + } + + REG_WRITE(ah, AR_RTC_RESET(ah), 1); + udelay(10); + return true; } @@ -1396,24 +1413,24 @@ static bool ath9k_hw_set_reset(struct at rst_flags |= AR_RTC_RC_MAC_COLD; } - if (AR_SREV_9330(ah)) { - if (!ath9k_hw_ar9330_reset_war(ah, type)) - return false; - } - if (ath9k_hw_mci_is_enabled(ah)) ar9003_mci_check_gpm_offset(ah); /* DMA HALT added to resolve ar9300 and ar9580 bus error during - * RTC_RC reg read + * RTC_RC reg read. Also needed for AR9550 external reset */ - if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { + if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, 20 * AH_WAIT_TIMEOUT); - REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); } + if (!AR_SREV_9100(ah)) + ath9k_hw_external_reset(ah, type); + + if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) + REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + REG_WRITE(ah, AR_RTC_RC(ah), rst_flags); REGWRITE_BUFFER_FLUSH(ah);