summaryrefslogtreecommitdiff
path: root/sys/dev/ic/ar5008.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/ar5008.c')
-rw-r--r--sys/dev/ic/ar5008.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c
index e0188134edd..4eb38555957 100644
--- a/sys/dev/ic/ar5008.c
+++ b/sys/dev/ic/ar5008.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5008.c,v 1.46 2017/11/28 04:35:39 stsp Exp $ */
+/* $OpenBSD: ar5008.c,v 1.47 2019/02/01 16:15:07 stsp Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -98,10 +98,11 @@ void ar5008_init_chains(struct athn_softc *);
void ar5008_set_rxchains(struct athn_softc *);
void ar5008_read_noisefloor(struct athn_softc *, int16_t *, int16_t *);
void ar5008_write_noisefloor(struct athn_softc *, int16_t *, int16_t *);
-void ar5008_get_noisefloor(struct athn_softc *, struct ieee80211_channel *);
+int ar5008_get_noisefloor(struct athn_softc *);
+void ar5008_apply_noisefloor(struct athn_softc *);
void ar5008_bb_load_noisefloor(struct athn_softc *);
-void ar5008_noisefloor_calib(struct athn_softc *);
void ar5008_do_noisefloor_calib(struct athn_softc *);
+void ar5008_init_noisefloor_calib(struct athn_softc *);
void ar5008_do_calib(struct athn_softc *);
void ar5008_next_calib(struct athn_softc *);
void ar5008_calib_iq(struct athn_softc *);
@@ -176,6 +177,9 @@ ar5008_attach(struct athn_softc *sc)
ops->disable_phy = ar5008_disable_phy;
ops->set_rxchains = ar5008_set_rxchains;
ops->noisefloor_calib = ar5008_do_noisefloor_calib;
+ ops->init_noisefloor_calib = ar5008_init_noisefloor_calib;
+ ops->get_noisefloor = ar5008_get_noisefloor;
+ ops->apply_noisefloor = ar5008_apply_noisefloor;
ops->do_calib = ar5008_do_calib;
ops->next_calib = ar5008_next_calib;
ops->hw_init = ar5008_hw_init;
@@ -1876,15 +1880,15 @@ ar5008_write_noisefloor(struct athn_softc *sc, int16_t *nf, int16_t *nf_ext)
AR_WRITE_BARRIER(sc);
}
-void
-ar5008_get_noisefloor(struct athn_softc *sc, struct ieee80211_channel *c)
+int
+ar5008_get_noisefloor(struct athn_softc *sc)
{
int16_t nf[AR_MAX_CHAINS], nf_ext[AR_MAX_CHAINS];
int i;
if (AR_READ(sc, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
/* Noisefloor calibration not finished. */
- return;
+ return 0;
}
/* Noisefloor calibration is finished. */
ar5008_read_noisefloor(sc, nf, nf_ext);
@@ -1896,6 +1900,7 @@ ar5008_get_noisefloor(struct athn_softc *sc, struct ieee80211_channel *c)
}
if (++sc->nf_hist_cur >= ATHN_NF_CAL_HIST_MAX)
sc->nf_hist_cur = 0;
+ return 1;
}
void
@@ -1926,14 +1931,41 @@ ar5008_bb_load_noisefloor(struct athn_softc *sc)
return;
}
- /* Restore noisefloor values to initial (max) values. */
+ /*
+ * Restore noisefloor values to initial (max) values. These will
+ * be used as initial values during the next NF calibration.
+ */
for (i = 0; i < AR_MAX_CHAINS; i++)
nf[i] = nf_ext[i] = AR_DEFAULT_NOISE_FLOOR;
ar5008_write_noisefloor(sc, nf, nf_ext);
}
void
-ar5008_noisefloor_calib(struct athn_softc *sc)
+ar5008_apply_noisefloor(struct athn_softc *sc)
+{
+ uint32_t agc_nfcal;
+
+ agc_nfcal = AR_READ(sc, AR_PHY_AGC_CONTROL) &
+ (AR_PHY_AGC_CONTROL_NF | AR_PHY_AGC_CONTROL_ENABLE_NF |
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+
+ if (agc_nfcal & AR_PHY_AGC_CONTROL_NF) {
+ /* Pause running NF calibration while values are updated. */
+ AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+ AR_WRITE_BARRIER(sc);
+ }
+
+ ar5008_bb_load_noisefloor(sc);
+
+ if (agc_nfcal & AR_PHY_AGC_CONTROL_NF) {
+ /* Restart interrupted NF calibration. */
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, agc_nfcal);
+ AR_WRITE_BARRIER(sc);
+ }
+}
+
+void
+ar5008_do_noisefloor_calib(struct athn_softc *sc)
{
AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
@@ -1942,7 +1974,7 @@ ar5008_noisefloor_calib(struct athn_softc *sc)
}
void
-ar5008_do_noisefloor_calib(struct athn_softc *sc)
+ar5008_init_noisefloor_calib(struct athn_softc *sc)
{
AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
AR_WRITE_BARRIER(sc);