123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- From: Felix Fietkau <nbd@nbd.name>
- 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 <nbd@nbd.name>
- ---
- --- a/drivers/net/wireless/ath/ath9k/hw.c
- +++ b/drivers/net/wireless/ath/ath9k/hw.c
- @@ -1271,39 +1271,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, 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, 0);
- + udelay(10);
- + }
- +
- + REG_WRITE(ah, AR_RTC_RESET, 1);
- + udelay(10);
- +
- return true;
- }
-
- @@ -1356,24 +1373,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, rst_flags);
-
- REGWRITE_BUFFER_FLUSH(ah);
|