summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2010-12-31 17:17:15 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2010-12-31 17:17:15 +0000
commit86475832be1dd5c523be9ae6c692d54867b08db6 (patch)
tree081566a2015b1631176bb60db4af2632e1bd917f /sys/dev/ic
parentf0f6a29566d2e88652c1e61ef67cd33426587c7c (diff)
commit some bits that will be required by AR9271/AR7010
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/ar5008.c35
-rw-r--r--sys/dev/ic/ar9285.c176
-rw-r--r--sys/dev/ic/ar9285reg.h16
-rw-r--r--sys/dev/ic/athn.c87
-rw-r--r--sys/dev/ic/athnreg.h20
5 files changed, 259 insertions, 75 deletions
diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c
index 5e03a334897..7b3cce75aff 100644
--- a/sys/dev/ic/ar5008.c
+++ b/sys/dev/ic/ar5008.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5008.c,v 1.15 2010/12/31 14:06:05 damien Exp $ */
+/* $OpenBSD: ar5008.c,v 1.16 2010/12/31 17:17:14 damien Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -817,7 +817,7 @@ ar5008_rx_process(struct athn_softc *sc)
ieee80211_michael_mic_failure(ic, 0);
/*
* XXX Check that it is not a control frame
- * (invalid MIC failures on valid ctl frames.)
+ * (invalid MIC failures on valid ctl frames).
*/
}
ifp->if_ierrors++;
@@ -1492,7 +1492,7 @@ ar5008_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
ds->ds_ctl4 |= AR_TXC4_RTSCTS_QUAL01;
ds->ds_ctl5 |= AR_TXC5_RTSCTS_QUAL23;
}
- /* Select protection rate (suboptimal but ok.) */
+ /* Select protection rate (suboptimal but ok). */
protridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK2;
if (ds->ds_ctl0 & AR_TXC0_RTS_ENABLE) {
@@ -1515,7 +1515,7 @@ ar5008_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
ds->ds_ctl7 |= SM(AR_TXC7_RTSCTS_RATE, hwrate);
}
- /* Finalize first Tx descriptor and fill others (if any.) */
+ /* Finalize first Tx descriptor and fill others (if any). */
ds->ds_ctl0 |= SM(AR_TXC0_FRAME_LEN, totlen);
for (i = 0; i < bf->bf_map->dm_nsegs; i++, ds++) {
@@ -1729,7 +1729,7 @@ ar5008_set_rxchains(struct athn_softc *sc)
void
ar5008_read_noisefloor(struct athn_softc *sc, int16_t *nf, int16_t *nf_ext)
{
-/* Sign-extends 9-bit value (assumes upper bits are zeroes.) */
+/* Sign-extends 9-bit value (assumes upper bits are zeroes). */
#define SIGN_EXT(v) (((v) ^ 0x100) - 0x100)
uint32_t reg;
int i;
@@ -2149,7 +2149,7 @@ ar5008_set_viterbi_mask(struct athn_softc *sc, int bin)
for (cur = -100; cur >= -6100; cur -= 100)
m[-cur / 100] = abs(cur - bin) < 75;
- /* Write viterbi mask (XXX needs to be reworked.) */
+ /* Write viterbi mask (XXX needs to be reworked). */
reg =
m[46] << 30 | m[47] << 28 | m[48] << 26 | m[49] << 24 |
m[50] << 22 | m[51] << 20 | m[52] << 18 | m[53] << 16 |
@@ -2221,6 +2221,7 @@ ar5008_hw_init(struct athn_softc *sc, struct ieee80211_channel *c,
struct athn_ops *ops = &sc->ops;
const struct athn_ini *ini = sc->ini;
const uint32_t *pvals;
+ uint32_t reg;
int i;
AR_WRITE(sc, AR_PHY(0), 0x00000007);
@@ -2312,13 +2313,15 @@ ar5008_hw_init(struct athn_softc *sc, struct ieee80211_channel *c,
AR_SETBITS(sc, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
/* Hardware workarounds for occasional Rx data corruption. */
- if (AR_SREV_9287_10_OR_LATER(sc))
- AR_CLRBITS(sc, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_HWWAR1);
- else if (AR_SREV_9280_10_OR_LATER(sc))
- AR_CLRBITS(sc, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_HWWAR1 |
- AR_PCU_MISC_MODE2_HWWAR2);
-
- if (AR_SREV_5416_20_OR_LATER(sc) && !AR_SREV_9280_10_OR_LATER(sc)) {
+ if (AR_SREV_9280_10_OR_LATER(sc)) {
+ reg = AR_READ(sc, AR_PCU_MISC_MODE2);
+ if (!AR_SREV_9271(sc))
+ reg &= ~AR_PCU_MISC_MODE2_HWWAR1;
+ if (AR_SREV_9287_10_OR_LATER(sc))
+ reg &= ~AR_PCU_MISC_MODE2_HWWAR2;
+ AR_WRITE(sc, AR_PCU_MISC_MODE2, reg);
+
+ } else if (AR_SREV_5416_20_OR_LATER(sc)) {
/* Disable baseband clock gating. */
AR_WRITE(sc, AR_PHY(651), 0x11);
@@ -2397,7 +2400,7 @@ ar5008_get_pdadcs(struct athn_softc *sc, uint8_t fbin,
boundaries[i] = AR_MAX_RATE_POWER;
if (i == 0 && !AR_SREV_5416_20_OR_LATER(sc)) {
- /* Fix the gain delta (AR5416 1.0 only.) */
+ /* Fix the gain delta (AR5416 1.0 only). */
delta = boundaries[0] - 23;
boundaries[0] = 23;
} else
@@ -2483,7 +2486,7 @@ ar5008_get_lg_tpow(struct athn_softc *sc, struct ieee80211_channel *c,
uint8_t fbin;
int i, lo, hi;
- /* Find interval (lower and upper indices.) */
+ /* Find interval (lower and upper indices). */
fbin = athn_chan2fbin(c);
for (i = 0; i < nchans; i++) {
if (tgt[i].bChannel == AR_BCHAN_UNUSED ||
@@ -2515,7 +2518,7 @@ ar5008_get_ht_tpow(struct athn_softc *sc, struct ieee80211_channel *c,
uint8_t fbin;
int i, lo, hi;
- /* Find interval (lower and upper indices.) */
+ /* Find interval (lower and upper indices). */
fbin = athn_chan2fbin(c);
for (i = 0; i < nchans; i++) {
if (tgt[i].bChannel == AR_BCHAN_UNUSED ||
diff --git a/sys/dev/ic/ar9285.c b/sys/dev/ic/ar9285.c
index f9085b432a6..73c13740265 100644
--- a/sys/dev/ic/ar9285.c
+++ b/sys/dev/ic/ar9285.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar9285.c,v 1.13 2010/12/31 14:06:05 damien Exp $ */
+/* $OpenBSD: ar9285.c,v 1.14 2010/12/31 17:17:14 damien Exp $ */
/*-
* Copyright (c) 2009-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -73,8 +73,10 @@ const struct ar_spur_chan *ar9285_get_spur_chans(struct athn_softc *, int);
void ar9285_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
struct ieee80211_channel *);
void ar9285_pa_calib(struct athn_softc *);
+void ar9271_pa_calib(struct athn_softc *);
int ar9285_cl_cal(struct athn_softc *, struct ieee80211_channel *,
struct ieee80211_channel *);
+void ar9271_load_ani(struct athn_softc *);
int ar9285_init_calib(struct athn_softc *, struct ieee80211_channel *,
struct ieee80211_channel *);
void ar9285_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
@@ -132,7 +134,12 @@ ar9285_setup(struct athn_softc *sc)
/* Select initialization values based on ROM. */
type = eep->baseEepHeader.txGainType;
DPRINTF(("Tx gain type=0x%x\n", type));
- if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1) { /* XE rev. */
+ if (AR_SREV_9271(sc)) {
+ if (type == AR_EEP_TXGAIN_HIGH_POWER)
+ sc->tx_gain = &ar9271_tx_gain_high_power;
+ else
+ sc->tx_gain = &ar9271_tx_gain;
+ } else if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1) { /* XE rev. */
if (type == AR_EEP_TXGAIN_HIGH_POWER)
sc->tx_gain = &ar9285_2_0_tx_gain_high_power;
else
@@ -299,29 +306,45 @@ ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
db2[0] = modal->db1_01;
db2[1] = db2[2] = db2[3] = db2[4] = db2[0];
}
- reg = AR_READ(sc, AR9285_AN_RF2G3);
- reg = RW(reg, AR9285_AN_RF2G3_OB_0, ob [0]);
- reg = RW(reg, AR9285_AN_RF2G3_OB_1, ob [1]);
- reg = RW(reg, AR9285_AN_RF2G3_OB_2, ob [2]);
- reg = RW(reg, AR9285_AN_RF2G3_OB_3, ob [3]);
- reg = RW(reg, AR9285_AN_RF2G3_OB_4, ob [4]);
- reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0]);
- reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1]);
- reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2]);
- AR_WRITE(sc, AR9285_AN_RF2G3, reg);
- AR_WRITE_BARRIER(sc);
- DELAY(100);
- reg = AR_READ(sc, AR9285_AN_RF2G4);
- reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3]);
- reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4]);
- reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0]);
- reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1]);
- reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2]);
- reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3]);
- reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4]);
- AR_WRITE(sc, AR9285_AN_RF2G4, reg);
- AR_WRITE_BARRIER(sc);
- DELAY(100);
+ if (AR_SREV_9271(sc)) {
+ reg = AR_READ(sc, AR9285_AN_RF2G3);
+ reg = RW(reg, AR9271_AN_RF2G3_OB_CCK, ob [0]);
+ reg = RW(reg, AR9271_AN_RF2G3_OB_PSK, ob [1]);
+ reg = RW(reg, AR9271_AN_RF2G3_OB_QAM, ob [2]);
+ reg = RW(reg, AR9271_AN_RF2G3_DB1, db1[0]);
+ AR_WRITE(sc, AR9285_AN_RF2G3, reg);
+ AR_WRITE_BARRIER(sc);
+ DELAY(100);
+ reg = AR_READ(sc, AR9285_AN_RF2G4);
+ reg = RW(reg, AR9271_AN_RF2G4_DB2, db2[0]);
+ AR_WRITE(sc, AR9285_AN_RF2G4, reg);
+ AR_WRITE_BARRIER(sc);
+ DELAY(100);
+ } else {
+ reg = AR_READ(sc, AR9285_AN_RF2G3);
+ reg = RW(reg, AR9285_AN_RF2G3_OB_0, ob [0]);
+ reg = RW(reg, AR9285_AN_RF2G3_OB_1, ob [1]);
+ reg = RW(reg, AR9285_AN_RF2G3_OB_2, ob [2]);
+ reg = RW(reg, AR9285_AN_RF2G3_OB_3, ob [3]);
+ reg = RW(reg, AR9285_AN_RF2G3_OB_4, ob [4]);
+ reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0]);
+ reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1]);
+ reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2]);
+ AR_WRITE(sc, AR9285_AN_RF2G3, reg);
+ AR_WRITE_BARRIER(sc);
+ DELAY(100);
+ reg = AR_READ(sc, AR9285_AN_RF2G4);
+ reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3]);
+ reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4]);
+ reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0]);
+ reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1]);
+ reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2]);
+ reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3]);
+ reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4]);
+ AR_WRITE(sc, AR9285_AN_RF2G4, reg);
+ AR_WRITE_BARRIER(sc);
+ DELAY(100);
+ }
reg = AR_READ(sc, AR_PHY_SETTLING);
reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
@@ -431,7 +454,6 @@ ar9285_pa_calib(struct athn_softc *sc)
AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS_6_1);
/* Clear offset 0. */
AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
-
/* Set offsets 6-1. */
for (i = 6; i >= 1; i--) {
AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i));
@@ -454,6 +476,8 @@ ar9285_pa_calib(struct athn_softc *sc)
else
AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
+ AR_WRITE_BARRIER(sc);
+
AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
@@ -468,6 +492,91 @@ ar9285_pa_calib(struct athn_softc *sc)
AR_WRITE_BARRIER(sc);
}
+void
+ar9271_pa_calib(struct athn_softc *sc)
+{
+ /* List of registers that need to be saved/restored. */
+ static const uint16_t regs[] = {
+ AR9285_AN_TOP3,
+ AR9285_AN_RXTXBB1,
+ AR9285_AN_RF2G1,
+ AR9285_AN_RF2G2,
+ AR9285_AN_TOP2,
+ AR9285_AN_RF2G8,
+ AR9285_AN_RF2G7
+ };
+ uint32_t svg[7], reg, ccomp_svg;
+ int i;
+
+ /* Save registers. */
+ for (i = 0; i < nitems(regs); i++)
+ svg[i] = AR_READ(sc, regs[i]);
+
+ AR_CLRBITS(sc, AR9285_AN_RF2G6, 1);
+ AR_SETBITS(sc, AR_PHY(2), 1 << 27);
+
+ AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
+ AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
+ AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
+ AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
+ AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
+ AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
+ AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
+ /* Power down PA drivers. */
+ AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
+ AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
+ AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
+
+ reg = AR_READ(sc, AR9285_AN_RF2G8);
+ reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+ AR_WRITE(sc, AR9285_AN_RF2G8, reg);
+
+ reg = AR_READ(sc, AR9285_AN_RF2G7);
+ reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+ AR_WRITE(sc, AR9285_AN_RF2G7, reg);
+
+ reg = AR_READ(sc, AR9285_AN_RF2G3);
+ /* Save compensation capacitor value. */
+ ccomp_svg = MS(reg, AR9271_AN_RF2G3_CCOMP);
+ /* Program compensation capacitor for dynamic PA. */
+ reg = RW(reg, AR9271_AN_RF2G3_CCOMP, 0xfff);
+ AR_WRITE(sc, AR9285_AN_RF2G3, reg);
+
+ AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
+ AR_WRITE_BARRIER(sc);
+ DELAY(30);
+
+ /* Clear offsets 6-0. */
+ AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS_6_0);
+ /* Set offsets 6-1. */
+ for (i = 6; i >= 1; i--) {
+ AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i));
+ AR_WRITE_BARRIER(sc);
+ DELAY(1);
+ if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9) {
+ AR_SETBITS(sc, AR9285_AN_RF2G6,
+ AR9271_AN_RF2G6_OFFS(i));
+ } else {
+ AR_CLRBITS(sc, AR9285_AN_RF2G6,
+ AR9271_AN_RF2G6_OFFS(i));
+ }
+ }
+ AR_WRITE_BARRIER(sc);
+
+ AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
+ AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
+
+ /* Restore registers. */
+ for (i = 0; i < nitems(regs); i++)
+ AR_WRITE(sc, regs[i], svg[i]);
+
+ /* Restore compensation capacitor value. */
+ reg = AR_READ(sc, AR9285_AN_RF2G3);
+ reg = RW(reg, AR9271_AN_RF2G3_CCOMP, ccomp_svg);
+ AR_WRITE(sc, AR9285_AN_RF2G3, reg);
+ AR_WRITE_BARRIER(sc);
+}
+
/*
* Carrier Leakage Calibration.
*/
@@ -518,6 +627,21 @@ ar9285_cl_cal(struct athn_softc *sc, struct ieee80211_channel *c,
return (0);
}
+void
+ar9271_load_ani(struct athn_softc *sc)
+{
+ /* Write ANI registers. */
+ AR_WRITE(sc, AR_PHY_DESIRED_SZ, 0x6d4000e2);
+ AR_WRITE(sc, AR_PHY_AGC_CTL1, 0x3139605e);
+ AR_WRITE(sc, AR_PHY_FIND_SIG, 0x7ec84d2e);
+ AR_WRITE(sc, AR_PHY_SFCORR_LOW, 0x06903881);
+ AR_WRITE(sc, AR_PHY_SFCORR, 0x5ac640d0);
+ AR_WRITE(sc, AR_PHY_CCK_DETECT, 0x803e68c8);
+ AR_WRITE(sc, AR_PHY_TIMING5, 0xd00a8007);
+ AR_WRITE(sc, AR_PHY_SFCORR_EXT, 0x05eea6d4);
+ AR_WRITE_BARRIER(sc);
+}
+
int
ar9285_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
struct ieee80211_channel *extc)
diff --git a/sys/dev/ic/ar9285reg.h b/sys/dev/ic/ar9285reg.h
index a4880937327..a7bc6bf5615 100644
--- a/sys/dev/ic/ar9285reg.h
+++ b/sys/dev/ic/ar9285reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar9285reg.h,v 1.5 2010/12/31 14:37:15 damien Exp $ */
+/* $OpenBSD: ar9285reg.h,v 1.6 2010/12/31 17:17:14 damien Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -67,6 +67,16 @@
#define AR9285_AN_RF2G3_OB_0_M 0x00e00000
#define AR9285_AN_RF2G3_OB_0_S 21
#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000
+#define AR9271_AN_RF2G3_CCOMP_M 0x00000fff
+#define AR9271_AN_RF2G3_CCOMP_S 0
+#define AR9271_AN_RF2G3_OB_QAM_M 0x00007000
+#define AR9271_AN_RF2G3_OB_QAM_S 12
+#define AR9271_AN_RF2G3_OB_PSK_M 0x00038000
+#define AR9271_AN_RF2G3_OB_PSK_S 15
+#define AR9271_AN_RF2G3_OB_CCK_M 0x001c0000
+#define AR9271_AN_RF2G3_OB_CCK_S 18
+#define AR9271_AN_RF2G3_DB1_M 0x00e00000
+#define AR9271_AN_RF2G3_DB1_S 21
/* Bits for AR9285_AN_RF2G4. */
#define AR9285_AN_RF2G4_DB2_4_M 0x00003800
@@ -83,6 +93,8 @@
#define AR9285_AN_RF2G4_DB1_4_S 26
#define AR9285_AN_RF2G4_DB1_3_M 0xe0000000
#define AR9285_AN_RF2G4_DB1_3_S 29
+#define AR9271_AN_RF2G4_DB2_M 0xe0000000
+#define AR9271_AN_RF2G4_DB2_S 29
/* Bits for AR9285_AN_RF2G5. */
#define AR9285_AN_RF2G5_IC50TX_M 0x00000700
@@ -93,6 +105,8 @@
#define AR9285_AN_RF2G6_CCOMP_S 11
#define AR9285_AN_RF2G6_OFFS_6_1 0x03f00000
#define AR9285_AN_RF2G6_OFFS(i) (1 << (19 + (i)))
+#define AR9271_AN_RF2G6_OFFS_6_0 0x07f00000
+#define AR9271_AN_RF2G6_OFFS(i) (1 << (20 + (i)))
/* Bits for AR9285_AN_RF2G7. */
#define AR9285_AN_RF2G7_PWDDB 0x00000002
diff --git a/sys/dev/ic/athn.c b/sys/dev/ic/athn.c
index e05ea581614..3f42e96d79d 100644
--- a/sys/dev/ic/athn.c
+++ b/sys/dev/ic/athn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: athn.c,v 1.65 2010/12/31 14:52:47 damien Exp $ */
+/* $OpenBSD: athn.c,v 1.66 2010/12/31 17:17:14 damien Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -151,12 +151,14 @@ int ar9280_attach(struct athn_softc *);
int ar9285_attach(struct athn_softc *);
int ar9287_attach(struct athn_softc *);
int ar9380_attach(struct athn_softc *);
+void ar9271_load_ani(struct athn_softc *);
int ar5416_init_calib(struct athn_softc *,
struct ieee80211_channel *, struct ieee80211_channel *);
int ar9285_init_calib(struct athn_softc *,
struct ieee80211_channel *, struct ieee80211_channel *);
int ar9003_init_calib(struct athn_softc *);
void ar9285_pa_calib(struct athn_softc *);
+void ar9271_pa_calib(struct athn_softc *);
void ar9287_1_3_enable_async_fifo(struct athn_softc *);
void ar9287_1_3_setup_async_fifo(struct athn_softc *);
void ar9003_reset_txsring(struct athn_softc *);
@@ -186,11 +188,11 @@ athn_attach(struct athn_softc *sc)
error = ar5416_attach(sc);
else if (AR_SREV_9280(sc))
error = ar9280_attach(sc);
- else if (AR_SREV_9285(sc))
+ else if (AR_SREV_9285(sc) || AR_SREV_9271(sc))
error = ar9285_attach(sc);
else if (AR_SREV_9287(sc))
error = ar9287_attach(sc);
- else if (AR_SREV_9380(sc))
+ else if (AR_SREV_9380(sc) || AR_SREV_9485(sc))
error = ar9380_attach(sc);
else
error = ENOTSUP;
@@ -202,15 +204,17 @@ athn_attach(struct athn_softc *sc)
/* We can put the chip in sleep state now. */
athn_set_power_sleep(sc);
- error = sc->ops.dma_alloc(sc);
- if (error != 0) {
- printf("%s: could not allocate DMA resources\n",
- sc->sc_dev.dv_xname);
- return (error);
+ if (!(sc->flags & ATHN_FLAG_USB)) {
+ error = sc->ops.dma_alloc(sc);
+ if (error != 0) {
+ printf("%s: could not allocate DMA resources\n",
+ sc->sc_dev.dv_xname);
+ return (error);
+ }
+ /* Steal one Tx buffer for beacons. */
+ sc->bcnbuf = SIMPLEQ_FIRST(&sc->txbufs);
+ SIMPLEQ_REMOVE_HEAD(&sc->txbufs, bf_list);
}
- /* Steal one Tx buffer for beacons. */
- sc->bcnbuf = SIMPLEQ_FIRST(&sc->txbufs);
- SIMPLEQ_REMOVE_HEAD(&sc->txbufs, bf_list);
if (sc->flags & ATHN_FLAG_RFSILENT) {
DPRINTF(("found RF switch connected to GPIO pin %d\n",
@@ -286,7 +290,7 @@ athn_attach(struct athn_softc *sc)
IEEE80211_HTCAP_CBW20_40 |
IEEE80211_HTCAP_SGI40 |
IEEE80211_HTCAP_DSSSCCK40;
- if (AR_SREV_9287_10_OR_LATER(sc))
+ if (AR_SREV_9271(sc) || AR_SREV_9287_10_OR_LATER(sc))
ic->ic_htcaps |= IEEE80211_HTCAP_SGI20;
if (AR_SREV_9380_10_OR_LATER(sc))
ic->ic_htcaps |= IEEE80211_HTCAP_LDPC;
@@ -371,12 +375,13 @@ athn_detach(struct athn_softc *sc)
timeout_del(&sc->scan_to);
timeout_del(&sc->calib_to);
- for (qid = 0; qid < ATHN_QID_COUNT; qid++)
- athn_tx_reclaim(sc, qid);
-
- /* Free Tx/Rx DMA resources. */
- sc->ops.dma_free(sc);
+ if (!(sc->flags & ATHN_FLAG_USB)) {
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++)
+ athn_tx_reclaim(sc, qid);
+ /* Free Tx/Rx DMA resources. */
+ sc->ops.dma_free(sc);
+ }
/* Free ROM copy. */
if (sc->eep != NULL)
free(sc->eep, M_DEVBUF);
@@ -555,16 +560,20 @@ athn_get_mac_name(struct athn_softc *sc)
return ("AR9280");
case AR_SREV_VERSION_9285:
return ("AR9285");
+ case AR_SREV_VERSION_9271:
+ return ("AR9271");
case AR_SREV_VERSION_9287:
return ("AR9287");
case AR_SREV_VERSION_9380:
return ("AR9380");
+ case AR_SREV_VERSION_9485:
+ return ("AR9485");
}
return ("unknown");
}
/*
- * Return RF chip name (not for single-chip solutions.)
+ * Return RF chip name (not for single-chip solutions).
*/
const char *
athn_get_rf_name(struct athn_softc *sc)
@@ -708,7 +717,7 @@ athn_set_power_sleep(struct athn_softc *sc)
* NB: Clearing RTC_RESET_EN when setting the chip to sleep mode
* results in high power consumption on AR5416 chipsets.
*/
- if (!AR_SREV_5416(sc))
+ if (!AR_SREV_5416(sc) && !AR_SREV_9271(sc))
AR_CLRBITS(sc, AR_RTC_RESET, AR_RTC_RESET_EN);
AR_WRITE_BARRIER(sc);
}
@@ -719,6 +728,8 @@ athn_init_pll(struct athn_softc *sc, const struct ieee80211_channel *c)
uint32_t pll;
if (AR_SREV_9380_10_OR_LATER(sc)) {
+ if (AR_SREV_9485(sc))
+ AR_WRITE(sc, AR_RTC_PLL_CONTROL2, 0x886666);
pll = SM(AR_RTC_9160_PLL_REFDIV, 0x5);
pll |= SM(AR_RTC_9160_PLL_DIV, 0x2c);
} else if (AR_SREV_9280_10_OR_LATER(sc)) {
@@ -747,6 +758,12 @@ athn_init_pll(struct athn_softc *sc, const struct ieee80211_channel *c)
}
DPRINTFN(5, ("AR_RTC_PLL_CONTROL=0x%08x\n", pll));
AR_WRITE(sc, AR_RTC_PLL_CONTROL, pll);
+ if (AR_SREV_9271(sc)) {
+ /* Switch core clock to 117MHz. */
+ AR_WRITE_BARRIER(sc);
+ DELAY(500);
+ AR_WRITE(sc, 0x50050, 0x304);
+ }
AR_WRITE_BARRIER(sc);
DELAY(100);
AR_WRITE(sc, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
@@ -856,8 +873,10 @@ athn_switch_chan(struct athn_softc *sc, struct ieee80211_channel *c,
if (error != 0)
goto reset;
- /* AR9280 always needs a full reset. */
-/* if (AR_SREV_9280(sc))*/
+#ifdef notyet
+ /* AR9280 (but not AR9280+AR7010) needs a full reset. */
+ if (AR_SREV_9280(sc) && !(sc->flags & ATHN_FLAG_USB))
+#endif
goto reset;
/* If band or bandwidth changes, we need to do a full reset. */
@@ -871,6 +890,8 @@ athn_switch_chan(struct athn_softc *sc, struct ieee80211_channel *c,
goto reset;
error = athn_set_chan(sc, c, extc);
+ if (AR_SREV_9271(sc) && error == 0)
+ ar9271_load_ani(sc);
if (error != 0) {
reset: /* Error found, try a full reset. */
DPRINTFN(3, ("needs a full reset\n"));
@@ -1175,7 +1196,10 @@ athn_calib_to(void *arg)
!AR_SREV_9380_10_OR_LATER(sc) &&
ticks >= sc->pa_calib_ticks + 240 * hz) {
sc->pa_calib_ticks = ticks;
- ar9285_pa_calib(sc);
+ if (AR_SREV_9271(sc))
+ ar9271_pa_calib(sc);
+ else
+ ar9285_pa_calib(sc);
}
/* Do periodic (every 30 seconds) temperature compensation. */
@@ -1222,7 +1246,10 @@ athn_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
if (AR_SREV_9285_11_OR_LATER(sc)) {
extern int ticks;
sc->pa_calib_ticks = ticks;
- ar9285_pa_calib(sc);
+ if (AR_SREV_9271(sc))
+ ar9271_pa_calib(sc);
+ else
+ ar9285_pa_calib(sc);
}
/* Do noisefloor calibration. */
ops->noisefloor_calib(sc);
@@ -1569,7 +1596,7 @@ athn_init_dma(struct athn_softc *sc)
reg = RW(reg, AR_TXCFG_DMASZ, AR_DMASZ_128B);
/* Set initial Tx trigger level. */
- if (AR_SREV_9285(sc))
+ if (AR_SREV_9285(sc) || AR_SREV_9271(sc))
reg = RW(reg, AR_TXCFG_FTRIG, AR_TXCFG_FTRIG_256B);
else if (!AR_SREV_9380_10_OR_LATER(sc))
reg = RW(reg, AR_TXCFG_FTRIG, AR_TXCFG_FTRIG_512B);
@@ -1584,9 +1611,13 @@ athn_init_dma(struct athn_softc *sc)
AR_WRITE(sc, AR_RXFIFO_CFG, 512);
/* Reduce the number of entries in PCU TXBUF to avoid wrap around. */
- AR_WRITE(sc, AR_PCU_TXBUF_CTRL, AR_SREV_9285(sc) ?
- AR9285_PCU_TXBUF_CTRL_USABLE_SIZE :
- AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+ if (AR_SREV_9285(sc)) {
+ AR_WRITE(sc, AR_PCU_TXBUF_CTRL,
+ AR9285_PCU_TXBUF_CTRL_USABLE_SIZE);
+ } else if (!AR_SREV_9271(sc)) {
+ AR_WRITE(sc, AR_PCU_TXBUF_CTRL,
+ AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+ }
AR_WRITE_BARRIER(sc);
/* Reset Tx status ring. */
@@ -2741,7 +2772,7 @@ athn_stop(struct ifnet *ifp, int disable)
/* Disable interrupts. */
athn_disable_interrupts(sc);
- /* Acknowledge interrupts (avoids interrupt storms.) */
+ /* Acknowledge interrupts (avoids interrupt storms). */
AR_WRITE(sc, AR_INTR_SYNC_CAUSE, 0xffffffff);
AR_WRITE(sc, AR_INTR_SYNC_MASK, 0);
diff --git a/sys/dev/ic/athnreg.h b/sys/dev/ic/athnreg.h
index edfa1fd2644..7d7b14a5258 100644
--- a/sys/dev/ic/athnreg.h
+++ b/sys/dev/ic/athnreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: athnreg.h,v 1.14 2010/12/31 14:06:05 damien Exp $ */
+/* $OpenBSD: athnreg.h,v 1.15 2010/12/31 17:17:14 damien Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -116,6 +116,7 @@
#define AR_RTC_REG_CONTROL0 0x7008
#define AR_RTC_REG_CONTROL1 0x700c
#define AR_RTC_PLL_CONTROL 0x7014
+#define AR_RTC_PLL_CONTROL2 0x703c
#define AR_RTC_RESET 0x7040
#define AR_RTC_STATUS 0x7044
#define AR_RTC_SLEEP_CLK 0x7048
@@ -775,6 +776,9 @@
#define AR_SREV_REVISION_9285_10 0
#define AR_SREV_REVISION_9285_11 1
#define AR_SREV_REVISION_9285_12 2
+#define AR_SREV_VERSION_9271 0x140
+#define AR_SREV_REVISION_9271_10 0
+#define AR_SREV_REVISION_9271_11 1
#define AR_SREV_VERSION_9287 0x180
#define AR_SREV_REVISION_9287_10 0
#define AR_SREV_REVISION_9287_11 1
@@ -783,6 +787,8 @@
#define AR_SREV_VERSION_9380 0x1c0
#define AR_SREV_REVISION_9380_10 0
#define AR_SREV_REVISION_9380_20 2
+#define AR_SREV_VERSION_9485 0x240
+#define AR_SREV_REVISION_9485_10 0
/* Bits for AR_AHB_MODE. */
#define AR_AHB_EXACT_WR_EN 0x00000000
@@ -1354,6 +1360,9 @@
((sc)->mac_ver > AR_SREV_VERSION_9285 || \
(AR_SREV_9285(sc) && (sc)->mac_rev >= AR_SREV_REVISION_9285_12))
+#define AR_SREV_9271(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9271)
+
#define AR_SREV_9287(sc) \
((sc)->mac_ver == AR_SREV_VERSION_9287)
#define AR_SREV_9287_10_OR_LATER(sc) \
@@ -1388,6 +1397,9 @@
((sc)->mac_ver > AR_SREV_VERSION_9380 || \
(AR_SREV_9380(sc) && (sc)->mac_rev >= AR_SREV_REVISION_9380_20))
+#define AR_SREV_9485(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9485)
+
#define AR_SINGLE_CHIP(sc) AR_SREV_9280_10_OR_LATER(sc)
#define AR_RADIO_SREV_MAJOR 0xf0
@@ -1440,13 +1452,13 @@ static const uint32_t ar_nonpcie_serdes[] = {
* Macros to access registers.
*/
#define AR_READ(sc, reg) \
- sc->ops.read((sc), (reg))
+ (sc)->ops.read((sc), (reg))
#define AR_WRITE(sc, reg, val) \
- sc->ops.write((sc), (reg), (val))
+ (sc)->ops.write((sc), (reg), (val))
#define AR_WRITE_BARRIER(sc) \
- sc->ops.write_barrier((sc))
+ (sc)->ops.write_barrier((sc))
#define AR_SETBITS(sc, reg, mask) \
AR_WRITE(sc, reg, AR_READ(sc, reg) | (mask))