diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2010-05-16 09:42:05 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2010-05-16 09:42:05 +0000 |
commit | f2d9a7772c813118fd77f2de69c61189095a0753 (patch) | |
tree | bef07ee22d864eac3f7cff0a28cb6941893a476e /sys/dev/ic | |
parent | c7ba6e406444881f5e4797f7f40d928a3816a24e (diff) |
cleanup calibration bits (not everything is enabled yet.)
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/ar5008.c | 65 | ||||
-rw-r--r-- | sys/dev/ic/ar9003.c | 38 | ||||
-rw-r--r-- | sys/dev/ic/athn.c | 47 | ||||
-rw-r--r-- | sys/dev/ic/athnvar.h | 5 |
4 files changed, 97 insertions, 58 deletions
diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c index 00eebe4541b..5ee1871501c 100644 --- a/sys/dev/ic/ar5008.c +++ b/sys/dev/ic/ar5008.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar5008.c,v 1.5 2010/05/16 09:19:48 damien Exp $ */ +/* $OpenBSD: ar5008.c,v 1.6 2010/05/16 09:42:04 damien Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -1824,37 +1824,42 @@ ar5008_do_noisefloor_calib(struct athn_softc *sc) void ar5008_do_calib(struct athn_softc *sc) { - int log = AR_MAX_LOG_CAL; /* XXX */ - uint32_t mode = 0, reg; + uint32_t mode, reg; + int log; reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0); + log = AR_SREV_9280_10_OR_LATER(sc) ? 10 : 2; reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, log); AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg); - if (sc->calib_mask & ATHN_CAL_ADC_GAIN) + if (sc->cur_calib_mask & ATHN_CAL_ADC_GAIN) mode = AR_PHY_CALMODE_ADC_GAIN; - else if (sc->calib_mask & ATHN_CAL_ADC_DC) + else if (sc->cur_calib_mask & ATHN_CAL_ADC_DC) mode = AR_PHY_CALMODE_ADC_DC_PER; - else if (sc->calib_mask & ATHN_CAL_IQ) + else /* ATHN_CAL_IQ */ mode = AR_PHY_CALMODE_IQ; AR_WRITE(sc, AR_PHY_CALMODE, mode); + DPRINTF(("starting calibration mode=0x%x\n", mode)); AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0, AR_PHY_TIMING_CTRL4_DO_CAL); } void ar5008_next_calib(struct athn_softc *sc) { - if (AR_READ(sc, AR_PHY_TIMING_CTRL4_0) & AR_PHY_TIMING_CTRL4_DO_CAL) { - /* Calibration in progress, come back later. */ - return; + /* Check if we have any calibration in progress. */ + if (sc->cur_calib_mask != 0) { + if (!(AR_READ(sc, AR_PHY_TIMING_CTRL4_0) & + AR_PHY_TIMING_CTRL4_DO_CAL)) { + /* Calibration completed for current sample. */ + if (sc->cur_calib_mask & ATHN_CAL_ADC_GAIN) + ar5008_calib_adc_gain(sc); + else if (sc->cur_calib_mask & ATHN_CAL_ADC_DC) + ar5008_calib_adc_dc_off(sc); + else /* ATHN_CAL_IQ */ + ar5008_calib_iq(sc); + } } - if (sc->calib_mask & ATHN_CAL_ADC_GAIN) - ar5008_calib_iq(sc); - else if (sc->calib_mask & ATHN_CAL_ADC_DC) - ar5008_calib_adc_gain(sc); - else if (sc->calib_mask & ATHN_CAL_IQ) - ar5008_calib_adc_dc_off(sc); } void @@ -1874,7 +1879,8 @@ ar5008_calib_iq(struct athn_softc *sc) cal->iq_corr_meas += (int32_t)AR_READ(sc, AR_PHY_CAL_MEAS_2(i)); } - if (++sc->calib.nsamples < AR_CAL_SAMPLES) { + if (!AR_SREV_9280_10_OR_LATER(sc) && + ++sc->calib.nsamples < AR_CAL_SAMPLES) { /* Not enough samples accumulated, continue. */ ar5008_do_calib(sc); return; @@ -1914,8 +1920,13 @@ ar5008_calib_iq(struct athn_softc *sc) AR_WRITE(sc, AR_PHY_TIMING_CTRL4(i), reg); } + /* Apply new settings. */ AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0, AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); + + /* IQ calibration done. */ + sc->cur_calib_mask &= ~ATHN_CAL_IQ; + memset(&sc->calib, 0, sizeof(sc->calib)); } void @@ -1934,7 +1945,8 @@ ar5008_calib_adc_gain(struct athn_softc *sc) cal->pwr_meas_odd_q += AR_READ(sc, AR_PHY_CAL_MEAS_2(i)); cal->pwr_meas_even_q += AR_READ(sc, AR_PHY_CAL_MEAS_3(i)); } - if (++sc->calib.nsamples < AR_CAL_SAMPLES) { + if (!AR_SREV_9280_10_OR_LATER(sc) && + ++sc->calib.nsamples < AR_CAL_SAMPLES) { /* Not enough samples accumulated, continue. */ ar5008_do_calib(sc); return; @@ -1958,8 +1970,13 @@ ar5008_calib_adc_gain(struct athn_softc *sc) AR_WRITE(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), reg); } + /* Apply new settings. */ AR_SETBITS(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); + + /* ADC gain calibration done. */ + sc->cur_calib_mask &= ~ATHN_CAL_ADC_GAIN; + memset(&sc->calib, 0, sizeof(sc->calib)); } void @@ -1979,14 +1996,17 @@ ar5008_calib_adc_dc_off(struct athn_softc *sc) cal->pwr_meas_odd_q += AR_READ(sc, AR_PHY_CAL_MEAS_2(i)); cal->pwr_meas_even_q += AR_READ(sc, AR_PHY_CAL_MEAS_3(i)); } - if (++sc->calib.nsamples < AR_CAL_SAMPLES) { + if (!AR_SREV_9280_10_OR_LATER(sc) && + ++sc->calib.nsamples < AR_CAL_SAMPLES) { /* Not enough samples accumulated, continue. */ ar5008_do_calib(sc); return; } - count = (1 << (AR_MAX_LOG_CAL + 5)) * sc->calib.nsamples; - + if (AR_SREV_9280_10_OR_LATER(sc)) + count = (1 << (10 + 5)); + else + count = (1 << ( 2 + 5)) * AR_CAL_SAMPLES; for (i = 0; i < sc->nrxchains; i++) { cal = &sc->calib.adc_dc_offset[i]; @@ -2004,8 +2024,13 @@ ar5008_calib_adc_dc_off(struct athn_softc *sc) AR_WRITE(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), reg); } + /* Apply new settings. */ AR_SETBITS(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); + + /* ADC DC offset calibration done. */ + sc->cur_calib_mask &= ~ATHN_CAL_ADC_DC; + memset(&sc->calib, 0, sizeof(sc->calib)); } void diff --git a/sys/dev/ic/ar9003.c b/sys/dev/ic/ar9003.c index 1038ac987ad..cafd25ea925 100644 --- a/sys/dev/ic/ar9003.c +++ b/sys/dev/ic/ar9003.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ar9003.c,v 1.8 2010/05/16 09:19:48 damien Exp $ */ +/* $OpenBSD: ar9003.c,v 1.9 2010/05/16 09:42:04 damien Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -1878,7 +1878,7 @@ ar9003_init_calib(struct athn_softc *sc) return (ETIMEDOUT); #ifdef notyet - /* Perform Tx I/Q calibration. */ + /* Perform Tx IQ calibration. */ ar9003_calib_tx_iq(sc); #endif @@ -1895,14 +1895,14 @@ ar9003_do_calib(struct athn_softc *sc) { uint32_t reg; - if (sc->calib_mask & ATHN_CAL_IQ) { + if (sc->cur_calib_mask & ATHN_CAL_IQ) { reg = AR_READ(sc, AR_PHY_TIMING4); reg = RW(reg, AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX, AR_MAX_LOG_CAL); AR_WRITE(sc, AR_PHY_TIMING4, reg); AR_WRITE(sc, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); AR_SETBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); - } else if (sc->calib_mask & ATHN_CAL_TEMP) { + } else if (sc->cur_calib_mask & ATHN_CAL_TEMP) { AR_SETBITS(sc, AR_PHY_65NM_CH0_THERM, AR_PHY_65NM_CH0_THERM_LOCAL); AR_SETBITS(sc, AR_PHY_65NM_CH0_THERM, @@ -1913,12 +1913,13 @@ ar9003_do_calib(struct athn_softc *sc) void ar9003_next_calib(struct athn_softc *sc) { - if (AR_READ(sc, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL) { - /* Calibration in progress, come back later. */ - return; + /* Check if we have any calibration in progress. */ + if (sc->cur_calib_mask != 0) { + if (!(AR_READ(sc, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) { + /* Calibration completed for current sample. */ + ar9003_calib_iq(sc); + } } - if (sc->calib_mask & ATHN_CAL_IQ) - ar9003_calib_iq(sc); } void @@ -1982,8 +1983,13 @@ ar9003_calib_iq(struct athn_softc *sc) AR_WRITE(sc, AR_PHY_RX_IQCAL_CORR_B(i), reg); } + /* Apply new settings. */ AR_SETBITS(sc, AR_PHY_RX_IQCAL_CORR_B(0), AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); + + /* IQ calibration done. */ + sc->cur_calib_mask &= ~ATHN_CAL_IQ; + memset(&sc->calib, 0, sizeof(sc->calib)); } #define DELPT 32 @@ -2045,7 +2051,7 @@ ar9003_get_iq_corr(struct athn_softc *sc, int32_t res[6], int32_t coeff[2]) cos[i] = (cos[i] * SCALE) / div; } - /* Compute I/Q mismatch (solve 4x4 linear equation.) */ + /* Compute IQ mismatch (solve 4x4 linear equation.) */ f1 = cos[0] - cos[1]; f3 = sin[0] - sin[1]; f2 = (f1 * f1 + f3 * f3) / SCALE; @@ -2117,7 +2123,7 @@ ar9003_calib_tx_iq(struct athn_softc *sc) reg = RW(reg, AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); AR_WRITE(sc, AR_PHY_TX_IQCAL_CONTROL_1, reg); - /* Start Tx I/Q calibration. */ + /* Start Tx IQ calibration. */ AR_SETBITS(sc, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL); /* Wait for completion. */ for (ntries = 0; ntries < 10000; ntries++) { @@ -2130,12 +2136,12 @@ ar9003_calib_tx_iq(struct athn_softc *sc) return (ETIMEDOUT); for (i = 0; i < sc->ntxchains; i++) { - /* Read Tx I/Q calibration status for this chain. */ + /* Read Tx IQ calibration status for this chain. */ reg = AR_READ(sc, AR_PHY_TX_IQCAL_STATUS_B(i)); if (reg & AR_PHY_TX_IQCAL_STATUS_FAILED) return (EIO); /* - * Read Tx I/Q calibration results for this chain. + * Read Tx IQ calibration results for this chain. * This consists in twelve signed 12-bit values. */ for (j = 0; j < 3; j++) { @@ -2150,11 +2156,11 @@ ar9003_calib_tx_iq(struct athn_softc *sc) res[j * 2 + 1] = reg & 0xffff; } - /* Compute Tx I/Q correction. */ + /* Compute Tx IQ correction. */ if (ar9003_get_iq_corr(sc, res, coeff) != 0) return (EIO); - /* Write Tx I/Q correction coefficients. */ + /* Write Tx IQ correction coefficients. */ reg = AR_READ(sc, AR_PHY_TX_IQCAL_CORR_COEFF_01_B(i)); reg = RW(reg, AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, coeff[0]); @@ -2168,7 +2174,7 @@ ar9003_calib_tx_iq(struct athn_softc *sc) AR_WRITE(sc, AR_PHY_RX_IQCAL_CORR_B(i), reg); } - /* Enable Tx I/Q correction. */ + /* Enable Tx IQ correction. */ AR_SETBITS(sc, AR_PHY_TX_IQCAL_CONTROL_3, AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN); AR_SETBITS(sc, AR_PHY_RX_IQCAL_CORR_B(0), diff --git a/sys/dev/ic/athn.c b/sys/dev/ic/athn.c index 719e5558a78..2d9b449fde9 100644 --- a/sys/dev/ic/athn.c +++ b/sys/dev/ic/athn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: athn.c,v 1.42 2010/05/16 09:19:48 damien Exp $ */ +/* $OpenBSD: athn.c,v 1.43 2010/05/16 09:42:04 damien Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -1182,26 +1182,27 @@ athn_init_calib(struct athn_softc *sc, struct ieee80211_channel *c, if (error != 0) return (error); - /* Do PA calibration. */ - if (AR_SREV_9285_11_OR_LATER(sc)) - ar9285_pa_calib(sc); - - /* Do noisefloor calibration. */ - ops->noisefloor_calib(sc); - - if (!AR_SREV_9160_10_OR_LATER(sc)) - return (0); - - /* Enable IQ calibration. */ - sc->calib_mask = ATHN_CAL_IQ; - - if (!AR_SREV_9380_10_OR_LATER(sc) && - (IEEE80211_IS_CHAN_5GHZ(c) || extc != NULL)) { - /* Enable ADC gain and ADC DC offset calibrations. */ - sc->calib_mask |= ATHN_CAL_ADC_GAIN | ATHN_CAL_ADC_DC; + if (!AR_SREV_9380_10_OR_LATER(sc)) { + /* Do PA calibration. */ + if (AR_SREV_9285_11_OR_LATER(sc)) + ar9285_pa_calib(sc); + + /* Do noisefloor calibration. */ + ops->noisefloor_calib(sc); + } + if (AR_SREV_9160_10_OR_LATER(sc)) { + /* Support IQ calibration. */ + sc->sup_calib_mask = ATHN_CAL_IQ; + if (AR_SREV_9380_10_OR_LATER(sc)) { + /* Support temperature compensation calibration. */ + sc->sup_calib_mask |= ATHN_CAL_TEMP; + } else if (IEEE80211_IS_CHAN_5GHZ(c) || extc != NULL) { + /* Support ADC gain calibration. */ + sc->sup_calib_mask |= ATHN_CAL_ADC_GAIN; + /* Support ADC DC offset calibration. */ + sc->sup_calib_mask |= ATHN_CAL_ADC_DC; + } } - - ops->do_calib(sc); return (0); } @@ -2297,6 +2298,12 @@ athn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) sc->imask |= AR_IMR_BMISS; } athn_enable_interrupts(sc); + + if (sc->sup_calib_mask != 0) { + memset(&sc->calib, 0, sizeof(sc->calib)); + sc->cur_calib_mask = sc->sup_calib_mask; + /* ops->do_calib(sc); */ + } /* XXX Start ANI. */ timeout_add_msec(&sc->calib_to, 500); diff --git a/sys/dev/ic/athnvar.h b/sys/dev/ic/athnvar.h index db931042038..4c7b8b14750 100644 --- a/sys/dev/ic/athnvar.h +++ b/sys/dev/ic/athnvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: athnvar.h,v 1.12 2010/05/16 09:19:48 damien Exp $ */ +/* $OpenBSD: athnvar.h,v 1.13 2010/05/16 09:42:04 damien Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -444,7 +444,8 @@ struct athn_softc { uint8_t ntxchains; uint8_t nrxchains; - uint8_t calib_mask; + uint8_t sup_calib_mask; + uint8_t cur_calib_mask; #define ATHN_CAL_IQ (1 << 0) #define ATHN_CAL_ADC_GAIN (1 << 1) #define ATHN_CAL_ADC_DC (1 << 2) |