示例#1
0
/*
 * Once configured for I/O - get input lines
 */
u_int32_t
ar5416GpioGet(struct ath_hal *ah, u_int32_t gpio)
{
    HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins);

    if (gpio >= AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins) {
        return 0xffffffff;
    }

    // Read output value for all gpio's, shift it left, and verify whether a 
    // specific gpio bit is set.
    if(AR_SREV_K2(ah)) {
        u_int32_t val;
         
        val = OS_REG_READ(ah, AR_GPIO_IN_OUT);
        if (val == (u_int32_t)(-1)) {
            return 0;
        } else {
            return (MS(val, AR9271_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
        }
    }
    else if (AR_SREV_KIWI_10_OR_LATER(ah)) {
        return (MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9287_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
    } else if (AR_SREV_KITE_10_OR_LATER(ah)) {
        return (MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR9285_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
    } else if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
        return (MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
    } else {
        return (MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
    }
}
示例#2
0
void
ar5416SetCcaThreshold(struct ath_hal *ah, u_int8_t thresh62)
{
    if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
        OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, thresh62);
        OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, thresh62);
        OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CCA_THRESH62, thresh62);
    } else {
        OS_REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, thresh62);
        OS_REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_CCA_THRESH62, thresh62);
    }
}
示例#3
0
/*
 * AGC calibration for the AR5416, AR9130, AR9160, AR9280.
 */
HAL_BOOL
ar5416InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan)
{

	if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		/* Disable ADC */
		OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
		    AR_PHY_ADC_CTL_OFF_PWDADC);

		/* Enable Rx Filter Cal */
		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_FLTR_CAL);
	} 	

	/* Calibrate the AGC */
	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);

	/* Poll for offset calibration complete */
	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: offset calibration did not complete in 1ms; "
		    "noisy environment?\n", __func__);
		return AH_FALSE;
	}

	if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		/* Enable ADC */
		OS_REG_SET_BIT(ah, AR_PHY_ADC_CTL,
		    AR_PHY_ADC_CTL_OFF_PWDADC);

		/* Disable Rx Filter Cal */
		OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_FLTR_CAL);
	}

	return AH_TRUE;
}
/*
 * Once configured for I/O - get input lines
 */
uint32_t
ar5416GpioGet(struct ath_hal *ah, uint32_t gpio)
{
	uint32_t bits;

	if (gpio >= AH_PRIVATE(ah)->ah_caps.halNumGpioPins)
		return 0xffffffff;
	/*
	 * Read output value for all gpio's, shift it,
	 * and verify whether the specific bit is set.
	 */
	if (AR_SREV_MERLIN_10_OR_LATER(ah))
		bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR928X_GPIO_IN_VAL);
	else
		bits = MS(OS_REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL);
	return ((bits & AR_GPIO_BIT(gpio)) != 0);
}
示例#5
0
int16_t ar5416GetExtChanNF(struct ath_hal *ah)
{
    int16_t nf;
    struct ath_hal_private *ahpriv = AH_PRIVATE(ah);

    if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0) {
        /* Noise floor calibration value is ready */
        if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
            nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
        } else {
            nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
        }
    } else {
        /* NF calibration is not done, return nominal value */
        nf = ahpriv->nfp->nominal;    
    }
    if (nf & 0x100)
        nf = (0 - ((nf ^ 0x1ff) + 1));
    return nf;
}
示例#6
0
static void
ar9285WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	u_int modesIndex, freqIndex;
	int regWrites = 0;

	/* Setup the indices for the next set of register array writes */
	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
	freqIndex = 2;
	if (IEEE80211_IS_CHAN_HT40(chan))
		modesIndex = 3;
	else if (IEEE80211_IS_CHAN_108G(chan))
		modesIndex = 5;
	else
		modesIndex = 4;

	/* Set correct Baseband to analog shift setting to access analog chips. */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
	    modesIndex, regWrites);
	if (AR_SREV_KITE_12_OR_LATER(ah)) {
		regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain,
		    modesIndex, regWrites);
	}
	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
	    1, regWrites);

	OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));

	if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		uint32_t val;
		val = OS_REG_READ(ah, AR_PCU_MISC_MODE2) &
			(~AR_PCU_MISC_MODE2_HWWAR1);
		OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
		OS_REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
	}

}
示例#7
0
/*
 * Process an RX descriptor, and return the status to the caller.
 * Copy some hardware specific items into the software portion
 * of the descriptor.
 *
 * NB: the caller is responsible for validating the memory contents
 *     of the descriptor (e.g. flushing any cached copy).
 */
HAL_STATUS
ar5416ProcRxDesc(struct ath_hal *ah, struct ath_desc *ds,
    uint32_t pa, struct ath_desc *nds, uint64_t tsf,
    struct ath_rx_status *rs)
{
	struct ar5416_desc *ads = AR5416DESC(ds);

	if ((ads->ds_rxstatus8 & AR_RxDone) == 0)
		return HAL_EINPROGRESS;

	rs->rs_status = 0;
	rs->rs_flags = 0;

	rs->rs_datalen = ads->ds_rxstatus1 & AR_DataLen;
	rs->rs_tstamp =  ads->AR_RcvTimestamp;

	/* XXX what about KeyCacheMiss? */

	rs->rs_rssi = MS(ads->ds_rxstatus4, AR_RxRSSICombined);
	rs->rs_rssi_ctl[0] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt00);
	rs->rs_rssi_ctl[1] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt01);
	rs->rs_rssi_ctl[2] = MS(ads->ds_rxstatus0, AR_RxRSSIAnt02);
	rs->rs_rssi_ext[0] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt10);
	rs->rs_rssi_ext[1] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt11);
	rs->rs_rssi_ext[2] = MS(ads->ds_rxstatus4, AR_RxRSSIAnt12);

	if (ads->ds_rxstatus8 & AR_RxKeyIdxValid)
		rs->rs_keyix = MS(ads->ds_rxstatus8, AR_KeyIdx);
	else
		rs->rs_keyix = HAL_RXKEYIX_INVALID;

	/* NB: caller expected to do rate table mapping */
	rs->rs_rate = RXSTATUS_RATE(ah, ads);
	rs->rs_more = (ads->ds_rxstatus1 & AR_RxMore) ? 1 : 0;

	rs->rs_isaggr = (ads->ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
	rs->rs_moreaggr = (ads->ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
	rs->rs_antenna = MS(ads->ds_rxstatus3, AR_RxAntenna);

	if (ads->ds_rxstatus3 & AR_GI)
		rs->rs_flags |= HAL_RX_GI;
	if (ads->ds_rxstatus3 & AR_2040)
		rs->rs_flags |= HAL_RX_2040;

	/*
	 * Only the AR9280 and later chips support STBC RX, so
	 * ensure we only set this bit for those chips.
	 */
	if (AR_SREV_MERLIN_10_OR_LATER(ah)
	    && ads->ds_rxstatus3 & AR_STBCFrame)
		rs->rs_flags |= HAL_RX_STBC;

	if (ads->ds_rxstatus8 & AR_PreDelimCRCErr)
		rs->rs_flags |= HAL_RX_DELIM_CRC_PRE;
	if (ads->ds_rxstatus8 & AR_PostDelimCRCErr)
		rs->rs_flags |= HAL_RX_DELIM_CRC_POST;
	if (ads->ds_rxstatus8 & AR_DecryptBusyErr)
		rs->rs_flags |= HAL_RX_DECRYPT_BUSY;
	if (ads->ds_rxstatus8 & AR_HiRxChain)
		rs->rs_flags |= HAL_RX_HI_RX_CHAIN;

	if ((ads->ds_rxstatus8 & AR_RxFrameOK) == 0) {
		/*
		 * These four bits should not be set together.  The
		 * 5416 spec states a Michael error can only occur if
		 * DecryptCRCErr not set (and TKIP is used).  Experience
		 * indicates however that you can also get Michael errors
		 * when a CRC error is detected, but these are specious.
		 * Consequently we filter them out here so we don't
		 * confuse and/or complicate drivers.
		 */

		/*
		 * The AR5416 sometimes sets both AR_CRCErr and AR_PHYErr
		 * when reporting radar pulses.  In this instance
		 * set HAL_RXERR_PHY as well as HAL_RXERR_CRC and
		 * let the driver layer figure out what to do.
		 *
		 * See PR kern/169362.
		 */
		if (ads->ds_rxstatus8 & AR_PHYErr) {
			u_int phyerr;

			/*
			 * Packets with OFDM_RESTART on post delimiter are CRC OK and
			 * usable and MAC ACKs them.
			 * To avoid packet from being lost, we remove the PHY Err flag
			 * so that driver layer does not drop them.
			 */
			phyerr = MS(ads->ds_rxstatus8, AR_PHYErrCode);

			if ((phyerr == HAL_PHYERR_OFDM_RESTART) &&
			    (ads->ds_rxstatus8 & AR_PostDelimCRCErr)) {
				ath_hal_printf(ah,
				    "%s: OFDM_RESTART on post-delim CRC error\n",
				    __func__);
				rs->rs_phyerr = 0;
			} else {
				rs->rs_status |= HAL_RXERR_PHY;
				rs->rs_phyerr = phyerr;
			}
		}
		if (ads->ds_rxstatus8 & AR_CRCErr)
			rs->rs_status |= HAL_RXERR_CRC;
		else if (ads->ds_rxstatus8 & AR_DecryptCRCErr)
			rs->rs_status |= HAL_RXERR_DECRYPT;
		else if (ads->ds_rxstatus8 & AR_MichaelErr)
			rs->rs_status |= HAL_RXERR_MIC;
	}

	return HAL_OK;
}
示例#8
0
u_int32_t
ar5416WowWakeUp(struct ath_hal *ah)
{
    uint32_t wowStatus = 0;
    uint32_t val = 0, rval;

    /*
     * Read the WOW Status register to know the wakeup reason.
     */
    rval = OS_REG_READ(ah, AR_WOW_PATTERN_REG);
    val = AR_WOW_STATUS(rval);
    
    /* 
     * Mask only the WOW events that we have enabled. Sometimes, we have spurious
     * WOW events from the AR_WOW_PATTERN_REG register. This mask will clean it up.
     */
    val &= AH_PRIVATE(ah)->ah_wow_event_mask;
    
    if (val) {
        if (val & AR_WOW_MAGIC_PAT_FOUND) {
            wowStatus |= AH_WOW_MAGIC_PATTERN_EN;
        }
        if (AR_WOW_PATTERN_FOUND(val)) {
            wowStatus |= AH_WOW_USER_PATTERN_EN;
        }
        if (val & AR_WOW_KEEP_ALIVE_FAIL) {
            wowStatus |= AH_WOW_LINK_CHANGE;
        }
        if (val & AR_WOW_BEACON_FAIL) {
            wowStatus |= AH_WOW_BEACON_MISS;
        }
    }

    /*
     * Set and clear WOW_PME_CLEAR registers for the chip to generate next wow signal.
     * Disable D3 before accessing other registers ?
     */
    val = OS_REG_READ(ah, AR_PCIE_PM_CTRL);
    val &= ~AR_PMCTRL_PWR_STATE_D1D3; // Check the bit value 0x01000000 (7-10) ??
    val |= AR_PMCTRL_WOW_PME_CLR;
    OS_REG_WRITE(ah, AR_PCIE_PM_CTRL, val);

    /*
     * Clear all events.
     */
    OS_REG_WRITE(ah, AR_WOW_PATTERN_REG,
        AR_WOW_CLEAR_EVENTS(OS_REG_READ(ah, AR_WOW_PATTERN_REG)));

    /*
     * Tie reset register.
     * FIXME: Per David Quan not tieing it back might have some repurcussions.
     */
    if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
        OS_REG_WRITE(ah, AR_WA, OS_REG_READ(ah, AR_WA) |
            AR_WA_UNTIE_RESET_EN | AR_WA_POR_SHORT | AR_WA_RESET_EN);
    }

    /* Restore the Beacon Threshold to init value */
    OS_REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);

    /*
     * Restore the way the PCI-E Reset, Power-On-Reset, external PCIE_POR_SHORT
     * pins are tied to its original value. Previously just before WOW sleep,
     * we untie the PCI-E Reset to our Chip's Power On Reset so that
     * any PCI-E reset from the bus will not reset our chip.
     */
    if (AR_SREV_MERLIN_20_OR_LATER(ah) && 
        (AH_PRIVATE(ah)->ah_is_pci_express == AH_TRUE)) {
    
        ar5416ConfigPciPowerSave(ah, 0, 0);
    }

    AH_PRIVATE(ah)->ah_wow_event_mask = 0;

    return (wowStatus);
}
示例#9
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);
}
示例#10
0
static void
ar9280AniSetup(struct ath_hal *ah)
{
	/*
	 * These are the parameters from the AR5416 ANI code;
	 * they likely need quite a bit of adjustment for the
	 * AR9280.
	 */
        static const struct ar5212AniParams aniparams = {
                .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
                .totalSizeDesired       = { -55, -55, -55, -55, -62 },
                .coarseHigh             = { -14, -14, -14, -14, -12 },
                .coarseLow              = { -64, -64, -64, -64, -70 },
                .firpwr                 = { -78, -78, -78, -78, -80 },
                .maxSpurImmunityLevel   = 2,
                .cycPwrThr1             = { 2, 4, 6 },
                .maxFirstepLevel        = 2,    /* levels 0..2 */
                .firstep                = { 0, 4, 8 },
                .ofdmTrigHigh           = 500,
                .ofdmTrigLow            = 200,
                .cckTrigHigh            = 200,
                .cckTrigLow             = 100,
                .rssiThrHigh            = 40,
                .rssiThrLow             = 7,
                .period                 = 100,
        };
	/* NB: disable ANI noise immmunity for reliable RIFS rx */
	AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);

        /* NB: ANI is not enabled yet */
        ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}

void
ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);

	if (AR_SREV_MERLIN_20(ah) &&
	    chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) {
		/*
		 * PLL WAR for Merlin 2.0/2.1
		 * When doing fast clock, set PLL to 0x142c
		 * Else, set PLL to 0x2850 to prevent reset-to-reset variation 
		 */
		pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850;
	} else if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
		if (chan != AH_NULL) {
			if (IEEE80211_IS_CHAN_HALF(chan))
				pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
			else if (IEEE80211_IS_CHAN_QUARTER(chan))
				pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
			if (IEEE80211_IS_CHAN_5GHZ(chan))
				pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
			else
				pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
		} else
			pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
	}

	OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
	OS_DELAY(RTC_PLL_SETTLE_DELAY);
	OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
}
示例#11
0
void
ar5416Set11nRateScenario(struct ath_hal *ah, void *ds,
                             void *lastds,
                             u_int dur_update_en, u_int rts_cts_rate, u_int rts_cts_duration,
                             HAL_11N_RATE_SERIES series[], u_int nseries,
                             u_int flags, u_int32_t smartAntenna)
#endif
{
        struct ath_hal_private *ap = AH_PRIVATE(ah);
        struct ar5416_desc *ads = AR5416DESC(ds);
        struct ar5416_desc *last_ads = AR5416DESC(lastds);
        u_int32_t ds_ctl0;
        u_int mode;

        HALASSERT(nseries == 4);
        (void)nseries;
        (void)rts_cts_duration;   /* use H/W to calculate RTSCTSDuration */

        /*
         * Rate control settings override
         */
        ds_ctl0 = ads->ds_ctl0;
        if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) {
            if (flags & HAL_TXDESC_RTSENA) {
                ds_ctl0 &= ~AR_CTSEnable;
                ds_ctl0 |= AR_RTSEnable;
            } else {
                ds_ctl0 &= ~AR_RTSEnable;
                ds_ctl0 |= AR_CTSEnable;
            }
        } else {
            ds_ctl0 = (ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
        }

        mode = ath_hal_get_curmode(ah, ap->ah_curchan);
        if (ap->ah_config.ath_hal_desc_tpc) {
            int16_t txpower;

            txpower = ar5416GetRateTxPower(ah, mode, series[0].rate_index,
                                           series[0].ch_sel);

            if(series[0].tx_power_cap == 0)
            {  
                /*For short range mode, set txpower to MAX to put series[0].TxPowerCap into the descriptor*/
                txpower = HAL_TXPOWER_MAX;
            }

            ds_ctl0 &= ~AR_XmitPower0;
            if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
                u_int count;
                for (count=0; count < nseries; count++) {
                    series[count].tx_power_cap -= AR5416_PWR_TABLE_OFFSET_DB * 2;
                }
            }
            ds_ctl0 |= set11nTxPower(0, AH_MIN(txpower, series[0].tx_power_cap));
        }

        ads->ds_ctl0 = ds_ctl0;

        ads->ds_ctl2 = set11nTries(series, 0)
                                 |  set11nTries(series, 1)
                                 |  set11nTries(series, 2)
                                 |  set11nTries(series, 3)
                                 |  (dur_update_en ? AR_DurUpdateEna : 0)
                                 |  SM(0, AR_BurstDur);

        ads->ds_ctl3 = set11nRate(series, 0)
                                 |  set11nRate(series, 1)
                                 |  set11nRate(series, 2)
                                 |  set11nRate(series, 3);

        ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
                                 |  set11nPktDurRTSCTS(series, 1);

        ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
                                 |  set11nPktDurRTSCTS(series, 3);

        ads->ds_ctl7 = set11nRateFlags(series, 0)
                                 |  set11nRateFlags(series, 1)
                                 |  set11nRateFlags(series, 2)
                                 |  set11nRateFlags(series, 3)
                                 | SM(rts_cts_rate, AR_RTSCTSRate);

        if (ap->ah_config.ath_hal_desc_tpc && AR_SREV_OWL_20_OR_LATER(ah)) {
            int16_t txpower;
            txpower = ar5416GetRateTxPower(
                ah, mode, series[1].rate_index, series[1].ch_sel);
            ads->ds_ctl9 =
                set11nTxPower(1, AH_MIN(txpower, series[1].tx_power_cap));
            txpower = ar5416GetRateTxPower(
                ah, mode, series[2].rate_index, series[2].ch_sel);
            ads->ds_ctl10 =
                set11nTxPower(2, AH_MIN(txpower, series[2].tx_power_cap));
            txpower = ar5416GetRateTxPower(
                ah, mode, series[3].rate_index, series[3].ch_sel);
            ads->ds_ctl11 =
                set11nTxPower(3, AH_MIN(txpower, series[3].tx_power_cap));
        }

#ifdef AH_NEED_DESC_SWAP
        last_ads->ds_ctl2 = __bswap32(ads->ds_ctl2);
        last_ads->ds_ctl3 = __bswap32(ads->ds_ctl3);
#else
        last_ads->ds_ctl2 = ads->ds_ctl2;
        last_ads->ds_ctl3 = ads->ds_ctl3;
#endif
}
示例#12
0
/*
 * Initialize Calibration infrastructure.
 */
HAL_BOOL
ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
	HAL_CHANNEL_INTERNAL *ichan;

	ichan = ath_hal_checkchannel(ah, chan);
	HALASSERT(ichan != AH_NULL);

	if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		/* Enable Rx Filter Cal */
		OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_FLTR_CAL);

		/* Clear the carrier leak cal bit */
		OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);

		/* kick off the cal */
		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);

		/* Poll for offset calibration complete */
		if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
			HALDEBUG(ah, HAL_DEBUG_ANY,
			    "%s: offset calibration failed to complete in 1ms; "
			    "noisy environment?\n", __func__);
			return AH_FALSE;
		}

		/* Set the cl cal bit and rerun the cal a 2nd time */
		/* Enable Rx Filter Cal */
		OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
		    AR_PHY_AGC_CONTROL_FLTR_CAL);

		OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
	} 	

	/* Calibrate the AGC */
	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);

	/* Poll for offset calibration complete */
	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: offset calibration did not complete in 1ms; "
		    "noisy environment?\n", __func__);
		return AH_FALSE;
	}

	/* 
	 * Do NF calibration after DC offset and other CALs.
	 * Per system engineers, noise floor value can sometimes be 20 dB
	 * higher than normal value if DC offset and noise floor cal are
	 * triggered at the same time.
	 */
	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);

	/* Initialize list pointers */
	cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;

	/*
	 * Enable IQ, ADC Gain, ADC DC Offset Cals
	 */
	if (AR_SREV_SOWL_10_OR_LATER(ah)) {
		/* Setup all non-periodic, init time only calibrations */
		/* XXX: Init DC Offset not working yet */
#if 0
		if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) {
			INIT_CAL(&cal->adcDcCalInitData);
			INSERT_CAL(cal, &cal->adcDcCalInitData);
		}
		/* Initialize current pointer to first element in list */
		cal->cal_curr = cal->cal_list;

		if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0))
			return AH_FALSE;
#endif
	}

	/* If Cals are supported, add them to list via INIT/INSERT_CAL */
	if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) {
		INIT_CAL(&cal->adcGainCalData);
		INSERT_CAL(cal, &cal->adcGainCalData);
		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%s: enable ADC Gain Calibration.\n", __func__);
	}
	if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) {
		INIT_CAL(&cal->adcDcCalData);
		INSERT_CAL(cal, &cal->adcDcCalData);
		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%s: enable ADC DC Calibration.\n", __func__);
	}
	if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) {
		INIT_CAL(&cal->iqCalData);
		INSERT_CAL(cal, &cal->iqCalData);
		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%s: enable IQ Calibration.\n", __func__);
	}
	/* Initialize current pointer to first element in list */
	cal->cal_curr = cal->cal_list;

	/* Kick off measurements for the first cal */
	if (cal->cal_curr != AH_NULL)
		ar5416ResetMeasurement(ah, cal->cal_curr);

	/* Mark all calibrations on this channel as being invalid */
	ichan->calValid = 0;

	return AH_TRUE;
}