Exemple #1
0
static void
ar2133WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
	int writes)
{
	(void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain,
		freqIndex, writes);
}
Exemple #2
0
/*
 * Fix on 2.4 GHz band for orientation sensitivity issue by increasing
 * rf_pwd_icsyndiv.
 * 
 * Theoretical Rules:
 *   if 2 GHz band
 *      if forceBiasAuto
 *         if synth_freq < 2412
 *            bias = 0
 *         else if 2412 <= synth_freq <= 2422
 *            bias = 1
 *         else // synth_freq > 2422
 *            bias = 2
 *      else if forceBias > 0
 *         bias = forceBias & 7
 *      else
 *         no change, use value from ini file
 *   else
 *      no change, invalid band
 *
 *  1st Mod:
 *    2422 also uses value of 2
 *    <approved>
 *
 *  2nd Mod:
 *    Less than 2412 uses value of 0, 2412 and above uses value of 2
 */
static void
ar2133ForceBias(struct ath_hal *ah, uint16_t synth_freq)
{
        uint32_t tmp_reg;
        int reg_writes = 0;
        uint32_t new_bias = 0;
	struct ar2133State *priv = AR2133(ah);

	/* XXX this is a bit of a silly check for 2.4ghz channels -adrian */
        if (synth_freq >= 3000)
                return;

        if (synth_freq < 2412)
                new_bias = 0;
        else if (synth_freq < 2422)
                new_bias = 1;
        else
                new_bias = 2;

        /* pre-reverse this field */
        tmp_reg = ath_hal_reverseBits(new_bias, 3);

        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Force rf_pwd_icsyndiv to %1d on %4d\n",
                  __func__, new_bias, synth_freq);

        /* swizzle rf_pwd_icsyndiv */
        ar5416ModifyRfBuffer(priv->Bank6Data, tmp_reg, 3, 181, 3);

        /* write Bank 6 with new params */
        ath_hal_ini_bank_write(ah, &AH5416(ah)->ah_ini_bank6, priv->Bank6Data, reg_writes);
}
/*
 * Collect data from HW to later perform ADC Gain Calibration
 */
void
ar5416AdcGainCalCollect(struct ath_hal *ah)
{
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
	int i;

	/*
	* Accumulate ADC Gain cal measures for active chains
	*/
	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
		cal->totalAdcIOddPhase(i) +=
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
		cal->totalAdcIEvenPhase(i) +=
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
		cal->totalAdcQOddPhase(i) +=
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
		cal->totalAdcQEvenPhase(i) +=
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));

		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
		    cal->calSamples, i, cal->totalAdcIOddPhase(i),
		    cal->totalAdcIEvenPhase(i), cal->totalAdcQOddPhase(i),
		    cal->totalAdcQEvenPhase(i));
	}
}
Exemple #4
0
void
ar5416BTCoexSetQcuThresh(struct ath_hal *ah, int qnum)
{
	struct ath_hal_5416 *ahp = AH5416(ah);

	ahp->ah_btCoexMode |= SM(qnum, AR_BT_QCU_THRESH);
}
Exemple #5
0
void
ar5416BTCoexConfig(struct ath_hal *ah, HAL_BT_COEX_CONFIG *btconf)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	HAL_BOOL rxClearPolarity = btconf->bt_rxclear_polarity;

	/*
	 * For Kiwi and Osprey, the polarity of rx_clear is active high.
	 * The bt_rxclear_polarity flag from ath(4) needs to be inverted.
	 */
	if (AR_SREV_KIWI(ah)) {
		rxClearPolarity = !btconf->bt_rxclear_polarity;
	}

	ahp->ah_btCoexMode = (ahp->ah_btCoexMode & AR_BT_QCU_THRESH) |
	    SM(btconf->bt_time_extend, AR_BT_TIME_EXTEND) |
	    SM(btconf->bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
	    SM(btconf->bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
	    SM(btconf->bt_mode, AR_BT_MODE) |
	    SM(btconf->bt_quiet_collision, AR_BT_QUIET) |
	    SM(rxClearPolarity, AR_BT_RX_CLEAR_POLARITY) |
	    SM(btconf->bt_priority_time, AR_BT_PRIORITY_TIME) |
	    SM(btconf->bt_first_slot_time, AR_BT_FIRST_SLOT_TIME);

	ahp->ah_btCoexMode2 |= SM(btconf->bt_hold_rxclear,
	    AR_BT_HOLD_RX_CLEAR);

	if (ahp->ah_btCoexSingleAnt == AH_FALSE) {
		/* Enable ACK to go out even though BT has higher priority. */
		ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT;
	}
}
Exemple #6
0
/*
 * ADC GAIN/DC offset calibration is for calibrating two ADCs that
 * are acting as one by interleaving incoming symbols. This isn't
 * relevant for 2.4GHz 20MHz wide modes because, as far as I can tell,
 * the secondary ADC is never enabled. It is enabled however for
 * 5GHz modes.
 *
 * It hasn't been confirmed whether doing this calibration is needed
 * at all in the above modes and/or whether it's actually harmful.
 * So for now, let's leave it enabled and just remember to get
 * confirmation that it needs to be clarified.
 *
 * See US Patent No: US 7,541,952 B1:
 *  " Method and Apparatus for Offset and Gain Compensation for
 *    Analog-to-Digital Converters."
 */
static OS_INLINE HAL_BOOL
ar5416IsCalSupp(struct ath_hal *ah, const struct ieee80211_channel *chan,
	HAL_CAL_TYPE calType) 
{
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;

	switch (calType & cal->suppCals) {
	case IQ_MISMATCH_CAL:
		/* Run IQ Mismatch for non-CCK only */
		return !IEEE80211_IS_CHAN_B(chan);
	case ADC_GAIN_CAL:
	case ADC_DC_CAL:
		/*
		 * Run ADC Gain Cal for either 5ghz any or 2ghz HT40.
		 *
		 * Don't run ADC calibrations for 5ghz fast clock mode
		 * in HT20 - only one ADC is used.
		 */
		if (IEEE80211_IS_CHAN_HT20(chan) &&
		    (IS_5GHZ_FAST_CLOCK_EN(ah, chan)))
			return AH_FALSE;
		if (IEEE80211_IS_CHAN_5GHZ(chan))
			return AH_TRUE;
		if (IEEE80211_IS_CHAN_HT40(chan))
			return AH_TRUE;
		return AH_FALSE;
	}
	return AH_FALSE;
}
void
ar5416AdcDcCalCollect(struct ath_hal *ah)
{
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
	int i;

	for (i = 0; i < AR5416_MAX_CHAINS; i++) {
		cal->totalAdcDcOffsetIOddPhase(i) += (int32_t)
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
		cal->totalAdcDcOffsetIEvenPhase(i) += (int32_t)
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
		cal->totalAdcDcOffsetQOddPhase(i) += (int32_t)
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
		cal->totalAdcDcOffsetQEvenPhase(i) += (int32_t)
		    OS_REG_READ(ah, AR_PHY_CAL_MEAS_3(i));

		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n",
		   cal->calSamples, i,
		   cal->totalAdcDcOffsetIOddPhase(i),
		   cal->totalAdcDcOffsetIEvenPhase(i),
		   cal->totalAdcDcOffsetQOddPhase(i),
		   cal->totalAdcDcOffsetQEvenPhase(i));
	}
}
Exemple #8
0
static void
ar5416AniCckErrTrigger(struct ath_hal *ah, HAL_BOOL inISR)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	HAL_CHANNEL_INTERNAL *chan = AH_PRIVATE(ah)->ah_curchan;
	struct ar5416AniState *aniState;
	WIRELESS_MODE mode;
	int32_t rssi;

	HALASSERT(chan != AH_NULL);

	if (!DO_ANI(ah)) {
		return;
	}

	/* first, raise noise immunity level, up to max */
	aniState = ahp->ah_curani;

    //PG: For WIRELESS_MODE debug of HT chips
    mode = ath_hal_chan2htwmode(ah, (HAL_CHANNEL *) chan);
    HDPRINTF(ah, HAL_DBG_ANI, "%s: Wireless Mode #=%d, Channel=%hu, cflags=0x%x, CLOCK_RATE=%u\n",
			__func__, mode, chan->channel, chan->channelFlags, CLOCK_RATE(ah));

	if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
		if (ar5416AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
				 aniState->noiseImmunityLevel + 1, inISR) == AH_TRUE)
			{return;}
	}
	/* In the case of AP mode operation, we cannot bucketize beacons
	 * according to RSSI.  Instead, raise Firstep level, up to max, and
	 * simply return
	 */ 
	if (AH_PRIVATE(ah)->ah_opmode == HAL_M_HOSTAP) {
		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
			ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
					 aniState->firstepLevel + 1, inISR);
		}
		return;
	}
	rssi = BEACON_RSSI(ahp);
	if (rssi >  aniState->rssiThrLow) {
		/*
		 * Beacon signal in mid and high range, raise firsteplevel.
		 */
		if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
			ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL,
					 aniState->firstepLevel + 1, inISR);
	} else {
		/*
		 * Beacon rssi is low, zero firstepLevel to maximize
		 * CCK sensitivity.
		 */
		mode = ath_hal_chan2wmode(ah, (HAL_CHANNEL *) chan);
		if (mode == WIRELESS_MODE_11g || mode == WIRELESS_MODE_11b) {
			if (aniState->firstepLevel > 0)
				ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0, inISR);
		}
	}
}
void
ath9k_hw_write_regs(struct ath_hal *ah, u32 modesIndex, u32 freqIndex,
		    int regWrites)
{
	struct ath_hal_5416 *ahp = AH5416(ah);

	REG_WRITE_ARRAY(&ahp->ah_iniBB_RfGain, freqIndex, regWrites);
}
Exemple #10
0
HAL_BOOL
ar5416FlashWrite(struct ath_hal *ah, u_int off, u_int16_t data)
{
    struct ath_hal_5416 *ahp = AH5416(ah);

    ((u_int16_t *)ahp->ah_cal_mem)[off] = data;
    return AH_TRUE;
}
Exemple #11
0
HAL_BOOL
ar5416FlashRead(struct ath_hal *ah, u_int off, u_int16_t *data)
{
    struct ath_hal_5416 *ahp = AH5416(ah);

    *data = ((u_int16_t *)ahp->ah_cal_mem)[off];
    return AH_TRUE;
}
Exemple #12
0
static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
	const struct hal_percal_data *calData =
		ahp->ah_cal_list_curr->calData;
	u32 numSamples =
		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;

	for (i = 0; i < numChains; i++) {
		iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
		iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
		qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
		qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];

		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Starting ADC DC Offset Cal for Chain %d\n", i);

		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_odd_i = %d\n", i,
			iOddMeasOffset);
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_even_i = %d\n", i,
			iEvenMeasOffset);
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_odd_q = %d\n", i,
			qOddMeasOffset);
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_even_q = %d\n", i,
			qEvenMeasOffset);

		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
			       numSamples) & 0x1ff;
		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
			       numSamples) & 0x1ff;

		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
			iDcMismatch);
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
			qDcMismatch);

		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
		val &= 0xc0000fff;
		val |= (qDcMismatch << 12) | (iDcMismatch << 21);
		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);

		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"ADC DC Offset Cal done for Chain %d\n", i);
	}

	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
}
Exemple #13
0
static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
	u32 qGainMismatch, iGainMismatch, val, i;

	for (i = 0; i < numChains; i++) {
		iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
		iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
		qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
		qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];

		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Starting ADC Gain Cal for Chain %d\n", i);

		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_odd_i = 0x%08x\n", i,
			iOddMeasOffset);
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_even_i = 0x%08x\n", i,
			iEvenMeasOffset);
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_odd_q = 0x%08x\n", i,
			qOddMeasOffset);
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"Chn %d pwr_meas_even_q = 0x%08x\n", i,
			qEvenMeasOffset);

		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
			iGainMismatch =
				((iEvenMeasOffset * 32) /
				 iOddMeasOffset) & 0x3f;
			qGainMismatch =
				((qOddMeasOffset * 32) /
				 qEvenMeasOffset) & 0x3f;

			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
				"Chn %d gain_mismatch_i = 0x%08x\n", i,
				iGainMismatch);
			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
				"Chn %d gain_mismatch_q = 0x%08x\n", i,
				qGainMismatch);

			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
			val &= 0xfffff000;
			val |= (qGainMismatch) | (iGainMismatch << 6);
			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);

			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
				"ADC Gain Cal done for Chain %d\n", i);
		}
	}

	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
}
Exemple #14
0
static void 
ar2133GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[])
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	int16_t nf;

	switch (ahp->ah_rx_chainmask) {
        case 0x7:
		nf = MS(OS_REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
		HALDEBUG(ah, HAL_DEBUG_NFCAL,
		    "NF calibrated [ctl] [chain 2] is %d\n", nf);
		nfarray[4] = nf;

		nf = MS(OS_REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
		HALDEBUG(ah, HAL_DEBUG_NFCAL,
		    "NF calibrated [ext] [chain 2] is %d\n", nf);
		nfarray[5] = nf;
		/* fall thru... */
        case 0x3:
        case 0x5:
		nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
		HALDEBUG(ah, HAL_DEBUG_NFCAL,
		    "NF calibrated [ctl] [chain 1] is %d\n", nf);
		nfarray[2] = nf;


		nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
		HALDEBUG(ah, HAL_DEBUG_NFCAL,
		    "NF calibrated [ext] [chain 1] is %d\n", nf);
		nfarray[3] = nf;
		/* fall thru... */
        case 0x1:
		nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
		HALDEBUG(ah, HAL_DEBUG_NFCAL,
		    "NF calibrated [ctl] [chain 0] is %d\n", nf);
		nfarray[0] = nf;

		nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
		if (nf & 0x100)
			nf = 0 - ((nf ^ 0x1ff) + 1);
		HALDEBUG(ah, HAL_DEBUG_NFCAL,
		    "NF calibrated [ext] [chain 0] is %d\n", nf);
		nfarray[1] = nf;

		break;
	}
}
Exemple #15
0
/*
 * Clear the specified key cache entry and any associated MIC entry.
 */
HAL_BOOL
ar5416ResetKeyCacheEntry(struct ath_hal *ah, u_int16_t entry)
{
	u_int32_t keyType;
	struct ath_hal_5416 *ahp = AH5416(ah);

	if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
		HDPRINTF(ah, HAL_DBG_KEYCACHE, "%s: entry %u out of range\n", __func__, entry);
		return AH_FALSE;
	}
	keyType = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry));

	ENABLE_REG_WRITE_BUFFER

	/* XXX why not clear key type/valid bit first? */
	OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
	OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
	OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
	OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
	OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
	OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
	OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
	OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
	if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
		u_int16_t micentry = entry+64;	/* MIC goes at slot+64 */

		HALASSERT(micentry < AH_PRIVATE(ah)->ah_caps.halKeyCacheSize);
		OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
		OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
		OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
		OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
		/* NB: key type and MAC are known to be ok */
	}

    OS_REG_WRITE_FLUSH(ah);

	DISABLE_REG_WRITE_BUFFER

	if (AH_PRIVATE(ah)->ah_curchan == AH_NULL)
            return AH_TRUE;

	if (ar5416GetCapability(ah, HAL_CAP_BB_RIFS_HANG, 0, AH_NULL)
		== HAL_OK) {
		if (keyType == AR_KEYTABLE_TYPE_TKIP    ||
		    keyType == AR_KEYTABLE_TYPE_40      ||
		    keyType == AR_KEYTABLE_TYPE_104     ||
		    keyType == AR_KEYTABLE_TYPE_128) {
		    /* SW WAR for Bug 31602 */
			if (--ahp->ah_rifs_sec_cnt == 0) {
				HDPRINTF(ah, HAL_DBG_KEYCACHE, "%s: Count = %d, enabling RIFS\n", __func__, ahp->ah_rifs_sec_cnt);
				ar5416SetRifsDelay(ah, AH_TRUE);
			}
		}
	}
	return AH_TRUE;
}
Exemple #16
0
bool ath9k_hw_init_cal(struct ath_hal *ah,
		       struct ath9k_channel *chan)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);

	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
		  AR_PHY_AGC_CONTROL_CAL);

	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
			"offset calibration failed to complete in 1ms; "
			"noisy environment?\n");
		return false;
	}

	if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
		ath9k_hw_9285_pa_cal(ah);

	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
		  REG_READ(ah, AR_PHY_AGC_CONTROL) |
		  AR_PHY_AGC_CONTROL_NF);

	ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;

	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
		if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
			INIT_CAL(&ahp->ah_adcGainCalData);
			INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
				"enabling ADC Gain Calibration.\n");
		}
		if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
			INIT_CAL(&ahp->ah_adcDcCalData);
			INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
				"enabling ADC DC Calibration.\n");
		}
		if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
			INIT_CAL(&ahp->ah_iqCalData);
			INSERT_CAL(ahp, &ahp->ah_iqCalData);
			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
				"enabling IQ Calibration.\n");
		}

		ahp->ah_cal_list_curr = ahp->ah_cal_list;

		if (ahp->ah_cal_list_curr)
			ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
	}

	ichan->CalValid = 0;

	return true;
}
Exemple #17
0
/*
 * Configure GPIO Pins to AR7010 (Magpie)
 */
void ar7010RegisterGpio(struct ath_hal *ah)
{
    struct ath_hal_5416 *ahp = AH5416(ah);

    ahp->ah_priv.priv.h.ah_gpio_cfg_input  = ar7010GpioCfgInput;
    ahp->ah_priv.priv.h.ah_gpio_cfg_output = ar7010GpioCfgOutput;
    ahp->ah_priv.priv.h.ah_gpio_get        = ar7010GpioGet;
    ahp->ah_priv.priv.h.ah_gpio_set        = ar7010GpioSet;
    ahp->ah_priv.priv.h.ah_gpio_set_intr   = ar7010GpioSetIntr;
}
Exemple #18
0
/*
 * Run temperature compensation calibration.
 *
 * The TX gain table is adjusted depending upon the difference
 * between the initial PDADC value and the currently read
 * average TX power sample value. This value is only valid if
 * frames have been transmitted, so currPDADC will be 0 if
 * no frames have yet been transmitted.
 */
void
ar9280olcTemperatureCompensation(struct ath_hal *ah)
{
	uint32_t rddata, i;
	int delta, currPDADC, regval;
	uint8_t hpwr_5g = 0;

	if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL))
		return;

	rddata = OS_REG_READ(ah, AR_PHY_TX_PWRCTRL4);
	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);

	HALDEBUG(ah, HAL_DEBUG_PERCAL,
	    "%s: called: initPDADC=%d, currPDADC=%d\n",
	    __func__, AH5416(ah)->initPDADC, currPDADC);

	if (AH5416(ah)->initPDADC == 0 || currPDADC == 0)
		return;

	(void) (ath_hal_eepromGet(ah, AR_EEP_DAC_HPWR_5G, &hpwr_5g));

	if (hpwr_5g)
		delta = (currPDADC - AH5416(ah)->initPDADC + 4) / 8;
	else
		delta = (currPDADC - AH5416(ah)->initPDADC + 5) / 10;

	HALDEBUG(ah, HAL_DEBUG_PERCAL, "%s: delta=%d, PDADCdelta=%d\n",
	    __func__, delta, AH9280(ah)->PDADCdelta);

	if (delta != AH9280(ah)->PDADCdelta) {
		AH9280(ah)->PDADCdelta = delta;
		for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
			regval = AH9280(ah)->originalGain[i] - delta;
			if (regval < 0)
				regval = 0;

			OS_REG_RMW_FIELD(ah,
				      AR_PHY_TX_GAIN_TBL1 + i * 4,
				      AR_PHY_TX_GAIN, regval);
		}
	}
}
/*
 * Recalibrate the lower PHY chips to account for temperature/environment
 * changes.
 */
HAL_BOOL
ar5416PerCalibration(struct ath_hal *ah, struct ieee80211_channel *chan,
	HAL_BOOL *isIQdone)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
	HAL_CAL_LIST *curCal = cal->cal_curr;

	if (curCal != AH_NULL && curCal->calData->calType == IQ_MISMATCH_CAL) {
		return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask,
		    AH_TRUE, isIQdone);
	} else {
		HAL_BOOL isCalDone;

		*isIQdone = AH_FALSE;
		return ar5416PerCalibrationN(ah, chan, ahp->ah_rx_chainmask,
		    AH_TRUE, &isCalDone);
	}
}
Exemple #20
0
static void
ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
{
	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
		OS_DELAY(1000);
		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
		OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
	}
}
Exemple #21
0
static inline HAL_BOOL
ar5416FillEeprom(struct ath_hal *ah)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	if (ahp->ah_eep_map == EEP_MAP_AR9287)
		return ar9287FillEeprom(ah);
    else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
		return ar5416FillEeprom4k(ah);
	else
		return ar5416FillEepromDef(ah);
}
Exemple #22
0
/*
 * Read EEPROM header info and program the device for correct operation
 * given the channel value.
 */
HAL_BOOL
ar5416EepromSetBoardValues(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	if (ahp->ah_eep_map == EEP_MAP_AR9287)
		return ar9287EepromSetBoardValues(ah, chan);
	else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
		return ar5416Eeprom4kSetBoardValues(ah, chan);
	else
		return ar5416EepromDefSetBoardValues(ah, chan);
}
Exemple #23
0
u_int32_t
ar5416INIFixup(struct ath_hal *ah,ar5416_eeprom_t *pEepData, u_int32_t reg, u_int32_t value)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	if (ahp->ah_eep_map == EEP_MAP_AR9287)
		return ar9287EepromINIFixup(ah, &pEepData->map.mapAr9287, reg, value);
	else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
		return ar5416Eeprom4kINIFixup(ah, &pEepData->map.map4k, reg, value);
	else
		return ar5416EepromDefINIFixup(ah, &pEepData->map.def, reg, value);
}
Exemple #24
0
/*
 * Clear the specified key cache entry and any associated MIC entry.
 */
HAL_BOOL
ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
{
	struct ath_hal_5416 *ahp = AH5416(ah);

	if (ar5212ResetKeyCacheEntry(ah, entry)) {
		ahp->ah_keytype[entry] = keyType[HAL_CIPHER_CLR];
		return AH_TRUE;
	} else
		return AH_FALSE;
}
Exemple #25
0
/**************************************************************
 * ar5416EepromSetAddac
 *
 * Set the ADDAC from eeprom for Sowl.
 */
void
ar5416EepromSetAddac(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	if (ahp->ah_eep_map == EEP_MAP_AR9287)
		ar9287EepromSetAddac(ah, chan);
	else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
		ar5416Eeprom4kSetAddac(ah, chan);
	else
		ar5416EepromDefSetAddac(ah, chan);
}
Exemple #26
0
/**************************************************************
 * ar5416EepromSetParam
 */
HAL_BOOL
ar5416EepromSetParam(struct ath_hal *ah, EEPROM_PARAM param, u_int32_t value)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	if (ahp->ah_eep_map == EEP_MAP_AR9287)
		return ar9287EepromSetParam(ah, param, value);
	else if (ahp->ah_eep_map == EEP_MAP_4KBITS)
		return ar5416Eeprom4kSetParam(ah, param, value);
	else
		return ar5416EepromDefSetParam(ah, param, value);
}
/*
 * Run non-periodic calibrations.
 */
static HAL_BOOL
ar5416RunInitCals(struct ath_hal *ah, int init_cal_count)
{
	struct ath_hal_5416 *ahp = AH5416(ah);
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
	HAL_CHANNEL_INTERNAL ichan;	/* XXX bogus */
	HAL_CAL_LIST *curCal = ahp->ah_cal_curr;
	HAL_BOOL isCalDone;
	int i;

	if (curCal == AH_NULL)
		return AH_FALSE;

	ichan.calValid = 0;
	for (i = 0; i < init_cal_count; i++) {
		/* Reset this Cal */
		ar5416ResetMeasurement(ah, curCal);
		/* Poll for offset calibration complete */
		if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {
			HALDEBUG(ah, HAL_DEBUG_ANY,
			    "%s: Cal %d failed to finish in 100ms.\n",
			    __func__, curCal->calData->calType);
			/* Re-initialize list pointers for periodic cals */
			cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
			return AH_FALSE;
		}
		/* Run this cal */
		ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask,
		    curCal, &isCalDone);
		if (!isCalDone)
			HALDEBUG(ah, HAL_DEBUG_ANY,
			    "%s: init cal %d did not complete.\n",
			    __func__, curCal->calData->calType);
		if (curCal->calNext != AH_NULL)
			curCal = curCal->calNext;
	}

	/* Re-initialize list pointers for periodic cals */
	cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;
	return AH_TRUE;
}
Exemple #28
0
/*
 * Cleanup any ANI state setup.
 */
void
ar5416AniDetach(struct ath_hal *ah)
{
	struct ath_hal_5416 *ahp = AH5416(ah);

	HDPRINTF(ah, HAL_DBG_ANI, "Detaching Ani\n");
	if (ahp->ah_hasHwPhyCounters) {
		ar5416DisableMIBCounters(ah);
		OS_REG_WRITE(ah, AR_PHY_ERR_1, 0);
		OS_REG_WRITE(ah, AR_PHY_ERR_2, 0);
	}
}
/*
 * Read the NF and check it against the noise floor threshold
 *
 * Return 0 if the NF calibration hadn't finished, 0 if it was
 * invalid, or > 0 for a valid NF reading.
 */
static int16_t
ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan)
{
	int16_t nf, nfThresh;
	int i;
	int retval = 0;

	if (ar5212IsNFCalInProgress(ah)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: NF didn't complete in calibration window\n", __func__);
		nf = 0;
		retval = -1;	/* NF didn't finish */
	} else {
		/* Finished NF cal, check against threshold */
		int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 };
		HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
			
		/* TODO - enhance for multiple chains and ext ch */
		ath_hal_getNoiseFloor(ah, nfarray);
		nf = nfarray[0];
		ar5416SanitizeNF(ah, nfarray);
		if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) {
			if (nf > nfThresh) {
				HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
				    "%s: noise floor failed detected; "
				    "detected %d, threshold %d\n", __func__,
				    nf, nfThresh);
				/*
				 * NB: Don't discriminate 2.4 vs 5Ghz, if this
				 *     happens it indicates a problem regardless
				 *     of the band.
				 */
				chan->ic_state |= IEEE80211_CHANSTATE_CWINT;
				nf = 0;
				retval = 0;
			}
		} else {
			nf = 0;
			retval = 0;
		}
		/* Update MIMO channel statistics, regardless of validity or not (for now) */
		for (i = 0; i < 3; i++) {
			ichan->noiseFloorCtl[i] = nfarray[i];
			ichan->noiseFloorExt[i] = nfarray[i + 3];
		}
		ichan->privFlags |= CHANNEL_MIMO_NF_VALID;

		ar5416UpdateNFHistBuff(ah, AH5416(ah)->ah_cal.nfCalHist, nfarray);
		ichan->rawNoiseFloor = nf;
		retval = nf;
	}
	return retval;
}
/*
 * Recalibrate the lower PHY chips to account for temperature/environment
 * changes.
 */
static void
ar5416DoCalibration(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *ichan,
	uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone)
{
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;

	/* Cal is assumed not done until explicitly set below */
	*isCalDone = AH_FALSE;

	HALDEBUG(ah, HAL_DEBUG_PERCAL,
	    "%s: %s Calibration, state %d, calValid 0x%x\n",
	    __func__, currCal->calData->calName, currCal->calState,
	    ichan->calValid);

	/* Calibration in progress. */
	if (currCal->calState == CAL_RUNNING) {
		/* Check to see if it has finished. */
		if (!(OS_REG_READ(ah, AR_PHY_TIMING_CTRL4) & AR_PHY_TIMING_CTRL4_DO_CAL)) {
			HALDEBUG(ah, HAL_DEBUG_PERCAL,
			    "%s: sample %d of %d finished\n",
			    __func__, cal->calSamples,
			    currCal->calData->calNumSamples);
			/* 
			 * Collect measurements for active chains.
			 */
			currCal->calData->calCollect(ah);
			if (++cal->calSamples >= currCal->calData->calNumSamples) {
				int i, numChains = 0;
				for (i = 0; i < AR5416_MAX_CHAINS; i++) {
					if (rxchainmask & (1 << i))
						numChains++;
				}
				/* 
				 * Process accumulated data
				 */
				currCal->calData->calPostProc(ah, numChains);

				/* Calibration has finished. */
				ichan->calValid |= currCal->calData->calType;
				currCal->calState = CAL_DONE;
				*isCalDone = AH_TRUE;
			} else {
				/*
				 * Set-up to collect of another sub-sample.
				 */
				ar5416SetupMeasurement(ah, currCal);
			}
		}
	} else if (!(ichan->calValid & currCal->calData->calType)) {
		/* If current cal is marked invalid in channel, kick it off */
		ar5416ResetMeasurement(ah, currCal);
	}
}