예제 #1
0
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);
}
예제 #2
0
/*--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 );
}
예제 #3
0
/*--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 );
}
예제 #4
0
/*
 * 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;
}
예제 #6
0
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);
}
예제 #7
0
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;
}
예제 #8
0
/*
 * ar5416SpectralScanCapable
 * -------------------------
 *  Returns the Spectral scan capability
 */
u_int32_t ar5416SpectralScanCapable( struct ath_hal *ah)
{
    return (AR_SREV_MERLIN(ah) || AR_SREV_KIWI(ah));
}
예제 #9
0
파일: ar5416_cal.c 프로젝트: luciang/haiku
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);
		}
}