void ar5416ConfigureSpectralScan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) { u_int32_t val; ar5416PrepSpectralScan(ah); val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) { val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD; val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); } if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); } if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) { val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD; val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD); } /* This section is different for Kiwi and Merlin */ if( AR_SREV_MERLIN(ah) ) { if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { val &= ~AR_PHY_SPECTRAL_SCAN_COUNT; val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT); } if (ss->ss_short_report == AH_TRUE) { val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; } else { val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; } } else { if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) { /* In Merlin, for continous scan, scan_count = 128. * In case of Kiwi, this value should be 0 */ if( ss->ss_count == 128 ) ss->ss_count = 0; val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI; val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); } if (ss->ss_short_report == AH_TRUE) { val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; } else { val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; } //Select the mask to be same as before val |= AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT_KIWI; } // Enable spectral scan OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENA); ar5416GetSpectralParams(ah, ss); }
/*--ar5416ConfigureScanCount-- * Sets the scan count to inVal */ void ar5416ConfigScanCount(struct ath_hal *ah, u_int32_t inVal) { u_int32_t val; val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); if( AR_SREV_MERLIN(ah)) { val &= ~AR_PHY_SPECTRAL_SCAN_COUNT; val |= SM(inVal, AR_PHY_SPECTRAL_SCAN_COUNT); } else { val &= ~AR_PHY_SPECTRAL_SCAN_COUNT_KIWI; val |= SM(inVal, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); } OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val ); }
/*--ar5416ConfigureShortRpt-- * Sets/resets the short report bit based on inVal */ void ar5416ConfigShortRpt(struct ath_hal *ah, u_int32_t inVal) { u_int32_t val; val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); if( AR_SREV_MERLIN(ah)) { if(inVal) val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; else val &= ~(AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); } else { if(inVal) val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; else val &= ~(AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI); } OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val ); }
/* * Get the spectral parameter values and return them in the pe * structure */ void ar5416GetSpectralParams(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss) { uint32_t val; val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN); ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD); ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD); if (AR_SREV_MERLIN(ah) ) { ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT); ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); } else { ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT_KIWI); ss->ss_short_report = MS(val, AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI); } val = OS_REG_READ(ah, AR_PHY_RADAR_1); ss->radar_bin_thresh_sel = MS(val, AR_PHY_RADAR_1_BIN_THRESH_SELECT); }
/* * Reads the Interrupt Status Register value from the NIC, thus deasserting * the interrupt line, and returns both the masked and unmasked mapped ISR * values. The value returned is mapped to abstract the hw-specific bit * locations in the Interrupt Status Register. * * (*masked) is cleared on initial call. * * Returns: A hardware-abstracted bitmap of all non-masked-out * interrupts pending, as well as an unmasked value */ HAL_BOOL ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked) { uint32_t isr, isr0, isr1, sync_cause; /* * Verify there's a mac interrupt and the RTC is on. */ if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) && (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON) isr = OS_REG_READ(ah, AR_ISR); else isr = 0; sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE); sync_cause &= AR_INTR_SYNC_DEFAULT; *masked = 0; if (isr == 0 && sync_cause == 0) return AH_FALSE; if (isr != 0) { struct ath_hal_5212 *ahp = AH5212(ah); uint32_t mask2; mask2 = 0; if (isr & AR_ISR_BCNMISC) { uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2); if (isr2 & AR_ISR_S2_TIM) mask2 |= HAL_INT_TIM; if (isr2 & AR_ISR_S2_DTIM) mask2 |= HAL_INT_DTIM; if (isr2 & AR_ISR_S2_DTIMSYNC) mask2 |= HAL_INT_DTIMSYNC; if (isr2 & (AR_ISR_S2_CABEND )) mask2 |= HAL_INT_CABEND; if (isr2 & AR_ISR_S2_GTT) mask2 |= HAL_INT_GTT; if (isr2 & AR_ISR_S2_CST) mask2 |= HAL_INT_CST; if (isr2 & AR_ISR_S2_TSFOOR) mask2 |= HAL_INT_TSFOOR; } isr = OS_REG_READ(ah, AR_ISR_RAC); if (isr == 0xffffffff) { *masked = 0; return AH_FALSE; } *masked = isr & HAL_INT_COMMON; if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) *masked |= HAL_INT_RX; if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | AR_ISR_TXEOL)) { *masked |= HAL_INT_TX; isr0 = OS_REG_READ(ah, AR_ISR_S0_S); ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK); ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC); isr1 = OS_REG_READ(ah, AR_ISR_S1_S); ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR); ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL); } if (AR_SREV_MERLIN(ah) || AR_SREV_KITE(ah)) { uint32_t isr5; isr5 = OS_REG_READ(ah, AR_ISR_S5_S); if (isr5 & AR_ISR_S5_TIM_TIMER) *masked |= HAL_INT_TIM_TIMER; } /* Interrupt Mitigation on AR5416 */ #ifdef AR5416_INT_MITIGATION if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) *masked |= HAL_INT_RX; if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) *masked |= HAL_INT_TX; #endif *masked |= mask2; } if (sync_cause != 0) { if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) { *masked |= HAL_INT_FATAL; } if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RADM CPL timeout\n", __func__); OS_REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); OS_REG_WRITE(ah, AR_RC, 0); *masked |= HAL_INT_FATAL; } /* * On fatal errors collect ISR state for debugging. */ if (*masked & HAL_INT_FATAL) { AH_PRIVATE(ah)->ah_fatalState[0] = isr; AH_PRIVATE(ah)->ah_fatalState[1] = sync_cause; HALDEBUG(ah, HAL_DEBUG_ANY, "%s: fatal error, ISR_RAC 0x%x SYNC_CAUSE 0x%x\n", __func__, isr, sync_cause); } OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); /* NB: flush write */ (void) OS_REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); } return AH_TRUE; }
HAL_BOOL ar5416WowEnable(struct ath_hal *ah, u_int32_t pattern_enable, u_int32_t timeoutInSeconds, int clearbssid) { uint32_t init_val, val, rval=0; const int ka_delay = 4; /* Delay of 4 millisec between two KeepAlive's */ uint32_t wow_event_mask; /* * ah_wow_event_mask is a mask to the AR_WOW_PATTERN_REG register to indicate * which WOW events that we have enabled. The WOW Events are from the * pattern_enable in this function and pattern_count of ar5416WowApplyPattern() */ wow_event_mask = AH_PRIVATE(ah)->ah_wow_event_mask; /* * Untie Power-On-Reset from the PCI-E Reset. When we are in WOW sleep, * we do not want the Reset from the PCI-E to disturb our hw state. */ if (AR_SREV_MERLIN_20_OR_LATER(ah) && (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE)) { /* * We need to untie the internal POR (power-on-reset) to the external * PCI-E reset. We also need to tie the PCI-E Phy reset to the PCI-E reset. */ u_int32_t wa_reg_val; if (AR_SREV_KITE(ah) || AR_SREV_KIWI(ah)) wa_reg_val = AR9285_WA_DEFAULT; else wa_reg_val = AR9280_WA_DEFAULT; /* * In Merlin and Kite, bit 14 in WA register (disable L1) should only * be set when device enters D3 and be cleared when device comes back to D0. */ if (AH_PRIVATE(ah)->ah_config.ath_hal_pcie_waen & AR_WA_D3_L1_DISABLE) wa_reg_val = wa_reg_val | AR_WA_D3_L1_DISABLE; wa_reg_val = wa_reg_val & ~(AR_WA_UNTIE_RESET_EN); wa_reg_val = wa_reg_val | AR_WA_RESET_EN | AR_WA_POR_SHORT; OS_REG_WRITE(ah, AR_WA, wa_reg_val); if (!AR_SREV_KITE(ah) || AR_SREV_KITE_12_OR_LATER(ah)) { /* s * For WOW sleep, we reprogram the SerDes so that the PLL and CHK REQ * are both enabled. This uses more power but the Maverick team reported * that otherwise, WOW sleep is unable and chip may disappears. */ ar928xConfigSerDes_WowSleep(ah); } } /* * Set the power states appropriately and enable pme. */ val = OS_REG_READ(ah, AR_PCIE_PM_CTRL); val |= AR_PMCTRL_HOST_PME_EN | \ AR_PMCTRL_PWR_PM_CTRL_ENA | AR_PMCTRL_AUX_PWR_DET; val &= ~AR_PMCTRL_WOW_PME_CLR; OS_REG_WRITE(ah, AR_PCIE_PM_CTRL, val); /* * Setup for for: * - beacon misses * - magic pattern * - keep alive timeout * - pattern matching */ /* * Program some default values for keep-alives, beacon misses, etc. */ init_val = OS_REG_READ(ah, AR_WOW_PATTERN_REG); val = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF) | init_val; OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val); rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG); init_val = OS_REG_READ(ah, AR_WOW_COUNT_REG); val = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) | \ AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) | \ AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT); OS_REG_WRITE(ah, AR_WOW_COUNT_REG, val); rval = OS_REG_READ(ah, AR_WOW_COUNT_REG); init_val = OS_REG_READ(ah, AR_WOW_BCN_TIMO_REG); if (pattern_enable & AH_WOW_BEACON_MISS) { val = AR_WOW_BEACON_TIMO; } else { /* We are not using the beacon miss. Program a large value. */ val = AR_WOW_BEACON_TIMO_MAX; } OS_REG_WRITE(ah, AR_WOW_BCN_TIMO_REG, val); rval = OS_REG_READ(ah, AR_WOW_BCN_TIMO_REG); init_val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_TIMO_REG); /* * Keep Alive Timo in ms, except Merlin - see EV 62708 */ if (pattern_enable == 0 || AR_SREV_MERLIN(ah)) { val = AR_WOW_KEEP_ALIVE_NEVER; } else { val = AH_PRIVATE(ah)->ah_config.ath_hal_keep_alive_timeout * 32; } OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO_REG, val); rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_TIMO_REG); init_val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_DELAY_REG); /* * Keep Alive delay in us. Based on 'power on clock' , therefore in uSec */ val = ka_delay * 1000; OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY_REG, val); rval = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_DELAY_REG); /* * Create KeepAlive Pattern to respond to beacons. */ ar5416WowCreateKeepAlivePattern(ah); /* * Configure Mac Wow Registers. */ val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG); /* * Send keep alive timeouts anyway. */ val &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS; if (pattern_enable & AH_WOW_LINK_CHANGE) { val &= ~ AR_WOW_KEEP_ALIVE_FAIL_DIS; wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; } else { val |= AR_WOW_KEEP_ALIVE_FAIL_DIS; } OS_REG_WRITE(ah, AR_WOW_KEEP_ALIVE_REG, val); val = OS_REG_READ(ah, AR_WOW_KEEP_ALIVE_REG); val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG); /* * We are relying on a bmiss failure. Ensure we have enough * threshold to prevent false positives. */ OS_REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, AR_WOW_BMISSTHRESHOLD); /* * Beacon miss & user pattern events are broken in Owl. * Enable only for Merlin. * The workaround is done at the ath_dev layer using the * sc->sc_wow_bmiss_intr field. * XXX: we need to cleanup this workaround before the next chip that * fixes this issue. */ if (!AR_SREV_MERLIN_10_OR_LATER(ah)) pattern_enable &= ~AH_WOW_BEACON_MISS; if (pattern_enable & AH_WOW_BEACON_MISS) { val |= AR_WOW_BEACON_FAIL_EN; wow_event_mask |= AR_WOW_BEACON_FAIL; } else { val &= ~AR_WOW_BEACON_FAIL_EN; } OS_REG_WRITE(ah, AR_WOW_BCN_EN_REG, val); val = OS_REG_READ(ah, AR_WOW_BCN_EN_REG); /* * Enable the magic packet registers. */ val = OS_REG_READ(ah, AR_WOW_PATTERN_REG); if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { val |= AR_WOW_MAGIC_EN; wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; } else { val &= ~AR_WOW_MAGIC_EN; } val |= AR_WOW_MAC_INTR_EN; OS_REG_WRITE(ah, AR_WOW_PATTERN_REG, val); val = OS_REG_READ(ah, AR_WOW_PATTERN_REG); /* For Kite and later version of the chips * enable wow pattern match for packets less than * 256 bytes for all patterns. */ if (AR_SREV_KITE_10_OR_LATER(ah)) { OS_REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B_REG, AR_WOW_PATTERN_SUPPORTED); } /* * Set the power states appropriately and enable pme. */ val = OS_REG_READ(ah, AR_PCIE_PM_CTRL); val |= AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA; OS_REG_WRITE(ah, AR_PCIE_PM_CTRL, val); if (timeoutInSeconds) { /* The clearbssid parameter is set only for the case where the wake needs to be on a timeout. The timeout mechanism, at this time, is specific to Maverick. For a manuf test, the system is put into sleep with a timer. On timer expiry, the chip interrupts(timer) and wakes the system. Clearbssid is specified as TRUE since we do not want a spurious beacon miss. If specified as true, we clear the bssid regs. */ // Setup the timer. OS_REG_WRITE(ah, AR_NEXT_NDP_TIMER, OS_REG_READ(ah, AR_TSF_L32) + timeoutInSeconds * 1000000 ); // convert Timeout to uSecs. OS_REG_WRITE(ah, AR_NDP_PERIOD, 30 * 1000000); // timer_period = 30 seconds always. OS_REG_WRITE(ah, AR_TIMER_MODE, OS_REG_READ(ah, AR_TIMER_MODE) | AR_NDP_TIMER_EN); // Enable the timer interrupt OS_REG_WRITE(ah, AR_IMR_S5, OS_REG_READ(ah, AR_IMR_S5) | AR_IMR_S5_GENTIMER7); OS_REG_WRITE(ah, AR_IMR, OS_REG_READ(ah, AR_IMR) | AR_IMR_GENTMR); if (clearbssid) { // If the bssid regs are set and all we want is a wake on timer, we run into an issue // with the wake coming in too early. OS_REG_WRITE(ah, AR_BSS_ID0, 0); OS_REG_WRITE(ah, AR_BSS_ID1, 0); } } /* * enable seq number generation in hw */ OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); ar5416SetPowerModeWowSleep(ah); AH_PRIVATE(ah)->ah_wow_event_mask = wow_event_mask; return (AH_TRUE); }
static HAL_BOOL ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) { static const uint32_t ar5416_cca_regs[] = { AR_PHY_CCA, AR_PHY_CH1_CCA, AR_PHY_CH2_CCA, AR_PHY_EXT_CCA, AR_PHY_CH1_EXT_CCA, AR_PHY_CH2_EXT_CCA }; struct ar5212NfCalHist *h; int i; int32_t val; uint8_t chainmask; int16_t default_nf = ar5416GetDefaultNF(ah, chan); /* * Force NF calibration for all chains. */ if (AR_SREV_KITE(ah)) { /* Kite has only one chain */ chainmask = 0x9; } else if (AR_SREV_MERLIN(ah) || AR_SREV_KIWI(ah)) { /* Merlin/Kiwi has only two chains */ chainmask = 0x1B; } else { chainmask = 0x3F; } /* * Write filtered NF values into maxCCApwr register parameter * so we can load below. */ h = AH5416(ah)->ah_cal.nfCalHist; HALDEBUG(ah, HAL_DEBUG_NFCAL, "CCA: "); for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { /* Don't write to EXT radio CCA registers unless in HT/40 mode */ /* XXX this check should really be cleaner! */ if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) continue; if (chainmask & (1 << i)) { int16_t nf_val; if (h) nf_val = h[i].privNF; else nf_val = default_nf; val = OS_REG_READ(ah, ar5416_cca_regs[i]); val &= 0xFFFFFE00; val |= (((uint32_t) nf_val << 1) & 0x1ff); HALDEBUG(ah, HAL_DEBUG_NFCAL, "[%d: %d]", i, nf_val); OS_REG_WRITE(ah, ar5416_cca_regs[i], val); } } HALDEBUG(ah, HAL_DEBUG_NFCAL, "\n"); /* Load software filtered NF value into baseband internal minCCApwr variable. */ OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); /* Wait for load to complete, should be fast, a few 10s of us. */ if (! ar5212WaitNFCalComplete(ah, 1000)) { /* * We timed out waiting for the noisefloor to load, probably due to an * in-progress rx. Simply return here and allow the load plenty of time * to complete before the next calibration interval. We need to avoid * trying to load -50 (which happens below) while the previous load is * still in progress as this can cause rx deafness. Instead by returning * here, the baseband nf cal will just be capped by our present * noisefloor until the next calibration timer. */ HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "Timeout while waiting for " "nf to load: AR_PHY_AGC_CONTROL=0x%x\n", OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); return AH_FALSE; } /* * Restore maxCCAPower register parameter again so that we're not capped * by the median we just loaded. This will be initial (and max) value * of next noise floor calibration the baseband does. */ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) { /* Don't write to EXT radio CCA registers unless in HT/40 mode */ /* XXX this check should really be cleaner! */ if (i > 2 && !IEEE80211_IS_CHAN_HT40(chan)) continue; if (chainmask & (1 << i)) { val = OS_REG_READ(ah, ar5416_cca_regs[i]); val &= 0xFFFFFE00; val |= (((uint32_t)(-50) << 1) & 0x1ff); OS_REG_WRITE(ah, ar5416_cca_regs[i], val); } } return AH_TRUE; }
/* * ar5416SpectralScanCapable * ------------------------- * Returns the Spectral scan capability */ u_int32_t ar5416SpectralScanCapable( struct ath_hal *ah) { return (AR_SREV_MERLIN(ah) || AR_SREV_KIWI(ah)); }
static void ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) { static const uint32_t ar5416_cca_regs[] = { AR_PHY_CCA, AR_PHY_CH1_CCA, AR_PHY_CH2_CCA, AR_PHY_EXT_CCA, AR_PHY_CH1_EXT_CCA, AR_PHY_CH2_EXT_CCA }; struct ar5212NfCalHist *h; int i, j; int32_t val; uint8_t chainmask; /* * Force NF calibration for all chains. */ if (AR_SREV_KITE(ah)) { /* Kite has only one chain */ chainmask = 0x9; } else if (AR_SREV_MERLIN(ah)) { /* Merlin has only two chains */ chainmask = 0x1B; } else { chainmask = 0x3F; } /* * Write filtered NF values into maxCCApwr register parameter * so we can load below. */ h = AH5416(ah)->ah_cal.nfCalHist; for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) if (chainmask & (1 << i)) { val = OS_REG_READ(ah, ar5416_cca_regs[i]); val &= 0xFFFFFE00; val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff); OS_REG_WRITE(ah, ar5416_cca_regs[i], val); } /* Load software filtered NF value into baseband internal minCCApwr variable. */ OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF); OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF); OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); /* Wait for load to complete, should be fast, a few 10s of us. */ for (j = 0; j < 1000; j++) { if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) break; OS_DELAY(10); } /* * Restore maxCCAPower register parameter again so that we're not capped * by the median we just loaded. This will be initial (and max) value * of next noise floor calibration the baseband does. */ for (i = 0; i < AR5416_NUM_NF_READINGS; i ++) if (chainmask & (1 << i)) { val = OS_REG_READ(ah, ar5416_cca_regs[i]); val &= 0xFFFFFE00; val |= (((uint32_t)(-50) << 1) & 0x1ff); OS_REG_WRITE(ah, ar5416_cca_regs[i], val); } }