示例#1
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;
}
示例#2
0
static void
ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
	const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
{
#define	CHAN_HT20	htole32(IEEE80211_CHAN_HT20)
#define	CHAN_HT40U	htole32(IEEE80211_CHAN_HT40U)
#define	CHAN_HT40D	htole32(IEEE80211_CHAN_HT40D)
#define	CHAN_HT		(CHAN_HT20|CHAN_HT40U|CHAN_HT40D)
	struct ath_softc *sc = ifp->if_softc;
	const HAL_RATE_TABLE *rt;
	uint8_t rix;

	rt = sc->sc_currates;
	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
	rix = rt->rateCodeToIndex[rs->rs_rate];
	sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate;
	sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
#ifdef AH_SUPPORT_AR5416
	sc->sc_rx_th.wr_chan_flags &= ~CHAN_HT;
	if (rs->rs_status & HAL_RXERR_PHY) {
		/*
		 * PHY error - make sure the channel flags
		 * reflect the actual channel configuration,
		 * not the received frame.
		 */
		if (IEEE80211_IS_CHAN_HT40U(sc->sc_curchan))
			sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U;
		else if (IEEE80211_IS_CHAN_HT40D(sc->sc_curchan))
			sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D;
		else if (IEEE80211_IS_CHAN_HT20(sc->sc_curchan))
			sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
	} else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) {	/* HT rate */
		struct ieee80211com *ic = ifp->if_l2com;

		if ((rs->rs_flags & HAL_RX_2040) == 0)
			sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
		else if (IEEE80211_IS_CHAN_HT40U(ic->ic_curchan))
			sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U;
		else
			sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D;
		if ((rs->rs_flags & HAL_RX_GI) == 0)
			sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
	}

#endif
	sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(sc, rs->rs_tstamp, tsf));
	if (rs->rs_status & HAL_RXERR_CRC)
		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
	/* XXX propagate other error flags from descriptor */
	sc->sc_rx_th.wr_antnoise = nf;
	sc->sc_rx_th.wr_antsignal = nf + rs->rs_rssi;
	sc->sc_rx_th.wr_antenna = rs->rs_antenna;
#undef CHAN_HT
#undef CHAN_HT20
#undef CHAN_HT40U
#undef CHAN_HT40D
}
示例#3
0
/*
 * Determine if calibration is supported by device and channel flags
 */
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 non-CCK & non 2GHz-HT20 only */
		return !IEEE80211_IS_CHAN_B(chan) &&
		    !(IEEE80211_IS_CHAN_2GHZ(chan) && IEEE80211_IS_CHAN_HT20(chan));
	}
	return AH_FALSE;
}
示例#4
0
/* Carrier leakage Calibration fix */
static HAL_BOOL
ar9285_hw_cl_cal(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
	if (IEEE80211_IS_CHAN_HT20(chan)) {
		OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
		OS_REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
		OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
			    AR_PHY_AGC_CONTROL_FLTR_CAL);
		OS_REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
		if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL,
				  AR_PHY_AGC_CONTROL_CAL, 0)) {
			HALDEBUG(ah, HAL_DEBUG_PERCAL,
				"offset calibration failed to complete in 1ms; noisy environment?\n");
			return AH_FALSE;
		}
		OS_REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
		OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
		OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
	}
	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_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
			  0)) {
		HALDEBUG(ah, HAL_DEBUG_PERCAL,
			"offset calibration failed to complete in 1ms; noisy environment?\n");
		return AH_FALSE;
	}

	OS_REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
	OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
	OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);

	return AH_TRUE;
}
示例#5
0
/*
 * rt2860_rf_set_chan
 */
void rt2860_rf_set_chan(struct rt2860_softc *sc,
	struct ieee80211_channel *c)
{
	struct ifnet *ifp;
	struct ieee80211com *ic;
	const struct rt2860_rf_prog *prog;
	uint32_t r1, r2, r3, r4;
	int8_t txpow1, txpow2;
	int i, chan;

	if (sc->mac_rev == 0x28720200) {
		rt2872_rf_set_chan(sc, c);
		return;
	} 

	ifp = sc->ifp;
	ic = ifp->if_l2com;
	prog = rt2860_rf_2850;

	/* get central channel position */

	chan = ieee80211_chan2ieee(ic, c);

	if ((sc->mac_rev & 0xffff0000) >= 0x30710000) {
		rt3090_set_chan(sc, chan);
		return;
	}

	if (IEEE80211_IS_CHAN_HT40U(c))
		chan += 2;
	else if (IEEE80211_IS_CHAN_HT40D(c))
		chan -= 2;

	RT2860_DPRINTF(sc, RT2860_DEBUG_CHAN,
		"%s: RF set channel: channel=%u, HT%s%s\n",
		device_get_nameunit(sc->dev),
		ieee80211_chan2ieee(ic, c),
		!IEEE80211_IS_CHAN_HT(c) ? " disabled" :
			IEEE80211_IS_CHAN_HT20(c) ? "20":
				IEEE80211_IS_CHAN_HT40U(c) ? "40U" : "40D",
		(ic->ic_flags & IEEE80211_F_SCAN) ? ", scanning" : "");

	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
		return;

	for (i = 0; prog[i].chan != chan; i++);

	r1 = prog[i].r1;
	r2 = prog[i].r2;
	r3 = prog[i].r3;
	r4 = prog[i].r4;

	txpow1 = sc->txpow1[i];
	txpow2 = sc->txpow2[i];

	if (sc->ntxpath == 1)
		r2 |= (1 << 14);

	if (sc->nrxpath == 2)
		r2 |= (1 << 6);
	else if (sc->nrxpath == 1)
		r2 |= (1 << 17) | (1 << 6);

	if (IEEE80211_IS_CHAN_2GHZ(c))
	{
		r3 = (r3 & 0xffffc1ff) | (txpow1 << 9);
		r4 = (r4 & ~0x001f87c0) | (sc->rf_freq_off << 15) |
		    (txpow2 << 6);
	}
	else
	{
		r3 = r3 & 0xffffc1ff;
		r4 = (r4 & ~0x001f87c0) | (sc->rf_freq_off << 15);

		if (txpow1 >= RT2860_EEPROM_TXPOW_5GHZ_MIN && txpow1 < 0)
		{
			txpow1 = (-RT2860_EEPROM_TXPOW_5GHZ_MIN + txpow1);
			if (txpow1 > RT2860_EEPROM_TXPOW_5GHZ_MAX)
				txpow1 = RT2860_EEPROM_TXPOW_5GHZ_MAX;

			r3 |= (txpow1 << 10);
		}
		else
		{
			if (txpow1 > RT2860_EEPROM_TXPOW_5GHZ_MAX)
				txpow1 = RT2860_EEPROM_TXPOW_5GHZ_MAX;

			r3 |= (txpow1 << 10) | (1 << 9);
		}

		if (txpow2 >= RT2860_EEPROM_TXPOW_5GHZ_MIN && txpow2 < 0)
		{
			txpow2 = (-RT2860_EEPROM_TXPOW_5GHZ_MIN + txpow2);
			if (txpow2 > RT2860_EEPROM_TXPOW_5GHZ_MAX)
				txpow2 = RT2860_EEPROM_TXPOW_5GHZ_MAX;

			r4 |= (txpow2 << 7);
		}
		else
		{
			if (txpow2 > RT2860_EEPROM_TXPOW_5GHZ_MAX)
				txpow2 = RT2860_EEPROM_TXPOW_5GHZ_MAX;

			r4 |= (txpow2 << 7) | (1 << 6);
		}
	}

	if (!(ic->ic_flags & IEEE80211_F_SCAN) && IEEE80211_IS_CHAN_HT40(c))
		r4 |= (1 << 21);

	rt2860_io_rf_write(sc, RT2860_REG_RF_R1, r1);
	rt2860_io_rf_write(sc, RT2860_REG_RF_R2, r2);
	rt2860_io_rf_write(sc, RT2860_REG_RF_R3, r3 & ~(1 << 2));
	rt2860_io_rf_write(sc, RT2860_REG_RF_R4, r4);

	DELAY(200);

	rt2860_io_rf_write(sc, RT2860_REG_RF_R1, r1);
	rt2860_io_rf_write(sc, RT2860_REG_RF_R2, r2);
	rt2860_io_rf_write(sc, RT2860_REG_RF_R3, r3 | (1 << 2));
	rt2860_io_rf_write(sc, RT2860_REG_RF_R4, r4);

	DELAY(200);

	rt2860_io_rf_write(sc, RT2860_REG_RF_R1, r1);
	rt2860_io_rf_write(sc, RT2860_REG_RF_R2, r2);
	rt2860_io_rf_write(sc, RT2860_REG_RF_R3, r3 & ~(1 << 2));
	rt2860_io_rf_write(sc, RT2860_REG_RF_R4, r4);

	rt2860_rf_select_chan_group(sc, c);

	DELAY(1000);
}
示例#6
0
/*
 * rt2872_rf_set_chan
 */
static void 
rt2872_rf_set_chan(struct rt2860_softc *sc,
	struct ieee80211_channel *c)
{
	struct ifnet *ifp;
	struct ieee80211com *ic;
	const struct rt2860_rf_prog *prog;
	uint32_t r1, r2, r3, r4;
	uint32_t r6, r7, r12, r13, r23, r24;
	int8_t txpow1, txpow2;
	int i, chan;

	ifp = sc->ifp;
	ic = ifp->if_l2com;
	prog = rt2860_rf_2850;

	/* get central channel position */

	chan = ieee80211_chan2ieee(ic, c);

	if (IEEE80211_IS_CHAN_HT40U(c))
		chan += 2;
	else if (IEEE80211_IS_CHAN_HT40D(c))
		chan -= 2;

	RT2860_DPRINTF(sc, RT2860_DEBUG_CHAN,
		"%s: RF set channel: channel=%u, HT%s%s\n",
		device_get_nameunit(sc->dev),
		ieee80211_chan2ieee(ic, c),
		!IEEE80211_IS_CHAN_HT(c) ? " disabled" :
			IEEE80211_IS_CHAN_HT20(c) ? "20":
				IEEE80211_IS_CHAN_HT40U(c) ? "40U" : "40D",
		(ic->ic_flags & IEEE80211_F_SCAN) ? ", scanning" : "");

	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
		return;

	for (i = 0; prog[i].chan != chan; i++);

	r1 = prog[i].r1;
	r2 = prog[i].r2;
	r3 = prog[i].r3;
	r4 = prog[i].r4;

	txpow1 = sc->txpow1[i];
	txpow2 = sc->txpow2[i];

	for (i = 0; rt2860_rf_fi3020[i].channel != chan; i++);

	/* Programm channel parameters */
	r2 = rt2860_rf_fi3020[i].n;
	rt2860_io_rf_write(sc, 2 , r2 );
	r3 = rt2860_rf_fi3020[i].k;
	rt2860_io_rf_write(sc, 3 , r3 );

	r6 = (rt3052_rf_default[6] & 0xFC) | (rt2860_rf_fi3020[i].r & 0x03);
	rt2860_io_rf_write(sc, 6 , r6 );

	/* Set Tx Power */
	r12 = (rt3052_rf_default[12] & 0xE0) | (txpow1 & 0x1f);
	rt2860_io_rf_write(sc, 12, r12);

	/* Set Tx1 Power */
	r13 = (rt3052_rf_default[13] & 0xE0) | (txpow2 & 0x1f);
	rt2860_io_rf_write(sc, 13, r13);

	/* Set RF offset */
	r23 = (rt3052_rf_default[23] & 0x80) | (sc->rf_freq_off);
	rt2860_io_rf_write(sc, 23, r23);

	/* Set BW */
	r24 = (rt3052_rf_default[24] & 0xDF);
	if (!(ic->ic_flags & IEEE80211_F_SCAN) && IEEE80211_IS_CHAN_HT40(c))
	    r24 |= 0x20;
	rt2860_io_rf_write(sc, 24, r24);

	/* Enable RF tuning */
	r7 = (rt3052_rf_default[7]) | 1;
	rt2860_io_rf_write(sc, 7 , r7 );

	/* Antenna */
	r1 = (rt3052_rf_default[1] & 0xab) | ((sc->nrxpath == 1)?0x10:0) |
	    ((sc->ntxpath == 1)?0x20:0);
	rt2860_io_rf_write(sc, 1 , r1 );

	DELAY(200);

	rt2860_rf_select_chan_group(sc, c);

	DELAY(1000);
}