summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2010-05-16 09:42:05 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2010-05-16 09:42:05 +0000
commitf2d9a7772c813118fd77f2de69c61189095a0753 (patch)
treebef07ee22d864eac3f7cff0a28cb6941893a476e /sys/dev/ic
parentc7ba6e406444881f5e4797f7f40d928a3816a24e (diff)
cleanup calibration bits (not everything is enabled yet.)
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/ar5008.c65
-rw-r--r--sys/dev/ic/ar9003.c38
-rw-r--r--sys/dev/ic/athn.c47
-rw-r--r--sys/dev/ic/athnvar.h5
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)