summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/ar5416.c914
-rw-r--r--sys/dev/ic/ar5416reg.h829
-rw-r--r--sys/dev/ic/ar9280.c583
-rw-r--r--sys/dev/ic/ar9280reg.h969
-rw-r--r--sys/dev/ic/ar9285.c680
-rw-r--r--sys/dev/ic/ar9285reg.h991
-rw-r--r--sys/dev/ic/ar9287.c605
-rw-r--r--sys/dev/ic/ar9287reg.h896
-rw-r--r--sys/dev/ic/athn.c4663
-rw-r--r--sys/dev/ic/athnreg.h2410
-rw-r--r--sys/dev/ic/athnvar.h513
11 files changed, 14053 insertions, 0 deletions
diff --git a/sys/dev/ic/ar5416.c b/sys/dev/ic/ar5416.c
new file mode 100644
index 00000000000..f808236f5a7
--- /dev/null
+++ b/sys/dev/ic/ar5416.c
@@ -0,0 +1,914 @@
+/* $OpenBSD: ar5416.c,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for Atheros 802.11a/g/n chipsets.
+ * Routines for AR5416, AR5418 and AR9160 chipsets.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/timeout.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/endian.h>
+#include <machine/intr.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/ic/athnreg.h>
+#include <dev/ic/athnvar.h>
+
+#include <dev/ic/ar5416reg.h>
+
+int ar5416_attach(struct athn_softc *);
+void ar5416_setup(struct athn_softc *);
+int ar5416_set_synth(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar5416_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+int ar5416_init_calib(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar5416_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
+ int, int, uint8_t, uint8_t *, uint8_t *);
+void ar5416_set_power_calib(struct athn_softc *,
+ struct ieee80211_channel *);
+void ar5416_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar5416_rw_rfbits(uint32_t *, int, int, uint32_t, int);
+void ar5416_rw_bank6tpc(struct athn_softc *, struct ieee80211_channel *,
+ uint32_t *);
+void ar5416_rf_reset(struct athn_softc *, struct ieee80211_channel *);
+void ar5416_reset_bb_gain(struct athn_softc *, struct ieee80211_channel *);
+void ar5416_force_bias(struct athn_softc *, struct ieee80211_channel *);
+void ar9160_rw_addac(struct athn_softc *, struct ieee80211_channel *,
+ uint32_t *);
+void ar5416_reset_addac(struct athn_softc *, struct ieee80211_channel *);
+
+int
+ar5416_attach(struct athn_softc *sc)
+{
+ sc->eep_base = AR5416_EEP_START_LOC;
+ sc->eep_size = sizeof (struct ar5416_eeprom);
+ sc->def_nf = AR5416_PHY_CCA_MAX_GOOD_VALUE;
+ sc->ngpiopins = 14;
+ sc->workaround = AR5416_WA_DEFAULT;
+ sc->ops.setup = ar5416_setup;
+ sc->ops.swap_rom = ar5416_swap_rom;
+ sc->ops.init_from_rom = ar5416_init_from_rom;
+ sc->ops.set_txpower = ar5416_set_txpower;
+ sc->ops.set_synth = ar5416_set_synth;
+ sc->ops.spur_mitigate = ar5416_spur_mitigate;
+ sc->ops.get_spur_chans = ar5416_get_spur_chans;
+ sc->ops.olpc_init = NULL;
+ if (AR_SREV_9160_10_OR_LATER(sc))
+ sc->ini = &ar9160_ini;
+ else
+ sc->ini = &ar5416_ini;
+ sc->serdes = ar5416_serdes;
+ return (0);
+}
+
+void
+ar5416_setup(struct athn_softc *sc)
+{
+ /* Select ADDAC programming. */
+ if (AR_SREV_9160_11(sc))
+ sc->addac = &ar9160_1_1_addac;
+ else if (AR_SREV_9160_10_OR_LATER(sc))
+ sc->addac = &ar9160_1_0_addac;
+ else if (AR_SREV_5416_22_OR_LATER(sc))
+ sc->addac = &ar5416_2_2_addac;
+ else
+ sc->addac = &ar5416_2_1_addac;
+}
+
+void
+ar5416_swap_rom(struct athn_softc *sc)
+{
+ struct ar5416_eeprom *eep = sc->eep;
+ struct ar5416_modal_eep_header *modal;
+ int i, j;
+
+ for (i = 0; i < 2; i++) { /* Dual-band. */
+ modal = &eep->modalHeader[i];
+
+ modal->antCtrlCommon = swap32(modal->antCtrlCommon);
+ for (j = 0; j < AR5416_MAX_CHAINS; j++) {
+ modal->antCtrlChain[j] =
+ swap32(modal->antCtrlChain[j]);
+ }
+ for (j = 0; j < AR_EEPROM_MODAL_SPURS; j++) {
+ modal->spurChans[j].spurChan =
+ swap16(modal->spurChans[j].spurChan);
+ }
+ }
+}
+
+const struct ar_spur_chan *
+ar5416_get_spur_chans(struct athn_softc *sc, int is2ghz)
+{
+ const struct ar5416_eeprom *eep = sc->eep;
+
+ return eep->modalHeader[is2ghz].spurChans;
+}
+
+int
+ar5416_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ uint32_t phy, reg;
+ uint32_t freq = c->ic_freq;
+ uint8_t chansel;
+
+ phy = 0;
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ if (((freq - 2192) % 5) == 0) {
+ chansel = ((freq - 672) * 2 - 3040) / 10;
+ } else if (((freq - 2224) % 5) == 0) {
+ chansel = ((freq - 704) * 2 - 3040) / 10;
+ phy |= AR5416_BMODE_SYNTH;
+ } else
+ return (EINVAL);
+ chansel <<= 2;
+
+ reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) /* Channel 14. */
+ reg |= AR_PHY_CCK_TX_CTRL_JAPAN;
+ else
+ reg &= ~AR_PHY_CCK_TX_CTRL_JAPAN;
+ AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
+
+ /* Fix for orientation sensitivity issue. */
+ if (AR_SREV_5416(sc))
+ ar5416_force_bias(sc, c);
+ } else {
+ if (freq >= 5120 && (freq % 20) == 0) {
+ chansel = (freq - 4800) / 20;
+ chansel <<= 2;
+ phy |= SM(AR5416_AMODE_REFSEL, 2);
+ } else if ((freq % 10) == 0) {
+ chansel = (freq - 4800) / 10;
+ chansel <<= 1;
+ if (AR_SREV_9160_10_OR_LATER(sc))
+ phy |= SM(AR5416_AMODE_REFSEL, 1);
+ else
+ phy |= SM(AR5416_AMODE_REFSEL, 2);
+ } else if ((freq % 5) == 0) {
+ chansel = (freq - 4800) / 5;
+ phy |= SM(AR5416_AMODE_REFSEL, 2);
+ } else
+ return (EINVAL);
+ }
+ chansel = athn_reverse_bits(chansel, 8);
+ phy |= chansel << 8 | 1 << 5 | 1;
+ DPRINTF(("AR_PHY(0x37)=0x%08x\n", phy));
+ AR_WRITE(sc, AR_PHY(0x37), phy);
+ return (0);
+}
+
+void
+ar5416_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
+ const struct ar5416_eeprom *eep = sc->eep;
+ const struct ar5416_modal_eep_header *modal;
+ uint32_t reg, offset;
+ uint8_t txRxAtten;
+ int i;
+
+ modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
+
+ AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon & 0xffff);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_20_OR_LATER(sc) &&
+ (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5))
+ offset = chainoffset[i];
+ else
+ offset = i * 0x1000;
+
+ AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
+ modal->antCtrlChain[i]);
+
+ reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+ modal->iqCalICh[i]);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+ modal->iqCalQCh[i]);
+ AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
+
+ if (i > 0 && !AR_SREV_5416_20_OR_LATER(sc))
+ continue;
+
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
+ reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_MARGIN,
+ modal->bswMargin[i]);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_ATTEN,
+ modal->bswAtten[i]);
+ AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
+ }
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
+ txRxAtten = modal->txRxAttenCh[i];
+ else /* Workaround for ROM versions < 14.3. */
+ txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
+ reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
+ reg = RW(reg, AR_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
+ AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
+
+ reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_RXTX_MARGIN,
+ modal->rxTxMarginCh[i]);
+ AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
+ }
+ reg = AR_READ(sc, AR_PHY_SETTLING);
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
+ AR_WRITE(sc, AR_PHY_SETTLING, reg);
+
+ reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
+ reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
+ reg = RW(reg, AR_PHY_DESIRED_SZ_PGA, modal->pgaDesiredSize);
+ AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
+
+ reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
+
+ reg = AR_READ(sc, AR_PHY_RF_CTL3);
+ reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
+
+ reg = AR_READ(sc, AR_PHY_CCA(0));
+ reg = RW(reg, AR_PHY_CCA_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_CCA(0), reg);
+
+ reg = AR_READ(sc, AR_PHY_EXT_CCA(0));
+ reg = RW(reg, AR_PHY_EXT_CCA_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_EXT_CCA(0), reg);
+
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
+ reg = AR_READ(sc, AR_PHY_RF_CTL2);
+ reg = RW(reg, AR_PHY_TX_END_DATA_START,
+ modal->txFrameToDataStart);
+ reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
+ }
+#ifndef IEEE80211_NO_HT
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
+ /* Overwrite switch settling with HT-40 value. */
+ reg = AR_READ(sc, AR_PHY_SETTLING);
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
+ AR_WRITE(sc, AR_PHY_SETTLING, reg);
+ }
+#endif
+}
+
+int
+ar5416_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ int ntries;
+
+ if (AR_SREV_9280_10_OR_LATER(sc)) {
+ /* XXX Linux tests AR9287?! */
+ AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
+ }
+ /* Calibrate the AGC. */
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+ /* Poll for offset calibration completion. */
+ for (ntries = 0; ntries < 10000; ntries++) {
+ if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_CAL))
+ break;
+ DELAY(10);
+ }
+ if (ntries == 10000)
+ return (ETIMEDOUT);
+ if (AR_SREV_9280_10_OR_LATER(sc)) {
+ AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+ AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
+ }
+ return (0);
+}
+
+void
+ar5416_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
+ int chain, int nxpdgains, uint8_t overlap, uint8_t *boundaries,
+ uint8_t *pdadcs)
+{
+ const struct ar5416_eeprom *eep = sc->eep;
+ const struct ar5416_cal_data_per_freq *pierdata;
+ const uint8_t *pierfreq;
+ struct athn_pier lopier, hipier;
+ int16_t delta;
+ uint8_t fbin, pwroff;
+ int i, lo, hi, npiers;
+
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ pierfreq = eep->calFreqPier2G;
+ pierdata = eep->calPierData2G[chain];
+ npiers = AR5416_NUM_2G_CAL_PIERS;
+ } else {
+ pierfreq = eep->calFreqPier5G;
+ pierdata = eep->calPierData5G[chain];
+ npiers = AR5416_NUM_5G_CAL_PIERS;
+ }
+ /* Find channel in ROM pier table. */
+ fbin = athn_chan2fbin(c);
+ athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
+
+ lopier.fbin = pierfreq[lo];
+ hipier.fbin = pierfreq[hi];
+ for (i = 0; i < nxpdgains; i++) {
+ lopier.pwr[i] = pierdata[lo].pwrPdg[i];
+ lopier.vpd[i] = pierdata[lo].vpdPdg[i];
+ hipier.pwr[i] = pierdata[lo].pwrPdg[i];
+ hipier.vpd[i] = pierdata[lo].vpdPdg[i];
+ }
+ athn_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
+ AR5416_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
+
+ if (!AR_SREV_9280_20_OR_LATER(sc))
+ return;
+
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_21)
+ pwroff = eep->baseEepHeader.pwrTableOffset;
+ else
+ pwroff = AR_PWR_TABLE_OFFSET_DB;
+ delta = (pwroff - AR_PWR_TABLE_OFFSET_DB) * 2; /* In half dB. */
+
+ /* Change the original gain boundaries setting. */
+ for (i = 0; i < nxpdgains; i++) {
+ /* XXX Possible overflows? */
+ boundaries[i] -= delta;
+ if (boundaries[i] > AR_MAX_RATE_POWER - overlap)
+ boundaries[i] = AR_MAX_RATE_POWER - overlap;
+ }
+ if (delta != 0) {
+ /* Shift the PDADC table to start at the new offset. */
+ for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
+ pdadcs[i] = pdadcs[MIN(i + delta,
+ AR_NUM_PDADC_VALUES - 1)];
+ }
+}
+
+void
+ar5416_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
+ const struct ar5416_eeprom *eep = sc->eep;
+ const struct ar5416_modal_eep_header *modal;
+ uint8_t boundaries[AR_PD_GAINS_IN_MASK];
+ uint8_t pdadcs[AR_NUM_PDADC_VALUES];
+ uint8_t xpdgains[AR5416_NUM_PD_GAINS];
+ uint8_t overlap, txgain;
+ uint32_t reg, offset;
+ int i, j, nxpdgains;
+
+ modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
+
+ if (sc->eep_rev < AR_EEP_MINOR_VER_2) {
+ overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+ } else
+ overlap = modal->pdGainOverlap;
+
+ if ((sc->flags & ATHN_FLAG_OLPC) && IEEE80211_IS_CHAN_2GHZ(c)) {
+ /* XXX not here. */
+ sc->pdadc =
+ ((const struct ar_cal_data_per_freq_olpc *)
+ eep->calPierData2G[0])->vpdPdg[0][0];
+ }
+
+ nxpdgains = 0;
+ memset(xpdgains, 0, sizeof xpdgains);
+ for (i = AR5416_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
+ if (nxpdgains >= AR5416_NUM_PD_GAINS)
+ break; /* Can't happen. */
+ if (modal->xpdGain & (1 << i))
+ xpdgains[nxpdgains++] = i;
+ }
+ reg = AR_READ(sc, AR_PHY_TPCRG1);
+ reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
+ reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
+ reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
+ reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_3, xpdgains[2]);
+ AR_WRITE(sc, AR_PHY_TPCRG1, reg);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (!(sc->txchainmask & (1 << i)))
+ continue;
+
+ if (AR_SREV_5416_20_OR_LATER(sc) &&
+ (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5))
+ offset = chainoffset[i];
+ else
+ offset = i * 0x1000;
+
+ if (sc->flags & ATHN_FLAG_OLPC) {
+ ar9280_2_0_olpc_get_pdadcs(sc, c, i, boundaries,
+ pdadcs, &txgain);
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_0);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+ AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_0, reg);
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_1);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+ AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_1, reg);
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, txgain);
+ AR_WRITE(sc, AR_PHY_TX_PWRCTRL7, reg);
+
+ overlap = 6;
+ } else {
+ ar5416_get_pdadcs(sc, c, i, nxpdgains, overlap,
+ boundaries, pdadcs);
+ }
+ /* Write boundaries. */
+ if (i == 0 || AR_SREV_5416_20_OR_LATER(sc)) {
+ reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP,
+ overlap);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1,
+ boundaries[0]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2,
+ boundaries[1]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3,
+ boundaries[2]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4,
+ boundaries[3]);
+ AR_WRITE(sc, AR_PHY_TPCRG5 + offset, reg);
+ }
+ /* Write PDADC values. */
+ for (j = 0; j < AR_NUM_PDADC_VALUES; j += 4) {
+ AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + offset + j,
+ pdadcs[j + 0] << 0 |
+ pdadcs[j + 1] << 8 |
+ pdadcs[j + 2] << 16 |
+ pdadcs[j + 3] << 24);
+ }
+ }
+}
+
+void
+ar5416_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ const struct ar5416_eeprom *eep = sc->eep;
+ const struct ar5416_modal_eep_header *modal;
+ uint8_t tpow_cck[4], tpow_ofdm[4];
+ uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
+ uint8_t tpow_ht20[8], tpow_ht40[8];
+ int16_t pwr, pwroff, max_ant_gain, power[ATHN_POWER_COUNT];
+ uint8_t cckinc, ht40inc;
+ int i;
+
+ ar5416_set_power_calib(sc, c);
+
+ modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
+
+ /* Compute transmit power reduction due to antenna gain. */
+ max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1]);
+ max_ant_gain = MAX(modal->antennaGainCh[2], max_ant_gain);
+ /* XXX */
+
+ /*
+ * Reduce scaled power by number of active chains to get per-chain
+ * transmit power level.
+ */
+ if (sc->ntxchains == 2)
+ pwr -= AR_PWR_DECREASE_FOR_2_CHAIN;
+ else if (sc->ntxchains == 3)
+ pwr -= AR_PWR_DECREASE_FOR_3_CHAIN;
+ if (pwr < 0)
+ pwr = 0;
+
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ /* Get CCK target powers. */
+ athn_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
+
+ /* Get OFDM target powers. */
+ athn_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
+
+#ifndef IEEE80211_NO_HT
+ /* Get HT-20 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_2GHT20,
+ eep->calTargetPower2GHT20, AR5416_NUM_2G_20_TARGET_POWERS,
+ tpow_ht20);
+
+ if (extc != NULL) {
+ /* Get HT-40 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_2GHT40,
+ eep->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS, tpow_ht40);
+
+ /* Get secondary channel CCK target powers. */
+ athn_get_lg_tpow(sc, extc, AR_CTL_11B,
+ eep->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck_ext);
+
+ /* Get secondary channel OFDM target powers. */
+ athn_get_lg_tpow(sc, extc, AR_CTL_11G,
+ eep->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm_ext);
+ }
+#endif
+ } else {
+ /* Get OFDM target powers. */
+ athn_get_lg_tpow(sc, c, AR_CTL_11A, eep->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm);
+
+#ifndef IEEE80211_NO_HT
+ /* Get HT-20 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_5GHT20,
+ eep->calTargetPower5GHT20, AR5416_NUM_5G_20_TARGET_POWERS,
+ tpow_ht20);
+
+ if (extc != NULL) {
+ /* Get HT-40 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_5GHT40,
+ eep->calTargetPower5GHT40,
+ AR5416_NUM_5G_40_TARGET_POWERS, tpow_ht40);
+
+ /* Get secondary channel OFDM target powers. */
+ athn_get_lg_tpow(sc, extc, AR_CTL_11A,
+ eep->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm_ext);
+ }
+#endif
+ }
+
+ /* Compute CCK/OFDM delta. */
+ cckinc = (sc->flags & ATHN_FLAG_OLPC) ? -2 : 0;
+
+ memset(power, 0, sizeof power);
+ /* Shuffle target powers accross transmit rates. */
+ power[ATHN_POWER_OFDM6 ] =
+ power[ATHN_POWER_OFDM9 ] =
+ power[ATHN_POWER_OFDM12] =
+ power[ATHN_POWER_OFDM18] =
+ power[ATHN_POWER_OFDM24] = tpow_ofdm[0];
+ power[ATHN_POWER_OFDM36] = tpow_ofdm[1];
+ power[ATHN_POWER_OFDM48] = tpow_ofdm[2];
+ power[ATHN_POWER_OFDM54] = tpow_ofdm[3];
+ power[ATHN_POWER_XR ] = tpow_ofdm[0];
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ power[ATHN_POWER_CCK1_LP ] = tpow_cck[0] + cckinc;
+ power[ATHN_POWER_CCK2_LP ] =
+ power[ATHN_POWER_CCK2_SP ] = tpow_cck[1] + cckinc;
+ power[ATHN_POWER_CCK55_LP] =
+ power[ATHN_POWER_CCK55_SP] = tpow_cck[2] + cckinc;
+ power[ATHN_POWER_CCK11_LP] =
+ power[ATHN_POWER_CCK11_SP] = tpow_cck[3] + cckinc;
+ }
+#ifndef IEEE80211_NO_HT
+ for (i = 0; i < nitems(tpow_ht20); i++)
+ power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
+ if (extc != NULL) {
+ /* Correct PAR difference between HT40 and HT20/Legacy. */
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2)
+ ht40inc = modal->ht40PowerIncForPdadc;
+ else
+ ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
+ for (i = 0; i < nitems(tpow_ht40); i++)
+ power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
+ power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
+ power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0] + cckinc;
+ power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ power[ATHN_POWER_CCK_EXT] = tpow_cck_ext[0] + cckinc;
+ }
+#endif
+
+ if (AR_SREV_9280_10_OR_LATER(sc)) {
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_21)
+ pwroff = eep->baseEepHeader.pwrTableOffset;
+ else
+ pwroff = AR_PWR_TABLE_OFFSET_DB;
+ for (i = 0; i < ATHN_POWER_COUNT; i++)
+ power[i] -= pwroff * 2; /* In half dB. */
+ }
+ for (i = 0; i < ATHN_POWER_COUNT; i++) {
+ if (power[i] > AR_MAX_RATE_POWER)
+ power[i] = AR_MAX_RATE_POWER;
+ }
+
+ /* Write transmit power values to hardware. */
+ athn_write_txpower(sc, power);
+
+ /*
+ * Write transmit power substraction for dynamic chain changing
+ * and per-packet transmit power.
+ */
+ AR_WRITE(sc, AR_PHY_POWER_TX_SUB,
+ (modal->pwrDecreaseFor3Chain & 0x3f) << 6 |
+ (modal->pwrDecreaseFor2Chain & 0x3f));
+}
+
+void
+ar5416_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ const struct ar_spur_chan *spurchans;
+ int i, spur, bin, spur_delta_phase, spur_freq_sd;
+
+ spurchans = sc->ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ spur = spurchans[i].spurChan;
+ if (spur == AR_NO_SPUR)
+ return; /* XXX disable if it was enabled! */
+ spur -= c->ic_freq * 10;
+ /* Verify range +/-9.5MHz */
+ if (abs(spur) < 95)
+ break;
+ }
+ if (i == AR_EEPROM_MODAL_SPURS)
+ return; /* XXX disable if it was enabled! */
+ DPRINTF(("enabling spur mitigation\n"));
+
+ AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+ AR_WRITE(sc, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
+
+ spur_delta_phase = (spur * 524288) / 100;
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ spur_freq_sd = (spur * 2048) / 440;
+ else
+ spur_freq_sd = (spur * 2048) / 400;
+
+ AR_WRITE(sc, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
+ SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
+
+ bin = spur * 32;
+ athn_set_viterbi_mask(sc, bin);
+}
+
+/*
+ * Replace bits "off" to "off+nbits-1" in column "col" with the specified
+ * value.
+ */
+void
+ar5416_rw_rfbits(uint32_t *buf, int col, int off, uint32_t val, int nbits)
+{
+ int idx, bit;
+
+ KASSERT(off >= 1 && col < 4 && nbits <= 32);
+
+ off--; /* Starts at 1. */
+ while (nbits-- > 0) {
+ idx = off / 8;
+ bit = off % 8;
+ buf[idx] &= ~(1 << (bit + col * 8));
+ buf[idx] |= ((val >> nbits) & 1) << (bit + col * 8);
+ off++;
+ }
+}
+
+/*
+ * Overwrite db and ob based on ROM settings.
+ */
+void
+ar5416_rw_bank6tpc(struct athn_softc *sc, struct ieee80211_channel *c,
+ uint32_t *rwbank6tpc)
+{
+ const struct ar5416_eeprom *eep = sc->eep;
+ const struct ar5416_modal_eep_header *modal;
+
+ if (IEEE80211_IS_CHAN_5GHZ(c)) {
+ modal = &eep->modalHeader[0];
+ /* 5GHz db in column 0, bits [200-202] */
+ ar5416_rw_rfbits(rwbank6tpc, 0, 200, modal->db, 3);
+ /* 5GHz ob in column 0, bits [203-205]. */
+ ar5416_rw_rfbits(rwbank6tpc, 0, 203, modal->ob, 3);
+ } else {
+ modal = &eep->modalHeader[1];
+ /* 2GHz db in column 0, bits [194-196] */
+ ar5416_rw_rfbits(rwbank6tpc, 0, 194, modal->db, 3);
+ /* 2GHz ob in column 0, bits [197-199]. */
+ ar5416_rw_rfbits(rwbank6tpc, 0, 197, modal->ob, 3);
+ }
+}
+
+/*
+ * Program analog RF.
+ */
+void
+ar5416_rf_reset(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ const uint32_t *bank6tpc;
+ int i;
+
+ /* Bank 0. */
+ AR_WRITE(sc, 0x98b0, 0x1e5795e5);
+ AR_WRITE(sc, 0x98e0, 0x02008020);
+
+ /* Bank 1. */
+ AR_WRITE(sc, 0x98b0, 0x02108421);
+ AR_WRITE(sc, 0x98ec, 0x00000008);
+
+ /* Bank 2. */
+ AR_WRITE(sc, 0x98b0, 0x0e73ff17);
+ AR_WRITE(sc, 0x98e0, 0x00000420);
+
+ /* Bank 3. */
+ if (IEEE80211_IS_CHAN_5GHZ(c))
+ AR_WRITE(sc, 0x98f0, 0x01400018);
+ else
+ AR_WRITE(sc, 0x98f0, 0x01c00018);
+
+ /* Select the Bank 6 TPC values to use. */
+ if (AR_SREV_9160_10_OR_LATER(sc))
+ bank6tpc = ar9160_bank6tpc_vals;
+ else
+ bank6tpc = ar5416_bank6tpc_vals;
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
+ uint32_t *rwbank6tpc = sc->rwbuf;
+
+ /* Copy values from .rodata to writable buffer. */
+ memcpy(rwbank6tpc, bank6tpc, 32 * sizeof (uint32_t));
+ ar5416_rw_bank6tpc(sc, c, rwbank6tpc);
+ bank6tpc = rwbank6tpc;
+ }
+ /* Bank 6 TPC. */
+ for (i = 0; i < 32; i++)
+ AR_WRITE(sc, 0x989c, bank6tpc[i]);
+ if (IEEE80211_IS_CHAN_5GHZ(c))
+ AR_WRITE(sc, 0x98d0, 0x0000000f);
+ else
+ AR_WRITE(sc, 0x98d0, 0x0010000f);
+
+ /* Bank 7. */
+ AR_WRITE(sc, 0x989c, 0x00000500);
+ AR_WRITE(sc, 0x989c, 0x00000800);
+ AR_WRITE(sc, 0x98cc, 0x0000000e);
+}
+
+void
+ar5416_reset_bb_gain(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ const uint32_t *pvals;
+ int i;
+
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ pvals = ar5416_bb_rfgain_vals_2g;
+ else
+ pvals = ar5416_bb_rfgain_vals_5g;
+ for (i = 0; i < 64; i++)
+ AR_WRITE(sc, AR_PHY_BB_RFGAIN(i), pvals[i]);
+}
+
+/*
+ * Fix orientation sensitivity issue on AR5416/2GHz by increasing
+ * rf_pwd_icsyndiv.
+ */
+void
+ar5416_force_bias(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ uint32_t *rwbank6 = sc->rwbuf;
+ uint8_t bias;
+ int i;
+
+ KASSERT(IEEE80211_IS_CHAN_2GHZ(c));
+
+ /* Copy values from .rodata to writable buffer. */
+ memcpy(rwbank6, ar5416_bank6_vals, sizeof ar5416_bank6_vals);
+
+ if (c->ic_freq < 2412)
+ bias = 0;
+ else if (c->ic_freq < 2422)
+ bias = 1;
+ else
+ bias = 2;
+ athn_reverse_bits(bias, 3);
+
+ /* Overwrite "rf_pwd_icsyndiv" (column 3, bits [181-183].) */
+ ar5416_rw_rfbits(rwbank6, 3, 181, bias, 3);
+
+ /* Write Bank 6. */
+ for (i = 0; i < 32; i++)
+ AR_WRITE(sc, 0x989c, rwbank6[i]);
+ AR_WRITE(sc, 0x98d0, 0x0010000f);
+}
+
+/*
+ * Overwrite XPA bias level based on ROM setting.
+ */
+void
+ar9160_rw_addac(struct athn_softc *sc, struct ieee80211_channel *c,
+ uint32_t *addac)
+{
+ struct ar5416_eeprom *eep = sc->eep;
+ struct ar5416_modal_eep_header *modal;
+ uint8_t fbin, bias;
+ int i;
+
+ /* XXX xpaBiasLvlFreq values have not been endian-swapped? */
+
+ /* Get the XPA bias level to use for the specified channel. */
+ modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
+ if (modal->xpaBiasLvl == 0xff) {
+ bias = modal->xpaBiasLvlFreq[0] >> 14;
+ fbin = athn_chan2fbin(c);
+ for (i = 1; i < 3; i++) {
+ if (modal->xpaBiasLvlFreq[i] == 0)
+ break;
+ if ((modal->xpaBiasLvlFreq[i] & 0xff) < fbin)
+ break;
+ bias = modal->xpaBiasLvlFreq[i] >> 14;
+ }
+ } else
+ bias = modal->xpaBiasLvl & 0x3;
+
+ bias = athn_reverse_bits(bias, 2); /* Put in host bit-order. */
+ DPRINTF(("bias level=%d\n", bias));
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ ar5416_rw_rfbits(addac, 0, 60, bias, 2);
+ else
+ ar5416_rw_rfbits(addac, 0, 55, bias, 2);
+}
+
+void
+ar5416_reset_addac(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ const struct athn_addac *addac = sc->addac;
+ const uint32_t *pvals;
+ int i;
+
+ if (AR_SREV_9160(sc) && sc->eep_rev >= AR_EEP_MINOR_VER_7) {
+ uint32_t *rwaddac = sc->rwbuf;
+
+ /* Copy values from .rodata to writable buffer. */
+ memcpy(rwaddac, addac->vals, addac->nvals * sizeof (uint32_t));
+ ar9160_rw_addac(sc, c, rwaddac);
+ pvals = rwaddac;
+ } else
+ pvals = addac->vals;
+ for (i = 0; i < addac->nvals; i++)
+ AR_WRITE(sc, 0x989c, pvals[i]);
+ AR_WRITE(sc, 0x98cc, 0); /* Finalize. */
+}
diff --git a/sys/dev/ic/ar5416reg.h b/sys/dev/ic/ar5416reg.h
new file mode 100644
index 00000000000..bc6cd868055
--- /dev/null
+++ b/sys/dev/ic/ar5416reg.h
@@ -0,0 +1,829 @@
+/* $OpenBSD: ar5416reg.h,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define AR5416_MAX_CHAINS 3
+
+#define AR5416_PHY_CCA_MAX_GOOD_VALUE ( -85)
+
+/* Bits for AR_PHY(0x37). */
+#define AR5416_BMODE_SYNTH 0x00000002
+#define AR5416_AMODE_REFSEL_M 0x0000000c
+#define AR5416_AMODE_REFSEL_S 2
+
+/*
+ * ROM layout used by AR5416, AR9160 and AR9280.
+ */
+#define AR5416_EEP_START_LOC 256
+#define AR5416_NUM_5G_CAL_PIERS 8
+#define AR5416_NUM_2G_CAL_PIERS 4
+#define AR5416_NUM_5G_20_TARGET_POWERS 8
+#define AR5416_NUM_5G_40_TARGET_POWERS 8
+#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_NUM_2G_20_TARGET_POWERS 4
+#define AR5416_NUM_2G_40_TARGET_POWERS 4
+#define AR5416_NUM_CTLS 24
+#define AR5416_NUM_BAND_EDGES 8
+#define AR5416_NUM_PD_GAINS 4
+#define AR5416_PD_GAINS_IN_MASK 4
+#define AR5416_PD_GAIN_ICEPTS 5
+
+struct ar5416_base_eep_header {
+ uint16_t length;
+ uint16_t checksum;
+ uint16_t version;
+ uint8_t opCapFlags;
+ uint8_t eepMisc;
+ uint16_t regDmn[2];
+ uint8_t macAddr[6];
+ uint8_t rxMask;
+ uint8_t txMask;
+ uint16_t rfSilent;
+ uint16_t blueToothOptions;
+ uint16_t deviceCap;
+ uint32_t binBuildNumber;
+ uint8_t deviceType;
+ /* End of common header. */
+ uint8_t pwdclkind;
+ uint8_t futureBase_1[2];
+ uint8_t rxGainType;
+#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
+#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
+#define AR5416_EEP_RXGAIN_ORIG 2
+
+ uint8_t dacHiPwrMode_5G;
+ uint8_t openLoopPwrCntl;
+ uint8_t dacLpMode;
+ uint8_t txGainType;
+ uint8_t rcChainMask;
+ uint8_t desiredScaleCCK;
+ uint8_t pwrTableOffset;
+ uint8_t frac_n_5g;
+ uint8_t futureBase_2[21];
+} __packed;
+
+struct ar5416_modal_eep_header {
+ uint32_t antCtrlChain[AR5416_MAX_CHAINS];
+ uint32_t antCtrlCommon;
+ uint8_t antennaGainCh[AR5416_MAX_CHAINS];
+ uint8_t switchSettling;
+ uint8_t txRxAttenCh[AR5416_MAX_CHAINS];
+ uint8_t rxTxMarginCh[AR5416_MAX_CHAINS];
+ uint8_t adcDesiredSize;
+ uint8_t pgaDesiredSize;
+ uint8_t xlnaGainCh[AR5416_MAX_CHAINS];
+ uint8_t txEndToXpaOff;
+ uint8_t txEndToRxOn;
+ uint8_t txFrameToXpaOn;
+ uint8_t thresh62;
+ uint8_t noiseFloorThreshCh[AR5416_MAX_CHAINS];
+ uint8_t xpdGain;
+ uint8_t xpd;
+ uint8_t iqCalICh[AR5416_MAX_CHAINS];
+ uint8_t iqCalQCh[AR5416_MAX_CHAINS];
+ uint8_t pdGainOverlap;
+ uint8_t ob;
+ uint8_t db;
+ uint8_t xpaBiasLvl;
+ uint8_t pwrDecreaseFor2Chain;
+ uint8_t pwrDecreaseFor3Chain;
+ uint8_t txFrameToDataStart;
+ uint8_t txFrameToPaOn;
+ uint8_t ht40PowerIncForPdadc;
+ uint8_t bswAtten[AR5416_MAX_CHAINS];
+ uint8_t bswMargin[AR5416_MAX_CHAINS];
+ uint8_t swSettleHt40;
+ uint8_t xatten2Db[AR5416_MAX_CHAINS];
+ uint8_t xatten2Margin[AR5416_MAX_CHAINS];
+ uint8_t ob_ch1;
+ uint8_t db_ch1;
+ uint8_t flagBits;
+#define AR5416_EEP_FLAG_USEANT1 0x01
+#define AR5416_EEP_FLAG_FORCEXPAON 0x02
+#define AR5416_EEP_FLAG_LOCALBIAS 0x04
+#define AR5416_EEP_FLAG_FEMBANDSELECT 0x08
+#define AR5416_EEP_FLAG_XLNABUFIN 0x10
+#define AR5416_EEP_FLAG_XLNAISEL_M 0x60
+#define AR5416_EEP_FLAG_XLNAISEL_S 5
+#define AR5416_EEP_FLAG_XLNABUFMODE 0x80
+
+ uint8_t miscBits;
+#define AR5416_EEP_MISC_TX_DAC_SCALE_CCK_M 0x03
+#define AR5416_EEP_MISC_TX_DAC_SCALE_CCK_S 0
+#define AR5416_EEP_MISC_TX_CLIP_M 0xfc
+#define AR5416_EEP_MISC_TX_CLIP_S 2
+
+ uint16_t xpaBiasLvlFreq[3];
+ uint8_t futureModal[6];
+ struct ar_spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __packed;
+
+struct ar5416_cal_data_per_freq {
+ uint8_t pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+ uint8_t vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __packed;
+
+struct ar5416_cal_ctl_data {
+ struct ar_cal_ctl_edges
+ ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __packed;
+
+struct ar5416_eeprom {
+ struct ar5416_base_eep_header baseEepHeader;
+ uint8_t custData[64];
+ struct ar5416_modal_eep_header modalHeader[2];
+ uint8_t calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
+ uint8_t calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
+ struct ar5416_cal_data_per_freq
+ calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
+ struct ar5416_cal_data_per_freq
+ calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+ struct ar_cal_target_power_leg
+ calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
+ struct ar_cal_target_power_leg
+ calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
+ struct ar_cal_target_power_leg
+ calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
+ uint8_t ctlIndex[AR5416_NUM_CTLS];
+ struct ar5416_cal_ctl_data ctlData[AR5416_NUM_CTLS];
+ uint8_t padding;
+} __packed;
+
+/* Macro to "pack" registers to 16-bit to save some .rodata space. */
+#define P(x) (x)
+
+/*
+ * AR5416 initialization values.
+ */
+static const uint16_t ar5416_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x08120), P(0x081d0), P(0x09804), P(0x09820),
+ P(0x09824), P(0x09828), P(0x09834), P(0x09838), P(0x09844),
+ P(0x09848), P(0x0a848), P(0x0b848), P(0x09850), P(0x09858),
+ P(0x0985c), P(0x09860), P(0x09864), P(0x09868), P(0x0986c),
+ P(0x09914), P(0x09918), P(0x09924), P(0x09944), P(0x09960),
+ P(0x0a960), P(0x0b960), P(0x09964), P(0x099bc), P(0x099c0),
+ P(0x099c4), P(0x099c8), P(0x099cc), P(0x099d0), P(0x099d4),
+ P(0x099d8), P(0x0a204), P(0x0a208), P(0x0a20c), P(0x0b20c),
+ P(0x0c20c), P(0x0a21c), P(0x0a230), P(0x0a274), P(0x0a300),
+ P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310), P(0x0a314),
+ P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324), P(0x0a328),
+ P(0x0a32c), P(0x0a330), P(0x0a334)
+};
+
+static const uint32_t ar5416_vals_5g20[] = {
+ 0x00000230, 0x00000168, 0x00000e60, 0x0000a000, 0x03e803e8,
+ 0x128d93a7, 0x08f04800, 0x00003210, 0x00000300, 0x02020200,
+ 0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x1372161e,
+ 0x001a6a65, 0x001a6a65, 0x001a6a65, 0x6c48b4e0, 0x7ec82d2e,
+ 0x31395d5e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
+ 0x000007d0, 0x000001b8, 0xd0058a0b, 0xffb81020, 0x00000900,
+ 0x00000900, 0x00000900, 0x00000000, 0x001a0a00, 0x038919be,
+ 0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000880, 0xd6be4788, 0x002ec1e0, 0x002ec1e0,
+ 0x002ec1e0, 0x1883800a, 0x00000000, 0x0a1a9caa, 0x18010000,
+ 0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b,
+ 0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbd07, 0x0000d7bf,
+ 0x00000000, 0x00000000, 0x00000000
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar5416_vals_5g40[] = {
+ 0x00000460, 0x000002d0, 0x00001cc0, 0x00014000, 0x07d007d0,
+ 0x128d93cf, 0x08f04800, 0x00003210, 0x000003c4, 0x02020200,
+ 0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x1372161e,
+ 0x001a6a65, 0x001a6a65, 0x001a6a65, 0x6d48b4e0, 0x7ec82d2e,
+ 0x3139605e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
+ 0x00000fa0, 0x00000370, 0xd0058a0b, 0xffb81020, 0x00000900,
+ 0x00000900, 0x00000900, 0x00000000, 0x001a0a00, 0x038919be,
+ 0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000880, 0xd6be4788, 0x002ec1e0, 0x002ec1e0,
+ 0x002ec1e0, 0x1883800a, 0x00000000, 0x0a1a9caa, 0x18010000,
+ 0x30032602, 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b,
+ 0x8c5b7e5a, 0x9d0f96cf, 0xb51fa69f, 0xcb3fbcbf, 0x0000d7bf,
+ 0x00000000, 0x00000000, 0x00000000
+};
+
+static const uint32_t ar5416_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00016000, 0x10801600,
+ 0x12e013d7, 0x08f04810, 0x0000320a, 0x000003c4, 0x02020200,
+ 0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x137216a0,
+ 0x00197a68, 0x00197a68, 0x00197a68, 0x6d48b0de, 0x7ec82d2e,
+ 0x3139605e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
+ 0x00001130, 0x00000268, 0xd0058a0b, 0xffb81020, 0x00012d80,
+ 0x00012d80, 0x00012d80, 0x00001120, 0x001a0a00, 0x038919be,
+ 0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000880, 0xd03e4788, 0x002ac120, 0x002ac120,
+ 0x002ac120, 0x1883800a, 0x00000210, 0x0a1a7caa, 0x18010000,
+ 0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a,
+ 0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000
+};
+#endif
+
+static const uint32_t ar5416_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x0000b000, 0x08400b00,
+ 0x12e013ab, 0x08f04810, 0x0000320a, 0x00000300, 0x02020200,
+ 0x00000e0e, 0x0a020001, 0x00000e0e, 0x00000007, 0x137216a0,
+ 0x00197a68, 0x00197a68, 0x00197a68, 0x6c48b0de, 0x7ec82d2e,
+ 0x31395d5e, 0x00049d18, 0x0001ce00, 0x409a4190, 0x050cb081,
+ 0x00000898, 0x00000134, 0xd0058a0b, 0xffb81020, 0x00012d80,
+ 0x00012d80, 0x00012d80, 0x00001120, 0x001a0a00, 0x038919be,
+ 0x06336f77, 0x6af6532c, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000880, 0xd03e4788, 0x002ac120, 0x002ac120,
+ 0x002ac120, 0x1883800a, 0x00000108, 0x0a1a7caa, 0x18010000,
+ 0x2e032402, 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a,
+ 0x950f8ccf, 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000
+};
+
+static const uint16_t ar5416_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x07010), P(0x07038),
+ P(0x08004), P(0x08008), P(0x0800c), P(0x08018), P(0x08020),
+ P(0x08038), P(0x0803c), P(0x08048), P(0x08054), P(0x08058),
+ P(0x0805c), P(0x08060), P(0x08064), P(0x080c0), P(0x080c4),
+ P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
+ P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
+ P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
+ P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
+ P(0x08124), P(0x08128), P(0x0812c), P(0x08130), P(0x08134),
+ P(0x08138), P(0x0813c), P(0x08144), P(0x08168), P(0x0816c),
+ P(0x08170), P(0x08174), P(0x08178), P(0x0817c), P(0x081c4),
+ P(0x081ec), P(0x081f0), P(0x081f4), P(0x081f8), P(0x081fc),
+ P(0x08200), P(0x08204), P(0x08208), P(0x0820c), P(0x08210),
+ P(0x08214), P(0x08218), P(0x0821c), P(0x08220), P(0x08224),
+ P(0x08228), P(0x0822c), P(0x08230), P(0x08234), P(0x08238),
+ P(0x0823c), P(0x08240), P(0x08244), P(0x08248), P(0x0824c),
+ P(0x08250), P(0x08254), P(0x08258), P(0x0825c), P(0x08260),
+ P(0x08264), P(0x08270), P(0x08274), P(0x08278), P(0x0827c),
+ P(0x08284), P(0x08288), P(0x0828c), P(0x08294), P(0x08298),
+ P(0x08300), P(0x08304), P(0x08308), P(0x0830c), P(0x08310),
+ P(0x08314), P(0x08318), P(0x08328), P(0x0832c), P(0x08330),
+ P(0x08334), P(0x08338), P(0x0833c), P(0x08340), P(0x09808),
+ P(0x0980c), P(0x09810), P(0x09814), P(0x0981c), P(0x0982c),
+ P(0x09830), P(0x0983c), P(0x09840), P(0x0984c), P(0x09854),
+ P(0x09900), P(0x09904), P(0x09908), P(0x0990c), P(0x0991c),
+ P(0x09920), P(0x0a920), P(0x0b920), P(0x09928), P(0x0992c),
+ P(0x09934), P(0x09938), P(0x0993c), P(0x09948), P(0x0994c),
+ P(0x09954), P(0x09958), P(0x0c95c), P(0x0c968), P(0x09970),
+ P(0x09974), P(0x09978), P(0x0997c), P(0x09980), P(0x09984),
+ P(0x09988), P(0x0998c), P(0x09990), P(0x09994), P(0x09998),
+ P(0x0999c), P(0x099a0), P(0x099a4), P(0x099a8), P(0x099ac),
+ P(0x099b0), P(0x099dc), P(0x099e0), P(0x099e4), P(0x099e8),
+ P(0x099ec), P(0x099fc), P(0x09b00), P(0x09b04), P(0x09b08),
+ P(0x09b0c), P(0x09b10), P(0x09b14), P(0x09b18), P(0x09b1c),
+ P(0x09b20), P(0x09b24), P(0x09b28), P(0x09b2c), P(0x09b30),
+ P(0x09b34), P(0x09b38), P(0x09b3c), P(0x09b40), P(0x09b44),
+ P(0x09b48), P(0x09b4c), P(0x09b50), P(0x09b54), P(0x09b58),
+ P(0x09b5c), P(0x09b60), P(0x09b64), P(0x09b68), P(0x09b6c),
+ P(0x09b70), P(0x09b74), P(0x09b78), P(0x09b7c), P(0x09b80),
+ P(0x09b84), P(0x09b88), P(0x09b8c), P(0x09b90), P(0x09b94),
+ P(0x09b98), P(0x09b9c), P(0x09ba0), P(0x09ba4), P(0x09ba8),
+ P(0x09bac), P(0x09bb0), P(0x09bb4), P(0x09bb8), P(0x09bbc),
+ P(0x09bc0), P(0x09bc4), P(0x09bc8), P(0x09bcc), P(0x09bd0),
+ P(0x09bd4), P(0x09bd8), P(0x09bdc), P(0x09be0), P(0x09be4),
+ P(0x09be8), P(0x09bec), P(0x09bf0), P(0x09bf4), P(0x09bf8),
+ P(0x09bfc), P(0x0a210), P(0x0a214), P(0x0a218), P(0x0a220),
+ P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234), P(0x0a238),
+ P(0x0a23c), P(0x0a240), P(0x0a244), P(0x0a248), P(0x0a24c),
+ P(0x0a250), P(0x0a254), P(0x0a258), P(0x0a25c), P(0x0a260),
+ P(0x0a268), P(0x0a26c), P(0x0b26c), P(0x0c26c), P(0x0d270),
+ P(0x0a278), P(0x0a27c), P(0x0a338), P(0x0a33c), P(0x0a340),
+ P(0x0a344), P(0x0a348), P(0x0a34c), P(0x0a350), P(0x0a354),
+ P(0x0a358), P(0x0d35c), P(0x0d360), P(0x0d364), P(0x0d368),
+ P(0x0d36c), P(0x0d370), P(0x0d374), P(0x0d378), P(0x0d37c),
+ P(0x0d380), P(0x0d384), P(0x0a388), P(0x0a38c), P(0x0a390),
+ P(0x0a394), P(0x0a398), P(0x0a39c), P(0x0a3a0), P(0x0a3a4),
+ P(0x0a3a8), P(0x0a3ac), P(0x0a3b0), P(0x0a3b4), P(0x0a3b8),
+ P(0x0a3bc), P(0x0a3c0), P(0x0a3c4), P(0x0a3c8), P(0x0a3cc),
+ P(0x0a3d0), P(0x0a3d4), P(0x0a3dc), P(0x0a3e0)
+};
+
+static const uint32_t ar5416_cm_vals[] = {
+ 0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x000004c2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000,
+ 0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000,
+ 0x000fc78f, 0x0000000f, 0x00000000, 0x2a82301a, 0x05dc01e0,
+ 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
+ 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
+ 0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
+ 0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00100000, 0x0010f400, 0x00000100, 0x0001e800,
+ 0x00000000, 0x00000000, 0x00000000, 0x400000ff, 0x00080922,
+ 0xa8000010, 0x00000000, 0x40000000, 0x003e4180, 0x00000000,
+ 0x0000002c, 0x0000002c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x00000302,
+ 0x00000e00, 0x00070000, 0x00000000, 0x000107ff, 0x00000000,
+ 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000,
+ 0x00000000, 0x00200400, 0x206a002e, 0x1284233c, 0x00000859,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000fff,
+ 0x05100000, 0x05100000, 0x05100000, 0x00000001, 0x00000004,
+ 0x1e1f2022, 0x0a0b0c0d, 0x00000000, 0x9280b212, 0x00020028,
+ 0x5d50e188, 0x00081fff, 0x004b6a8e, 0x000003ce, 0x190fb515,
+ 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000001, 0x001fff00, 0x00000000,
+ 0x03051000, 0x00000000, 0x00000200, 0xaaaaaaaa, 0x3c466478,
+ 0x000000aa, 0x00001042, 0x00000000, 0x00000001, 0x00000002,
+ 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
+ 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, 0x00000010,
+ 0x00000011, 0x00000012, 0x00000013, 0x00000014, 0x00000015,
+ 0x00000018, 0x00000019, 0x0000001a, 0x0000001b, 0x0000001c,
+ 0x0000001d, 0x00000020, 0x00000021, 0x00000022, 0x00000023,
+ 0x00000024, 0x00000025, 0x00000028, 0x00000029, 0x0000002a,
+ 0x0000002b, 0x0000002c, 0x0000002d, 0x00000030, 0x00000031,
+ 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000010,
+ 0x0000001a, 0x40806333, 0x00106c10, 0x009c4060, 0x018830c6,
+ 0x00000400, 0x00000bb5, 0x00000011, 0x20202020, 0x20202020,
+ 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000001,
+ 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01, 0xdfa91f01,
+ 0x00000000, 0x0e79e5c6, 0x0e79e5c6, 0x0e79e5c6, 0x00820820,
+ 0x1ce739ce, 0x051701ce, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff,
+ 0x79a8aa1f, 0x07ffffef, 0x0fffffe7, 0x17ffffe5, 0x1fffffe4,
+ 0x37ffffe3, 0x3fffffe3, 0x57ffffe3, 0x5fffffe2, 0x7fffffe2,
+ 0x7f3c7bba, 0xf3307ff0, 0x08000000, 0x20202020, 0x20202020,
+ 0x1ce739ce, 0x000001ce, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000246, 0x20202020,
+ 0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce
+};
+
+static const struct athn_ini ar5416_ini = {
+ nitems(ar5416_regs),
+ ar5416_regs,
+ ar5416_vals_5g20,
+#ifndef IEEE80211_NO_HT
+ ar5416_vals_5g40,
+ ar5416_vals_2g40,
+#endif
+ ar5416_vals_2g20,
+ nitems(ar5416_cm_regs),
+ ar5416_cm_regs,
+ ar5416_cm_vals
+};
+
+/*
+ * AR9160 initialization values.
+ */
+static const uint16_t ar9160_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x09804), P(0x09820), P(0x09824), P(0x09828),
+ P(0x09834), P(0x09838), P(0x09844), P(0x09848), P(0x0a848),
+ P(0x0b848), P(0x09850), P(0x09858), P(0x0985c), P(0x09860),
+ P(0x0c864), P(0x09868), P(0x0986c), P(0x09914), P(0x09918),
+ P(0x09924), P(0x09944), P(0x09960), P(0x0a960), P(0x0b960),
+ P(0x09964), P(0x0c968), P(0x0c9bc), P(0x099c0), P(0x099c4),
+ P(0x099c8), P(0x099cc), P(0x099d0), P(0x099d4), P(0x099d8),
+ P(0x0a204), P(0x0a208), P(0x0a20c), P(0x0b20c), P(0x0c20c),
+ P(0x0a21c), P(0x0a230), P(0x0a274), P(0x0a300), P(0x0a304),
+ P(0x0a308), P(0x0a30c), P(0x0a310), P(0x0a314), P(0x0a318),
+ P(0x0a31c), P(0x0a320), P(0x0a324), P(0x0a328), P(0x0a32c),
+ P(0x0a330), P(0x0a334)
+};
+
+static const uint32_t ar9160_vals_5g20[] = {
+ 0x00000230, 0x00000168, 0x00000e60, 0x0000a000, 0x03e803e8,
+ 0x128d93a7, 0x00000300, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x0372161e, 0x001a6a65, 0x001a6a65,
+ 0x001a6a65, 0x6c48b4e2, 0x7ec82d2e, 0x31395d5e, 0x00048d18,
+ 0x0001ce00, 0x409a40d0, 0x050cb081, 0x000007d0, 0x0000000a,
+ 0xd00a8a07, 0xffb81020, 0x00009b40, 0x00009b40, 0x00009b40,
+ 0x00001120, 0x000003b5, 0x001a0600, 0x038919be, 0x06336f77,
+ 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000,
+ 0x00000880, 0xd6be4788, 0x002fc160, 0x002fc160, 0x002fc160,
+ 0x1883800a, 0x00000000, 0x0a1a9caa, 0x18010000, 0x30032602,
+ 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a,
+ 0x9d0f96cf, 0xb51fa69f, 0xcb3fbd07, 0x0000d7bf, 0x00000000,
+ 0x00000000, 0x00000000
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar9160_vals_5g40[] = {
+ 0x00000460, 0x000002d0, 0x00001cc0, 0x00014000, 0x07d007d0,
+ 0x128d93cf, 0x000003c4, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x0372161e, 0x001a6a65, 0x001a6a65,
+ 0x001a6a65, 0x6c48b4e2, 0x7ec82d2e, 0x31395d5e, 0x00048d18,
+ 0x0001ce00, 0x409a40d0, 0x050cb081, 0x00000fa0, 0x00000014,
+ 0xd00a8a07, 0xffb81020, 0x00009b40, 0x00009b40, 0x00009b40,
+ 0x00001120, 0x000003b5, 0x001a0600, 0x038919be, 0x06336f77,
+ 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000,
+ 0x00000880, 0xd6be4788, 0x002fc160, 0x002fc160, 0x002fc160,
+ 0x1883800a, 0x00000000, 0x0a1a9caa, 0x18010000, 0x30032602,
+ 0x48073e06, 0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a,
+ 0x9d0f96cf, 0xb51fa69f, 0xcb3fbcbf, 0x0000d7bf, 0x00000000,
+ 0x00000000, 0x00000000
+};
+
+static const uint32_t ar9160_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00016000, 0x10801600,
+ 0x12e013d7, 0x000003c4, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x037216a0, 0x00197a68, 0x00197a68,
+ 0x00197a68, 0x6c48b0e2, 0x7ec82d2e, 0x31395d5e, 0x00048d20,
+ 0x0001ce00, 0x409a40d0, 0x050cb081, 0x00001130, 0x00000016,
+ 0xd00a8a0d, 0xffb81020, 0x00009b40, 0x00009b40, 0x00009b40,
+ 0x00001120, 0x000003ce, 0x001a0c00, 0x038919be, 0x06336f77,
+ 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000,
+ 0x00000880, 0xd03e4788, 0x002ac120, 0x002ac120, 0x002ac120,
+ 0x1883800a, 0x00000210, 0x0a1a7caa, 0x18010000, 0x2e032402,
+ 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf,
+ 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+};
+#endif
+
+static const uint32_t ar9160_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x0000b000, 0x08400b00,
+ 0x12e013ab, 0x00000300, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x037216a0, 0x00197a68, 0x00197a68,
+ 0x00197a68, 0x6c48b0e2, 0x7ec82d2e, 0x31395d5e, 0x00048d20,
+ 0x0001ce00, 0x409a40d0, 0x050cb081, 0x00000898, 0x0000000b,
+ 0xd00a8a0d, 0xffb81020, 0x00009b40, 0x00009b40, 0x00009b40,
+ 0x00001120, 0x000003ce, 0x001a0c00, 0x038919be, 0x06336f77,
+ 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000, 0x00000000,
+ 0x00000880, 0xd03e4788, 0x002ac120, 0x002ac120, 0x002ac120,
+ 0x1883800a, 0x00000108, 0x0a1a7caa, 0x18010000, 0x2e032402,
+ 0x4a0a3c06, 0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf,
+ 0xa5cf9b4f, 0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000
+};
+
+static const uint16_t ar9160_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x07010), P(0x07038),
+ P(0x08004), P(0x08008), P(0x0800c), P(0x08018), P(0x08020),
+ P(0x08038), P(0x0803c), P(0x08048), P(0x08054), P(0x08058),
+ P(0x0805c), P(0x08060), P(0x08064), P(0x080c0), P(0x080c4),
+ P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
+ P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
+ P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
+ P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
+ P(0x08120), P(0x08124), P(0x08128), P(0x0812c), P(0x08130),
+ P(0x08134), P(0x08138), P(0x0813c), P(0x08144), P(0x08168),
+ P(0x0816c), P(0x08170), P(0x08174), P(0x08178), P(0x0817c),
+ P(0x081c4), P(0x081d0), P(0x081ec), P(0x081f0), P(0x081f4),
+ P(0x081f8), P(0x081fc), P(0x08200), P(0x08204), P(0x08208),
+ P(0x0820c), P(0x08210), P(0x08214), P(0x08218), P(0x0821c),
+ P(0x08220), P(0x08224), P(0x08228), P(0x0822c), P(0x08230),
+ P(0x08234), P(0x08238), P(0x0823c), P(0x08240), P(0x08244),
+ P(0x08248), P(0x0824c), P(0x08250), P(0x08254), P(0x08258),
+ P(0x0825c), P(0x08260), P(0x08270), P(0x08274), P(0x08278),
+ P(0x0827c), P(0x08284), P(0x08288), P(0x0828c), P(0x08294),
+ P(0x08298), P(0x08300), P(0x08304), P(0x08308), P(0x0830c),
+ P(0x08310), P(0x08314), P(0x08318), P(0x08328), P(0x0832c),
+ P(0x08330), P(0x08334), P(0x08338), P(0x0833c), P(0x08340),
+ P(0x09808), P(0x0980c), P(0x09810), P(0x09814), P(0x0981c),
+ P(0x0982c), P(0x09830), P(0x0983c), P(0x09840), P(0x0984c),
+ P(0x09854), P(0x09900), P(0x09904), P(0x09908), P(0x0990c),
+ P(0x0991c), P(0x09920), P(0x0a920), P(0x0b920), P(0x09928),
+ P(0x0992c), P(0x09934), P(0x09938), P(0x0993c), P(0x09948),
+ P(0x0994c), P(0x09954), P(0x09958), P(0x09940), P(0x0c95c),
+ P(0x09970), P(0x09974), P(0x09978), P(0x0997c), P(0x09980),
+ P(0x09984), P(0x09988), P(0x0998c), P(0x09990), P(0x09994),
+ P(0x09998), P(0x0999c), P(0x099a0), P(0x099a4), P(0x099a8),
+ P(0x099ac), P(0x099b0), P(0x099dc), P(0x099e0), P(0x099e4),
+ P(0x099e8), P(0x099ec), P(0x099fc), P(0x09b00), P(0x09b04),
+ P(0x09b08), P(0x09b0c), P(0x09b10), P(0x09b14), P(0x09b18),
+ P(0x09b1c), P(0x09b20), P(0x09b24), P(0x09b28), P(0x09b2c),
+ P(0x09b30), P(0x09b34), P(0x09b38), P(0x09b3c), P(0x09b40),
+ P(0x09b44), P(0x09b48), P(0x09b4c), P(0x09b50), P(0x09b54),
+ P(0x09b58), P(0x09b5c), P(0x09b60), P(0x09b64), P(0x09b68),
+ P(0x09b6c), P(0x09b70), P(0x09b74), P(0x09b78), P(0x09b7c),
+ P(0x09b80), P(0x09b84), P(0x09b88), P(0x09b8c), P(0x09b90),
+ P(0x09b94), P(0x09b98), P(0x09b9c), P(0x09ba0), P(0x09ba4),
+ P(0x09ba8), P(0x09bac), P(0x09bb0), P(0x09bb4), P(0x09bb8),
+ P(0x09bbc), P(0x09bc0), P(0x09bc4), P(0x09bc8), P(0x09bcc),
+ P(0x09bd0), P(0x09bd4), P(0x09bd8), P(0x09bdc), P(0x09be0),
+ P(0x09be4), P(0x09be8), P(0x09bec), P(0x09bf0), P(0x09bf4),
+ P(0x09bf8), P(0x09bfc), P(0x0a210), P(0x0a214), P(0x0a218),
+ P(0x0a220), P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234),
+ P(0x0a238), P(0x0a23c), P(0x0a240), P(0x0a244), P(0x0a248),
+ P(0x0a24c), P(0x0a250), P(0x0a254), P(0x0a258), P(0x0a25c),
+ P(0x0a260), P(0x0a268), P(0x0a26c), P(0x0b26c), P(0x0c26c),
+ P(0x0d270), P(0x0a278), P(0x0a27c), P(0x0a338), P(0x0a33c),
+ P(0x0a340), P(0x0a344), P(0x0a348), P(0x0a34c), P(0x0a350),
+ P(0x0a354), P(0x0a358), P(0x0d35c), P(0x0d360), P(0x0d364),
+ P(0x0d368), P(0x0d36c), P(0x0d370), P(0x0d374), P(0x0d378),
+ P(0x0d37c), P(0x0d380), P(0x0d384), P(0x0a388), P(0x0a38c),
+ P(0x0a390), P(0x0a394), P(0x0a398), P(0x0a39c), P(0x0a3a0),
+ P(0x0a3a4), P(0x0a3a8), P(0x0a3ac), P(0x0a3b0), P(0x0a3b4),
+ P(0x0a3b8), P(0x0a3bc), P(0x0a3c0), P(0x0a3c4), P(0x0a3c8),
+ P(0x0a3cc), P(0x0a3d0), P(0x0a3d4), P(0x0a3dc), P(0x0a3e0)
+};
+
+static const uint32_t ar9160_cm_vals[] = {
+ 0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x00000020, 0x000004c2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000,
+ 0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000,
+ 0x000fc78f, 0x0000000f, 0x00000000, 0x2a82301a, 0x05dc01e0,
+ 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
+ 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
+ 0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
+ 0x08f04800, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000,
+ 0x00000000, 0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000,
+ 0x00000000, 0x00003210, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00100000, 0x0010f400,
+ 0x00000100, 0x0001e800, 0x00000000, 0x00000000, 0x00000000,
+ 0x400000ff, 0x00080922, 0x00000000, 0x40000000, 0x003e4180,
+ 0x00000000, 0x0000002c, 0x0000002c, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007,
+ 0x00000302, 0x00000e00, 0x00ff0000, 0x00000000, 0x000107ff,
+ 0x00000000, 0xad848e19, 0x7d14e000, 0x9c0a9f6b, 0x00000000,
+ 0x0000a000, 0x00000000, 0x00200400, 0x206a01ae, 0x1284233c,
+ 0x00000859, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x10000fff, 0x05100000, 0x05100000, 0x05100000, 0x00000001,
+ 0x00000004, 0x1e1f2022, 0x0a0b0c0d, 0x00000000, 0x9280b212,
+ 0x00020028, 0x5f3ca3de, 0x2108ecff, 0x00750604, 0x004b6a8e,
+ 0x190fb515, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x201fff00,
+ 0x006f0000, 0x03051000, 0x00000000, 0x00000200, 0xaaaaaaaa,
+ 0x3c466478, 0x0cc80caa, 0x00001042, 0x00000000, 0x00000001,
+ 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008,
+ 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d,
+ 0x00000010, 0x00000011, 0x00000012, 0x00000013, 0x00000014,
+ 0x00000015, 0x00000018, 0x00000019, 0x0000001a, 0x0000001b,
+ 0x0000001c, 0x0000001d, 0x00000020, 0x00000021, 0x00000022,
+ 0x00000023, 0x00000024, 0x00000025, 0x00000028, 0x00000029,
+ 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d, 0x00000030,
+ 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
+ 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
+ 0x00000010, 0x0000001a, 0x40806333, 0x00106c10, 0x009c4060,
+ 0x018830c6, 0x00000400, 0x001a0bb5, 0x00000000, 0x20202020,
+ 0x20202020, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
+ 0x00000001, 0x0000e000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
+ 0xdfa91f01, 0x00000001, 0x0ebae9c6, 0x0ebae9c6, 0x0ebae9c6,
+ 0x00820820, 0x1ce739ce, 0x050701ce, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x3fffffff, 0x3fffffff, 0x3fffffff,
+ 0x0003ffff, 0x79bfaa03, 0x07ffffef, 0x0fffffe7, 0x17ffffe5,
+ 0x1fffffe4, 0x37ffffe3, 0x3fffffe3, 0x57ffffe3, 0x5fffffe2,
+ 0x7fffffe2, 0x7f3c7bba, 0xf3307ff0, 0x0c000000, 0x20202020,
+ 0x20202020, 0x1ce739ce, 0x000001ce, 0x00000001, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000246,
+ 0x20202020, 0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce
+};
+
+static const struct athn_ini ar9160_ini = {
+ nitems(ar9160_regs),
+ ar9160_regs,
+ ar9160_vals_5g20,
+#ifndef IEEE80211_NO_HT
+ ar9160_vals_5g40,
+ ar9160_vals_2g40,
+#endif
+ ar9160_vals_2g20,
+ nitems(ar9160_cm_regs),
+ ar9160_cm_regs,
+ ar9160_cm_vals
+};
+
+/*
+ * BB/RF Gains common to AR5416 and AR9160.
+ */
+static const uint32_t ar5416_bb_rfgain_vals_5g[] = {
+ 0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1,
+ 0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8,
+ 0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009,
+ 0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0,
+ 0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011,
+ 0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038,
+ 0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059,
+ 0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9
+};
+
+static const uint32_t ar5416_bb_rfgain_vals_2g[] = {
+ 0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181,
+ 0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8,
+ 0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9,
+ 0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0,
+ 0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191,
+ 0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8,
+ 0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199,
+ 0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
+ 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9
+};
+
+static const uint32_t ar5416_2_1_addac_vals[] = {
+ 0x00000000, 0x00000003, 0x00000000, 0x0000000c, 0x00000000,
+ 0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000060, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000
+};
+
+static const struct athn_addac ar5416_2_1_addac = {
+ nitems(ar5416_2_1_addac_vals),
+ ar5416_2_1_addac_vals
+};
+
+static const uint32_t ar5416_2_2_addac_vals[] = {
+ 0x00000000, 0x00000003, 0x00000000, 0x0000000c, 0x00000000,
+ 0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000060, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000058, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000
+};
+
+static const struct athn_addac ar5416_2_2_addac = {
+ nitems(ar5416_2_2_addac_vals),
+ ar5416_2_2_addac_vals
+};
+
+static const uint32_t ar9160_1_0_addac_vals[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x000000c0, 0x00000018, 0x00000004, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x000000c0, 0x00000019, 0x00000004, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000004, 0x00000003, 0x00000008,
+ 0x00000000
+};
+
+static const struct athn_addac ar9160_1_0_addac = {
+ nitems(ar9160_1_0_addac_vals),
+ ar9160_1_0_addac_vals
+};
+
+static const uint32_t ar9160_1_1_addac_vals[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x000000c0, 0x00000018, 0x00000004, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x000000c0, 0x00000019, 0x00000004, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000
+};
+
+static const struct athn_addac ar9160_1_1_addac = {
+ nitems(ar9160_1_1_addac_vals),
+ ar9160_1_1_addac_vals
+};
+
+static const uint32_t ar5416_bank6tpc_vals[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00e00000, 0x005e0000,
+ 0x00120000, 0x00620000, 0x00020000, 0x00ff0000, 0x00ff0000,
+ 0x00ff0000, 0x40ff0000, 0x005f0000, 0x00870000, 0x00f90000,
+ 0x007b0000, 0x00ff0000, 0x00f50000, 0x00dc0000, 0x00110000,
+ 0x006100a8, 0x00423022, 0x201400df, 0x00c40002, 0x003000f2,
+ 0x00440016, 0x00410040, 0x0001805e, 0x0000c0ab, 0x000000e1,
+ 0x00007081, 0x000000d4
+};
+
+static const uint32_t ar9160_bank6tpc_vals[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00e00000, 0x005e0000,
+ 0x00120000, 0x00620000, 0x00020000, 0x00ff0000, 0x00ff0000,
+ 0x00ff0000, 0x40ff0000, 0x005f0000, 0x00870000, 0x00f90000,
+ 0x007b0000, 0x00ff0000, 0x00f50000, 0x00dc0000, 0x00110000,
+ 0x006100a8, 0x00423022, 0x2014008f, 0x00c40002, 0x003000f2,
+ 0x00440016, 0x00410040, 0x0001805e, 0x0000c0ab, 0x000000e1,
+ 0x00007080, 0x000000d4
+};
+
+static const uint32_t ar5416_bank6_vals[] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00e00000, 0x005e0000,
+ 0x00120000, 0x00620000, 0x00020000, 0x00ff0000, 0x00ff0000,
+ 0x00ff0000, 0x40ff0000, 0x005f0000, 0x00870000, 0x00f90000,
+ 0x007b0000, 0x00ff0000, 0x00f50000, 0x00dc0000, 0x00110000,
+ 0x006100a8, 0x004210a2, 0x0014008f, 0x00c40003, 0x003000f2,
+ 0x00440016, 0x00410040, 0x0001805e, 0x0000c0ab, 0x000000f1,
+ 0x00002081, 0x000000d4
+};
+
+/*
+ * Serializer/Deserializer programming.
+ */
+static const uint32_t ar5416_serdes[] = {
+ 0x9248fc00,
+ 0x24924924,
+ /* RX shut off when elecidle is asserted. */
+ 0x28000039,
+ 0x53160824,
+ 0xe5980579,
+ 0x001defff,
+ 0x1aaabe40,
+ 0xbe105554,
+ 0x000e3007
+};
diff --git a/sys/dev/ic/ar9280.c b/sys/dev/ic/ar9280.c
new file mode 100644
index 00000000000..ffa07d28a4c
--- /dev/null
+++ b/sys/dev/ic/ar9280.c
@@ -0,0 +1,583 @@
+/* $OpenBSD: ar9280.c,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for Atheros 802.11a/g/n chipsets.
+ * Routines for AR9220, AR9223, AR9280 and AR9281 chipsets.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/timeout.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/endian.h>
+#include <machine/intr.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/ic/athnreg.h>
+#include <dev/ic/athnvar.h>
+
+#include <dev/ic/ar5416reg.h> /* We share the ROM layout. */
+#include <dev/ic/ar9280reg.h>
+
+int ar9280_attach(struct athn_softc *);
+void ar9280_setup(struct athn_softc *);
+void ar9280_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar9280_reset_rx_gain(struct athn_softc *, struct ieee80211_channel *);
+void ar9280_reset_tx_gain(struct athn_softc *, struct ieee80211_channel *);
+void ar9280_2_0_olpc_init(struct athn_softc *);
+void ar9280_2_0_olpc_temp_compensation(struct athn_softc *);
+
+int
+ar9280_attach(struct athn_softc *sc)
+{
+ sc->eep_base = AR5416_EEP_START_LOC;
+ sc->eep_size = sizeof (struct ar5416_eeprom);
+ sc->def_nf = AR9280_PHY_CCA_MAX_GOOD_VALUE;
+ sc->ngpiopins = 10;
+ sc->workaround = AR9280_WA_DEFAULT;
+ sc->ops.setup = ar9280_setup;
+ sc->ops.swap_rom = ar5416_swap_rom;
+ sc->ops.init_from_rom = ar9280_init_from_rom;
+ sc->ops.set_txpower = ar5416_set_txpower;
+ sc->ops.set_synth = ar9280_set_synth;
+ sc->ops.spur_mitigate = ar9280_spur_mitigate;
+ sc->ops.get_spur_chans = ar5416_get_spur_chans;
+ sc->ops.olpc_init = ar9280_2_0_olpc_init;
+ if (AR_SREV_9280_20_OR_LATER(sc))
+ sc->ini = &ar9280_2_0_ini;
+ else
+ sc->ini = &ar9280_1_0_ini;
+ if (AR_SREV_9280_20_OR_LATER(sc))
+ sc->serdes = ar9280_2_0_serdes;
+ else
+ sc->serdes = ar9280_1_0_serdes;
+ return (0);
+}
+
+void
+ar9280_setup(struct athn_softc *sc)
+{
+ const struct ar5416_eeprom *eep = sc->eep;
+ uint8_t type;
+
+ /* Determine if open loop power control should be used. */
+ if (AR_SREV_9280_20_OR_LATER(sc) &&
+ sc->eep_rev >= AR_EEP_MINOR_VER_19 &&
+ eep->baseEepHeader.openLoopPwrCntl)
+ sc->flags |= ATHN_FLAG_OLPC;
+
+ if (AR_SREV_9280_20(sc)) {
+ /* Check if we have a valid rxGainType field in ROM. */
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_17) {
+ /* Select initialization values based on ROM. */
+ type = eep->baseEepHeader.rxGainType;
+ DPRINTF(("Rx gain type=0x%x\n", type));
+ if (type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
+ sc->rx_gain = &ar9280_2_0_rx_gain_23db_backoff;
+ else if (type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
+ sc->rx_gain = &ar9280_2_0_rx_gain_13db_backoff;
+ else
+ sc->rx_gain = &ar9280_2_0_rx_gain;
+ } else
+ sc->rx_gain = &ar9280_2_0_rx_gain;
+
+ /* Check if we have a valid txGainType field in ROM. */
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_19) {
+ /* Select initialization values based on ROM. */
+ type = eep->baseEepHeader.txGainType;
+ DPRINTF(("Tx gain type=0x%x\n", type));
+ if (type == AR_EEP_TXGAIN_HIGH_POWER)
+ sc->tx_gain = &ar9280_2_0_tx_gain_high_power;
+ else
+ sc->tx_gain = &ar9280_2_0_tx_gain;
+ } else
+ sc->tx_gain = &ar9280_2_0_tx_gain;
+ }
+}
+
+int
+ar9280_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ uint32_t phy, reg, ndiv = 0;
+ uint32_t freq = c->ic_freq;
+
+ phy = AR_READ(sc, AR9280_PHY_SYNTH_CONTROL) & ~0x3fffffff;
+
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ phy |= (freq << 16) / 15;
+ phy |= AR9280_BMODE | AR9280_FRACMODE;
+
+ if (AR_SREV_9287_11_OR_LATER(sc)) {
+ /* XXX Magic from the Linux driver. */
+ if (freq == 2484) { /* Channel 14. */
+ /* Japanese regulatory requirements. */
+ AR_WRITE(sc, AR_PHY(637), 0x00000000);
+ AR_WRITE(sc, AR_PHY(638), 0xefff0301);
+ AR_WRITE(sc, AR_PHY(639), 0xca9228ee);
+ } else {
+ AR_WRITE(sc, AR_PHY(637), 0x00fffeff);
+ AR_WRITE(sc, AR_PHY(638), 0x00f5f9ff);
+ AR_WRITE(sc, AR_PHY(639), 0xb79f6427);
+ }
+ } else {
+ reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) /* Channel 14. */
+ reg |= AR_PHY_CCK_TX_CTRL_JAPAN;
+ else
+ reg &= ~AR_PHY_CCK_TX_CTRL_JAPAN;
+ AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
+ }
+ } else {
+ if (AR_SREV_9285_10_OR_LATER(sc) ||
+ sc->eep_rev < AR_EEP_MINOR_VER_22 ||
+ !((struct ar5416_base_eep_header *)sc->eep)->frac_n_5g) {
+ if ((freq % 20) == 0) {
+ ndiv = (freq * 3) / 60;
+ phy |= SM(AR9280_AMODE_REFSEL, 3);
+ } else if ((freq % 10) == 0) {
+ ndiv = (freq * 6) / 60;
+ phy |= SM(AR9280_AMODE_REFSEL, 2);
+ }
+ }
+ if (ndiv != 0) {
+ phy |= (ndiv & 0x1ff) << 17;
+ phy |= (ndiv & ~0x1ff) * 2;
+ } else {
+ phy |= (freq << 15) / 15;
+ phy |= AR9280_FRACMODE;
+
+ reg = AR_READ(sc, AR_AN_SYNTH9);
+ reg = RW(reg, AR_AN_SYNTH9_REFDIVA, 1);
+ AR_WRITE(sc, AR_AN_SYNTH9, reg);
+ }
+ }
+ DPRINTF(("AR9280_PHY_SYNTH_CONTROL=0x%08x\n", phy));
+ AR_WRITE(sc, AR9280_PHY_SYNTH_CONTROL, phy);
+ return (0);
+}
+
+void
+ar9280_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
+ const struct ar5416_eeprom *eep = sc->eep;
+ const struct ar5416_modal_eep_header *modal;
+ uint32_t reg, offset;
+ uint8_t txRxAtten;
+ int i;
+
+ modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
+
+ AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon & 0xffff);
+
+ for (i = 0; i < AR9280_MAX_CHAINS; i++) {
+ if (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5)
+ offset = chainoffset[i];
+ else
+ offset = i * 0x1000;
+
+ AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
+ modal->antCtrlChain[i]);
+
+ reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+ modal->iqCalICh[i]);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+ modal->iqCalQCh[i]);
+ AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
+
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
+ reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ modal->bswMargin[i]);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ modal->bswAtten[i]);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ modal->xatten2Margin[i]);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ modal->xatten2Db[i]);
+ AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
+ }
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
+ txRxAtten = modal->txRxAttenCh[i];
+ else /* Workaround for ROM versions < 14.3. */
+ txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
+ reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN,
+ txRxAtten);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN,
+ modal->rxTxMarginCh[i]);
+ AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
+ }
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ reg = AR_READ(sc, AR_AN_RF2G1_CH0);
+ reg = RW(reg, AR_AN_RF2G1_CH0_OB, modal->ob);
+ reg = RW(reg, AR_AN_RF2G1_CH0_DB, modal->db);
+ AR_WRITE(sc, AR_AN_RF2G1_CH0, reg);
+ DELAY(100);
+
+ reg = AR_READ(sc, AR_AN_RF2G1_CH1);
+ reg = RW(reg, AR_AN_RF2G1_CH1_OB, modal->ob_ch1);
+ reg = RW(reg, AR_AN_RF2G1_CH1_DB, modal->db_ch1);
+ AR_WRITE(sc, AR_AN_RF2G1_CH1, reg);
+ DELAY(100);
+ } else {
+ reg = AR_READ(sc, AR_AN_RF5G1_CH0);
+ reg = RW(reg, AR_AN_RF5G1_CH0_OB5, modal->ob);
+ reg = RW(reg, AR_AN_RF5G1_CH0_DB5, modal->db);
+ AR_WRITE(sc, AR_AN_RF5G1_CH0, reg);
+ DELAY(100);
+
+ reg = AR_READ(sc, AR_AN_RF5G1_CH1);
+ reg = RW(reg, AR_AN_RF5G1_CH1_OB5, modal->ob_ch1);
+ reg = RW(reg, AR_AN_RF5G1_CH1_DB5, modal->db_ch1);
+ AR_WRITE(sc, AR_AN_RF5G1_CH1, reg);
+ DELAY(100);
+ }
+ reg = AR_READ(sc, AR_AN_TOP2);
+ reg = RW(reg, AR_AN_TOP2_XPABIAS_LVL, modal->xpaBiasLvl);
+ if (modal->flagBits & AR5416_EEP_FLAG_LOCALBIAS)
+ reg |= AR_AN_TOP2_LOCALBIAS;
+ else
+ reg &= ~AR_AN_TOP2_LOCALBIAS;
+ /* Fix for dual-band devices. */
+ if (sc->eep_rev > AR_EEP_MINOR_VER_10 &&
+ (eep->baseEepHeader.opCapFlags & AR_OPFLAGS_11A)) {
+ if (eep->baseEepHeader.pwdclkind)
+ reg |= AR_AN_TOP2_PWDCLKIND;
+ else
+ reg &= ~AR_AN_TOP2_PWDCLKIND;
+ }
+ AR_WRITE(sc, AR_AN_TOP2, reg);
+ DELAY(100);
+
+ reg = AR_READ(sc, AR_PHY_XPA_CFG);
+ if (modal->flagBits & AR5416_EEP_FLAG_FORCEXPAON)
+ reg |= AR_PHY_FORCE_XPA_CFG;
+ else
+ reg &= ~AR_PHY_FORCE_XPA_CFG;
+ AR_WRITE(sc, AR_PHY_XPA_CFG, reg);
+
+ reg = AR_READ(sc, AR_PHY_SETTLING);
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
+ AR_WRITE(sc, AR_PHY_SETTLING, reg);
+
+ reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
+ reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
+ AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
+
+ reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
+
+ reg = AR_READ(sc, AR_PHY_RF_CTL3);
+ reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
+
+ reg = AR_READ(sc, AR_PHY_CCA(0));
+ reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_CCA(0), reg);
+
+ reg = AR_READ(sc, AR_PHY_EXT_CCA0);
+ reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
+
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
+ reg = AR_READ(sc, AR_PHY_RF_CTL2);
+ reg = RW(reg, AR_PHY_TX_END_DATA_START,
+ modal->txFrameToDataStart);
+ reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
+ }
+#ifndef IEEE80211_NO_HT
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
+ /* Overwrite switch settling with HT-40 value. */
+ reg = AR_READ(sc, AR_PHY_SETTLING);
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
+ AR_WRITE(sc, AR_PHY_SETTLING, reg);
+ }
+#endif
+ if (AR_SREV_9280_20_OR_LATER(sc) &&
+ sc->eep_rev >= AR_EEP_MINOR_VER_19) {
+ reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
+ reg = RW(reg, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
+ MS(modal->miscBits, AR5416_EEP_MISC_TX_DAC_SCALE_CCK));
+ AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
+ }
+ if (AR_SREV_9280_20(sc) &&
+ sc->eep_rev >= AR_EEP_MINOR_VER_20) {
+ reg = AR_READ(sc, AR_AN_TOP1);
+ if (eep->baseEepHeader.dacLpMode &&
+ (IEEE80211_IS_CHAN_2GHZ(c) ||
+ !eep->baseEepHeader.dacHiPwrMode_5G))
+ reg |= AR_AN_TOP1_DACLPMODE;
+ else
+ reg &= ~AR_AN_TOP1_DACLPMODE;
+ AR_WRITE(sc, AR_AN_TOP1, reg);
+ DELAY(100);
+
+ reg = AR_READ(sc, AR_PHY_FRAME_CTL);
+ reg = RW(reg, AR_PHY_FRAME_CTL_TX_CLIP,
+ MS(modal->miscBits, AR5416_EEP_MISC_TX_CLIP));
+ AR_WRITE(sc, AR_PHY_FRAME_CTL, reg);
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL9);
+ reg = RW(reg, AR_PHY_TX_DESIRED_SCALE_CCK,
+ eep->baseEepHeader.desiredScaleCCK);
+ AR_WRITE(sc, AR_PHY_TX_PWRCTRL9, reg);
+ }
+}
+
+void
+ar9280_2_0_olpc_get_pdadcs(struct athn_softc *sc,
+ struct ieee80211_channel *c, int chain, uint8_t *boundaries,
+ uint8_t *pdadcs, uint8_t *txgain)
+{
+ const struct ar5416_eeprom *eep = sc->eep;
+ const struct ar_cal_data_per_freq_olpc *pierdata;
+ const uint8_t *pierfreq;
+ uint8_t fbin, pcdac, pwr, idx;
+ int i, lo, hi, npiers;
+
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ pierfreq = eep->calFreqPier2G;
+ pierdata = (const struct ar_cal_data_per_freq_olpc *)
+ eep->calPierData2G[chain];
+ npiers = AR5416_NUM_2G_CAL_PIERS;
+ } else {
+ pierfreq = eep->calFreqPier5G;
+ pierdata = (const struct ar_cal_data_per_freq_olpc *)
+ eep->calPierData5G[chain];
+ npiers = AR5416_NUM_5G_CAL_PIERS;
+ }
+ /* Find channel in ROM pier table. */
+ fbin = athn_chan2fbin(c);
+ athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
+
+ /* Get average. */
+ pwr = (pierdata[lo].pwrPdg[0][0] + pierdata[hi].pwrPdg[0][0]) / 2;
+ pwr /= 2; /* Convert to dB. */
+
+ pcdac = pierdata[hi].pcdac[0][0]; /* XXX lo??? */
+ for (idx = 0; idx < AR9280_TX_GAIN_TABLE_SIZE - 1; idx++)
+ if (pcdac > sc->tx_gain_tbl[idx])
+ break;
+ *txgain = idx;
+
+ for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
+ pdadcs[i] = (i < pwr) ? 0x00 : 0xff;
+
+ for (i = 0; i < AR_PD_GAINS_IN_MASK; i++)
+ boundaries[i] = AR9280_PD_GAIN_BOUNDARY_DEFAULT;
+}
+
+void
+ar9280_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ const struct ar_spur_chan *spurchans;
+ int spur, bin, spur_delta_phase, spur_freq_sd, spur_subchannel_sd;
+ int spur_off, bound, i;
+
+ /* NB: Always clear. */
+ AR_CLRBITS(sc, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+
+ bound = (extc != NULL) ? 19 : 10;
+
+ spurchans = sc->ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ spur = spurchans[i].spurChan;
+ /* XXX Linux checks this too late? */
+ if (spur == AR_NO_SPUR)
+ return; /* XXX disable if it was enabled! */
+ spur /= 10;
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ spur += AR_BASE_FREQ_2GHZ;
+ else
+ spur += AR_BASE_FREQ_5GHZ;
+ spur -= c->ic_freq;
+ if (abs(spur) < bound)
+ break;
+ }
+ if (i == AR_EEPROM_MODAL_SPURS)
+ return; /* XXX disable if it was enabled! */
+ DPRINTF(("enabling spur mitigation\n"));
+
+ AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+ AR_WRITE(sc, AR_PHY_SPUR_REG,
+ AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
+
+ if (extc != NULL) {
+ spur_delta_phase = (spur * 262144) / 10;
+ if (spur < 0) {
+ spur_subchannel_sd = 1;
+ spur_off = spur + 10;
+ } else {
+ spur_subchannel_sd = 0;
+ spur_off = spur - 10;
+ }
+ } else {
+ spur_delta_phase = (spur * 524288) / 10;
+ spur_subchannel_sd = 0;
+ spur_off = spur;
+ }
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ spur_freq_sd = (spur_off * 2048) / 44;
+ else
+ spur_freq_sd = (spur_off * 2048) / 40;
+
+ AR_WRITE(sc, AR_PHY_TIMING11,
+ AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
+ SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
+
+ AR_WRITE(sc, AR_PHY_SFCORR_EXT,
+ SM(AR_PHY_SFCORR_SPUR_SUBCHNL_SD, spur_subchannel_sd));
+
+ bin = spur * 320;
+ athn_set_viterbi_mask(sc, bin);
+}
+
+void
+ar9280_reset_rx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ const struct athn_gain *prog = sc->rx_gain;
+ const uint32_t *pvals;
+ int i;
+
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ pvals = prog->vals_2g;
+ else
+ pvals = prog->vals_5g;
+ for (i = 0; i < prog->nregs; i++)
+ AR_WRITE(sc, prog->regs[i], pvals[i]);
+}
+
+void
+ar9280_reset_tx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ const struct athn_gain *prog = sc->tx_gain;
+ const uint32_t *pvals;
+ int i;
+
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ pvals = prog->vals_2g;
+ else
+ pvals = prog->vals_5g;
+ for (i = 0; i < prog->nregs; i++)
+ AR_WRITE(sc, prog->regs[i], pvals[i]);
+}
+
+void
+ar9280_2_0_olpc_init(struct athn_softc *sc)
+{
+ uint32_t reg;
+ int i;
+
+ /* Save original Tx gain values. */
+ for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
+ reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
+ sc->tx_gain_tbl[i] = MS(reg, AR_PHY_TX_GAIN);
+ }
+ /* Initial Tx gain temperature compensation. */
+ sc->tcomp = 0;
+}
+
+void
+ar9280_2_0_olpc_temp_compensation(struct athn_softc *sc)
+{
+ const struct ar5416_eeprom *eep = sc->eep;
+ int8_t pdadc, txgain, tcomp;
+ uint32_t reg;
+ int i;
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL4);
+ pdadc = MS(reg, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
+ DPRINTF(("PD Avg Out=%d\n", pdadc));
+
+ if (sc->pdadc == 0 || pdadc == 0)
+ return; /* No frames transmitted yet. */
+
+ /* Compute Tx gain temperature compensation. */
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_20 &&
+ eep->baseEepHeader.dacHiPwrMode_5G)
+ tcomp = (pdadc - sc->pdadc + 4) / 8;
+ else
+ tcomp = (pdadc - sc->pdadc + 5) / 10;
+ DPRINTF(("OLPC temp compensation=%d\n", tcomp));
+
+ if (tcomp == sc->tcomp)
+ return; /* Don't rewrite the same values. */
+ sc->tcomp = tcomp;
+
+ /* Adjust Tx gain values. */
+ for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
+ txgain = sc->tx_gain_tbl[i] - tcomp;
+ if (txgain < 0)
+ txgain = 0;
+ reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
+ reg = RW(reg, AR_PHY_TX_GAIN, txgain);
+ AR_WRITE(sc, AR_PHY_TX_GAIN_TBL(i), reg);
+ }
+}
diff --git a/sys/dev/ic/ar9280reg.h b/sys/dev/ic/ar9280reg.h
new file mode 100644
index 00000000000..fe7d03a828f
--- /dev/null
+++ b/sys/dev/ic/ar9280reg.h
@@ -0,0 +1,969 @@
+/* $OpenBSD: ar9280reg.h,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define AR9280_MAX_CHAINS 2
+
+#define AR9280_PD_GAIN_BOUNDARY_DEFAULT 56
+#define AR9280_PHY_CCA_MAX_GOOD_VALUE (-112)
+
+#define AR9280_PHY_SYNTH_CONTROL 0x9874
+
+/* Bits for AR9280_PHY_SYNTH_CONTROL. */
+#define AR9280_BMODE 0x20000000
+#define AR9280_FRACMODE 0x10000000
+#define AR9280_AMODE_REFSEL_M 0x0c000000
+#define AR9280_AMODE_REFSEL_S 26
+
+/*
+ * NB: The AR9280 uses the same ROM layout than the AR5416.
+ */
+
+/* Macro to "pack" registers to 16-bit to save some .rodata space. */
+#define P(x) (x)
+
+/*
+ * AR9280 1.0 initialization values.
+ */
+static const uint16_t ar9280_1_0_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x09804), P(0x09820), P(0x09824), P(0x09828),
+ P(0x09834), P(0x09838), P(0x09844), P(0x09848), P(0x0a848),
+ P(0x09850), P(0x09858), P(0x0985c), P(0x09860), P(0x0c864),
+ P(0x09868), P(0x0986c), P(0x09914), P(0x09918), P(0x09924),
+ P(0x09944), P(0x09960), P(0x0a960), P(0x09964), P(0x0c9b8),
+ P(0x0c9bc), P(0x099c0), P(0x099c4), P(0x099c8), P(0x099cc),
+ P(0x099d0), P(0x099d4), P(0x099d8), P(0x09a00), P(0x09a04),
+ P(0x09a08), P(0x09a0c), P(0x09a10), P(0x09a14), P(0x09a18),
+ P(0x09a1c), P(0x09a20), P(0x09a24), P(0x09a28), P(0x09a2c),
+ P(0x09a30), P(0x09a34), P(0x09a38), P(0x09a3c), P(0x09a40),
+ P(0x09a44), P(0x09a48), P(0x09a4c), P(0x09a50), P(0x09a54),
+ P(0x09a58), P(0x09a5c), P(0x09a60), P(0x09a64), P(0x09a68),
+ P(0x09a6c), P(0x09a70), P(0x09a74), P(0x09a78), P(0x09a7c),
+ P(0x09a80), P(0x09a84), P(0x09a88), P(0x09a8c), P(0x09a90),
+ P(0x09a94), P(0x09a98), P(0x09a9c), P(0x09aa0), P(0x09aa4),
+ P(0x09aa8), P(0x09aac), P(0x09ab0), P(0x09ab4), P(0x09ab8),
+ P(0x09abc), P(0x09ac0), P(0x09ac4), P(0x09ac8), P(0x09acc),
+ P(0x09ad0), P(0x09ad4), P(0x09ad8), P(0x09adc), P(0x09ae0),
+ P(0x09ae4), P(0x09ae8), P(0x09aec), P(0x09af0), P(0x09af4),
+ P(0x09af8), P(0x09afc), P(0x09b00), P(0x09b04), P(0x09b08),
+ P(0x09b0c), P(0x09b10), P(0x09b14), P(0x09b18), P(0x09b1c),
+ P(0x09b20), P(0x09b24), P(0x09b28), P(0x09b2c), P(0x09b30),
+ P(0x09b34), P(0x09b38), P(0x09b3c), P(0x09b40), P(0x09b44),
+ P(0x09b48), P(0x09b4c), P(0x09b50), P(0x09b54), P(0x09b58),
+ P(0x09b5c), P(0x09b60), P(0x09b64), P(0x09b68), P(0x09b6c),
+ P(0x09b70), P(0x09b74), P(0x09b78), P(0x09b7c), P(0x09b80),
+ P(0x09b84), P(0x09b88), P(0x09b8c), P(0x09b90), P(0x09b94),
+ P(0x09b98), P(0x09b9c), P(0x09ba0), P(0x09ba4), P(0x09ba8),
+ P(0x09bac), P(0x09bb0), P(0x09bb4), P(0x09bb8), P(0x09bbc),
+ P(0x09bc0), P(0x09bc4), P(0x09bc8), P(0x09bcc), P(0x09bd0),
+ P(0x09bd4), P(0x09bd8), P(0x09bdc), P(0x09be0), P(0x09be4),
+ P(0x09be8), P(0x09bec), P(0x09bf0), P(0x09bf4), P(0x09bf8),
+ P(0x09bfc), P(0x0a204), P(0x0a208), P(0x0a20c), P(0x0b20c),
+ P(0x0a21c), P(0x0a230), P(0x0a274), P(0x0a300), P(0x0a304),
+ P(0x0a308), P(0x0a30c), P(0x0a310), P(0x0a314), P(0x0a318),
+ P(0x0a31c), P(0x0a320), P(0x0a324), P(0x0a328), P(0x0a32c),
+ P(0x0a330), P(0x0a334), P(0x0a338), P(0x0a33c), P(0x0a340),
+ P(0x0a344), P(0x0a348), P(0x0a34c), P(0x0a350), P(0x0a354),
+ P(0x0784c), P(0x07854), P(0x07870), P(0x0788c)
+};
+
+static const uint32_t ar9280_1_0_vals_5g20[] = {
+ 0x00000230, 0x00000168, 0x00000e60, 0x0000a000, 0x03e803e8,
+ 0x128d8027, 0x00000300, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x1372161e, 0x00028566, 0x00028566,
+ 0x6d4000e2, 0x7ec82d2e, 0x3139605e, 0x00049d18, 0x0001ce00,
+ 0x5ac64190, 0x06903081, 0x000007d0, 0x0000000a, 0xd00a8a07,
+ 0xdfbc1010, 0x00000010, 0x00000010, 0x00000210, 0x0000001a,
+ 0x00000600, 0x05eea6d4, 0x06336f77, 0x60f6532c, 0x08f186c8,
+ 0x00046384, 0x00000000, 0x00000000, 0x00008184, 0x00008188,
+ 0x0000818c, 0x00008190, 0x00008194, 0x00008200, 0x00008204,
+ 0x00008208, 0x0000820c, 0x00008210, 0x00008214, 0x00008280,
+ 0x00008284, 0x00008288, 0x0000828c, 0x00008290, 0x00008300,
+ 0x00008304, 0x00008308, 0x0000830c, 0x00008310, 0x00008314,
+ 0x00008380, 0x00008384, 0x00008388, 0x0000838c, 0x00008390,
+ 0x00008394, 0x0000a380, 0x0000a384, 0x0000a388, 0x0000a38c,
+ 0x0000a390, 0x0000a394, 0x0000a780, 0x0000a784, 0x0000a788,
+ 0x0000a78c, 0x0000a790, 0x0000a794, 0x0000ab84, 0x0000ab88,
+ 0x0000ab8c, 0x0000ab90, 0x0000ab94, 0x0000af80, 0x0000af84,
+ 0x0000af88, 0x0000af8c, 0x0000af90, 0x0000af94, 0x0000b380,
+ 0x0000b384, 0x0000b388, 0x0000b38c, 0x0000b390, 0x0000b394,
+ 0x0000b398, 0x0000b780, 0x0000b784, 0x0000b788, 0x0000b78c,
+ 0x0000b790, 0x0000b794, 0x0000b798, 0x0000d784, 0x0000d788,
+ 0x0000d78c, 0x0000d790, 0x0000f780, 0x0000f784, 0x0000f788,
+ 0x0000f78c, 0x0000f790, 0x0000f794, 0x0000f7a4, 0x0000f7a8,
+ 0x0000f7ac, 0x0000f7b0, 0x0000f7b4, 0x0000f7a1, 0x0000f7a5,
+ 0x0000f7a9, 0x0000f7ad, 0x0000f7b1, 0x0000f7b5, 0x0000f7c5,
+ 0x0000f7c9, 0x0000f7cd, 0x0000f7d1, 0x0000f7d5, 0x0000f7c2,
+ 0x0000f7c6, 0x0000f7ca, 0x0000f7ce, 0x0000f7d2, 0x0000f7d6,
+ 0x0000f7c3, 0x0000f7c7, 0x0000f7cb, 0x0000f7d3, 0x0000f7d7,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x00000444, 0x803e4788, 0x000c6019, 0x000c6019,
+ 0x1883800a, 0x00000000, 0x0a19c652, 0x00000000, 0x00003002,
+ 0x00006004, 0x0000a006, 0x0000e012, 0x00011014, 0x0001504a,
+ 0x0001904c, 0x0001c04e, 0x00020092, 0x0002410a, 0x0002710c,
+ 0x0002b18b, 0x0002e1cc, 0x000321ec, 0x000321ec, 0x000321ec,
+ 0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec,
+ 0x0e4f048c, 0x12031828, 0x807ec400, 0x00010000
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar9280_1_0_vals_5g40[] = {
+ 0x00000460, 0x000002d0, 0x00001cc0, 0x00014000, 0x07d007d0,
+ 0x128d804f, 0x000003c4, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x1372161e, 0x00028566, 0x00028566,
+ 0x6d4000e2, 0x7ec82d2e, 0x3139605e, 0x00049d18, 0x0001ce00,
+ 0x5ac64190, 0x06903081, 0x000007d0, 0x00000014, 0xd00a8a07,
+ 0xdfbc1010, 0x00000010, 0x00000010, 0x00000210, 0x0000001a,
+ 0x00000600, 0x05eea6d4, 0x06336f77, 0x60f6532c, 0x08f186c8,
+ 0x00046384, 0x00000000, 0x00000000, 0x00008184, 0x00008188,
+ 0x0000818c, 0x00008190, 0x00008194, 0x00008200, 0x00008204,
+ 0x00008208, 0x0000820c, 0x00008210, 0x00008214, 0x00008280,
+ 0x00008284, 0x00008288, 0x0000828c, 0x00008290, 0x00008300,
+ 0x00008304, 0x00008308, 0x0000830c, 0x00008310, 0x00008314,
+ 0x00008380, 0x00008384, 0x00008388, 0x0000838c, 0x00008390,
+ 0x00008394, 0x0000a380, 0x0000a384, 0x0000a388, 0x0000a38c,
+ 0x0000a390, 0x0000a394, 0x0000a780, 0x0000a784, 0x0000a788,
+ 0x0000a78c, 0x0000a790, 0x0000a794, 0x0000ab84, 0x0000ab88,
+ 0x0000ab8c, 0x0000ab90, 0x0000ab94, 0x0000af80, 0x0000af84,
+ 0x0000af88, 0x0000af8c, 0x0000af90, 0x0000af94, 0x0000b380,
+ 0x0000b384, 0x0000b388, 0x0000b38c, 0x0000b390, 0x0000b394,
+ 0x0000b398, 0x0000b780, 0x0000b784, 0x0000b788, 0x0000b78c,
+ 0x0000b790, 0x0000b794, 0x0000b798, 0x0000d784, 0x0000d788,
+ 0x0000d78c, 0x0000d790, 0x0000f780, 0x0000f784, 0x0000f788,
+ 0x0000f78c, 0x0000f790, 0x0000f794, 0x0000f7a4, 0x0000f7a8,
+ 0x0000f7ac, 0x0000f7b0, 0x0000f7b4, 0x0000f7a1, 0x0000f7a5,
+ 0x0000f7a9, 0x0000f7ad, 0x0000f7b1, 0x0000f7b5, 0x0000f7c5,
+ 0x0000f7c9, 0x0000f7cd, 0x0000f7d1, 0x0000f7d5, 0x0000f7c2,
+ 0x0000f7c6, 0x0000f7ca, 0x0000f7ce, 0x0000f7d2, 0x0000f7d6,
+ 0x0000f7c3, 0x0000f7c7, 0x0000f7cb, 0x0000f7d3, 0x0000f7d7,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x00000444, 0x803e4788, 0x000c6019, 0x000c6019,
+ 0x1883800a, 0x00000000, 0x0a19c652, 0x00000000, 0x00003002,
+ 0x00006004, 0x0000a006, 0x0000e012, 0x00011014, 0x0001504a,
+ 0x0001904c, 0x0001c04e, 0x00020092, 0x0002410a, 0x0002710c,
+ 0x0002b18b, 0x0002e1cc, 0x000321ec, 0x000321ec, 0x000321ec,
+ 0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec,
+ 0x0e4f048c, 0x12031828, 0x807ec400, 0x00010000
+};
+
+static const uint32_t ar9280_1_0_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00016000, 0x10801080,
+ 0x12e00057, 0x000003c4, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x137216a0, 0x00028563, 0x00028563,
+ 0x6d4000e2, 0x7ec82d2e, 0x3139605e, 0x00049d20, 0x0001ce00,
+ 0x5ac64190, 0x06903881, 0x00000898, 0x00000016, 0xd00a8a0d,
+ 0xdfbc1010, 0x00000010, 0x00000010, 0x00000210, 0x0000001a,
+ 0x00000c00, 0x05eea6d4, 0x06336f77, 0x60f6532c, 0x08f186c8,
+ 0x00046384, 0x00000000, 0x00000000, 0x00000214, 0x00000218,
+ 0x00000224, 0x00000228, 0x0000022c, 0x00000230, 0x000002a4,
+ 0x000002a8, 0x000002ac, 0x000002b0, 0x000002b4, 0x000002b8,
+ 0x00000390, 0x00000394, 0x00000398, 0x00000334, 0x00000338,
+ 0x000003ac, 0x000003b0, 0x000003b4, 0x000003b8, 0x000003a5,
+ 0x000003a9, 0x000003ad, 0x00008194, 0x000081a0, 0x0000820c,
+ 0x000081a8, 0x00008284, 0x00008288, 0x00008224, 0x00008290,
+ 0x00008300, 0x00008304, 0x00008308, 0x0000830c, 0x00008380,
+ 0x00008384, 0x00008700, 0x00008704, 0x00008708, 0x0000870c,
+ 0x00008780, 0x00008784, 0x00008b00, 0x00008b04, 0x00008b08,
+ 0x00008b0c, 0x00008b80, 0x00008b84, 0x00008b88, 0x00008b8c,
+ 0x00008b90, 0x00008f80, 0x00008f84, 0x00008f88, 0x00008f8c,
+ 0x00008f90, 0x0000930c, 0x00009310, 0x00009384, 0x00009388,
+ 0x00009324, 0x00009704, 0x000096a4, 0x000096a8, 0x00009710,
+ 0x00009714, 0x00009720, 0x00009724, 0x00009728, 0x0000972c,
+ 0x000097a0, 0x000097a4, 0x000097a8, 0x000097b0, 0x000097b4,
+ 0x000097b8, 0x000097a5, 0x000097a9, 0x000097ad, 0x000097b1,
+ 0x000097b5, 0x000097b9, 0x000097c5, 0x000097c9, 0x000097d1,
+ 0x000097d5, 0x000097d9, 0x000097c6, 0x000097ca, 0x000097ce,
+ 0x000097d2, 0x000097d6, 0x000097c3, 0x000097c7, 0x000097cb,
+ 0x000097cf, 0x000097d7, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x00000444, 0x803e4788, 0x000c6019, 0x000c6019,
+ 0x1883800a, 0x00000210, 0x0a1aa652, 0x00000000, 0x00003002,
+ 0x00008009, 0x0000b00b, 0x0000e012, 0x00012048, 0x0001604a,
+ 0x0001a211, 0x0001e213, 0x0002121b, 0x00024412, 0x00028414,
+ 0x0002b44a, 0x00030649, 0x0003364b, 0x00038a49, 0x0003be48,
+ 0x0003ee4a, 0x00042e88, 0x00046e8a, 0x00049ec9, 0x0004bf42,
+ 0x0e4d048c, 0x12035828, 0x807ec000, 0x00110000
+};
+#endif
+
+static const uint32_t ar9280_1_0_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x0000b000, 0x08400840,
+ 0x12e0002b, 0x00000300, 0x02020200, 0x00000e0e, 0x0a020001,
+ 0x00000e0e, 0x00000007, 0x137216a0, 0x00028563, 0x00028563,
+ 0x6d4000e2, 0x7ec82d2e, 0x3139605e, 0x00049d20, 0x0001ce00,
+ 0x5ac64190, 0x06903881, 0x00000898, 0x0000000b, 0xd00a8a0d,
+ 0xdfbc1010, 0x00000010, 0x00000010, 0x00000210, 0x0000001a,
+ 0x00000c00, 0x05eea6d4, 0x06336f77, 0x60f6532c, 0x08f186c8,
+ 0x00046384, 0x00000000, 0x00000000, 0x00000214, 0x00000218,
+ 0x00000224, 0x00000228, 0x0000022c, 0x00000230, 0x000002a4,
+ 0x000002a8, 0x000002ac, 0x000002b0, 0x000002b4, 0x000002b8,
+ 0x00000390, 0x00000394, 0x00000398, 0x00000334, 0x00000338,
+ 0x000003ac, 0x000003b0, 0x000003b4, 0x000003b8, 0x000003a5,
+ 0x000003a9, 0x000003ad, 0x00008194, 0x000081a0, 0x0000820c,
+ 0x000081a8, 0x00008284, 0x00008288, 0x00008224, 0x00008290,
+ 0x00008300, 0x00008304, 0x00008308, 0x0000830c, 0x00008380,
+ 0x00008384, 0x00008700, 0x00008704, 0x00008708, 0x0000870c,
+ 0x00008780, 0x00008784, 0x00008b00, 0x00008b04, 0x00008b08,
+ 0x00008b0c, 0x00008b80, 0x00008b84, 0x00008b88, 0x00008b8c,
+ 0x00008b90, 0x00008f80, 0x00008f84, 0x00008f88, 0x00008f8c,
+ 0x00008f90, 0x0000930c, 0x00009310, 0x00009384, 0x00009388,
+ 0x00009324, 0x00009704, 0x000096a4, 0x000096a8, 0x00009710,
+ 0x00009714, 0x00009720, 0x00009724, 0x00009728, 0x0000972c,
+ 0x000097a0, 0x000097a4, 0x000097a8, 0x000097b0, 0x000097b4,
+ 0x000097b8, 0x000097a5, 0x000097a9, 0x000097ad, 0x000097b1,
+ 0x000097b5, 0x000097b9, 0x000097c5, 0x000097c9, 0x000097d1,
+ 0x000097d5, 0x000097d9, 0x000097c6, 0x000097ca, 0x000097ce,
+ 0x000097d2, 0x000097d6, 0x000097c3, 0x000097c7, 0x000097cb,
+ 0x000097cf, 0x000097d7, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x00000444, 0x803e4788, 0x000c6019, 0x000c6019,
+ 0x1883800a, 0x00000108, 0x0a1aa652, 0x00000000, 0x00003002,
+ 0x00008009, 0x0000b00b, 0x0000e012, 0x00012048, 0x0001604a,
+ 0x0001a211, 0x0001e213, 0x0002121b, 0x00024412, 0x00028414,
+ 0x0002b44a, 0x00030649, 0x0003364b, 0x00038a49, 0x0003be48,
+ 0x0003ee4a, 0x00042e88, 0x00046e8a, 0x00049ec9, 0x0004bf42,
+ 0x0e4d048c, 0x12035828, 0x807ec000, 0x00110000
+};
+
+static const uint16_t ar9280_1_0_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x07010),
+ P(0x07038), P(0x08004), P(0x08008), P(0x0800c), P(0x08018),
+ P(0x08020), P(0x08038), P(0x0803c), P(0x08048), P(0x08054),
+ P(0x08058), P(0x0805c), P(0x08060), P(0x08064), P(0x08070),
+ P(0x080c0), P(0x080c4), P(0x080c8), P(0x080cc), P(0x080d0),
+ P(0x080d4), P(0x080d8), P(0x080e0), P(0x080e4), P(0x080e8),
+ P(0x080ec), P(0x080f0), P(0x080f4), P(0x080f8), P(0x080fc),
+ P(0x08100), P(0x08104), P(0x08108), P(0x0810c), P(0x08110),
+ P(0x08118), P(0x0811c), P(0x08120), P(0x08124), P(0x08128),
+ P(0x0812c), P(0x08130), P(0x08134), P(0x08138), P(0x0813c),
+ P(0x08144), P(0x08168), P(0x0816c), P(0x08170), P(0x08174),
+ P(0x08178), P(0x0817c), P(0x081c4), P(0x081d0), P(0x081ec),
+ P(0x081f0), P(0x081f4), P(0x081f8), P(0x081fc), P(0x08200),
+ P(0x08204), P(0x08208), P(0x0820c), P(0x08210), P(0x08214),
+ P(0x08218), P(0x0821c), P(0x08220), P(0x08224), P(0x08228),
+ P(0x0822c), P(0x08230), P(0x08234), P(0x08238), P(0x0823c),
+ P(0x08240), P(0x08244), P(0x08248), P(0x0824c), P(0x08250),
+ P(0x08254), P(0x08258), P(0x0825c), P(0x08260), P(0x08270),
+ P(0x08274), P(0x08278), P(0x0827c), P(0x08284), P(0x08288),
+ P(0x0828c), P(0x08294), P(0x08298), P(0x08300), P(0x08304),
+ P(0x08308), P(0x0830c), P(0x08310), P(0x08314), P(0x08318),
+ P(0x08328), P(0x0832c), P(0x08330), P(0x08334), P(0x08338),
+ P(0x0833c), P(0x08340), P(0x08344), P(0x09808), P(0x0980c),
+ P(0x09810), P(0x09814), P(0x0981c), P(0x0982c), P(0x09830),
+ P(0x0983c), P(0x09840), P(0x0984c), P(0x0a84c), P(0x09854),
+ P(0x09900), P(0x09904), P(0x09908), P(0x0990c), P(0x0991c),
+ P(0x09920), P(0x0a920), P(0x09928), P(0x0992c), P(0x09934),
+ P(0x09938), P(0x0993c), P(0x09948), P(0x0994c), P(0x09954),
+ P(0x09958), P(0x09940), P(0x0c95c), P(0x0c968), P(0x09970),
+ P(0x09974), P(0x09978), P(0x0997c), P(0x09980), P(0x09984),
+ P(0x09988), P(0x0998c), P(0x09990), P(0x09994), P(0x09998),
+ P(0x0999c), P(0x099a0), P(0x099a4), P(0x099a8), P(0x099ac),
+ P(0x099b0), P(0x099b4), P(0x099dc), P(0x099e0), P(0x099e4),
+ P(0x099e8), P(0x099ec), P(0x099fc), P(0x0a210), P(0x0a214),
+ P(0x0a218), P(0x0a220), P(0x0a224), P(0x0a228), P(0x0a22c),
+ P(0x0a234), P(0x0a238), P(0x0a23c), P(0x0a240), P(0x0a244),
+ P(0x0a248), P(0x0a24c), P(0x0a250), P(0x0a254), P(0x0a258),
+ P(0x0a25c), P(0x0a260), P(0x0a268), P(0x0a26c), P(0x0b26c),
+ P(0x0d270), P(0x0a278), P(0x0a27c), P(0x0a358), P(0x0d35c),
+ P(0x0d360), P(0x0d364), P(0x0d368), P(0x0d36c), P(0x0d370),
+ P(0x0d374), P(0x0d378), P(0x0d37c), P(0x0d380), P(0x0d384),
+ P(0x0a388), P(0x0a38c), P(0x0a390), P(0x0a394), P(0x0a398),
+ P(0x0a39c), P(0x0a3a0), P(0x0a3a4), P(0x0a3a8), P(0x0a3ac),
+ P(0x0a3b0), P(0x0a3b4), P(0x0a3b8), P(0x0a3bc), P(0x0a3c0),
+ P(0x0a3c4), P(0x0a3c8), P(0x0a3cc), P(0x0a3d0), P(0x0a3d4),
+ P(0x0a3dc), P(0x0a3e0), P(0x0a3e4), P(0x0a3e8), P(0x0a3ec),
+ P(0x07800), P(0x07804), P(0x07808), P(0x0780c), P(0x07810),
+ P(0x07814), P(0x07818), P(0x0781c), P(0x07820), P(0x07824),
+ P(0x07828), P(0x0782c), P(0x07830), P(0x07834), P(0x07838),
+ P(0x0783c), P(0x07840), P(0x07844), P(0x07848), P(0x07850),
+ P(0x07858), P(0x07860), P(0x07864), P(0x07868), P(0x0786c),
+ P(0x07874), P(0x07878), P(0x0787c), P(0x07880), P(0x07884),
+ P(0x07888), P(0x07890), P(0x07894), P(0x07898)
+};
+
+static const uint32_t ar9280_1_0_cm_vals[] = {
+ 0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000033,
+ 0x000004c2, 0x00000000, 0x00000000, 0x00000000, 0x00000700,
+ 0x00000000, 0x00000000, 0x00000000, 0x40000000, 0x00000000,
+ 0x00000000, 0x000fc78f, 0x0000000f, 0x00000000, 0x00000000,
+ 0x2a82301a, 0x05dc01e0, 0x1f402710, 0x01f40000, 0x00001e00,
+ 0x00000000, 0x00400000, 0xffffffff, 0x0000ffff, 0x003f3f3f,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00020000,
+ 0x00020000, 0x00000001, 0x00000052, 0x00000000, 0x00000168,
+ 0x000100aa, 0x00003210, 0x08f04800, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x32143320, 0xfaa4fa50,
+ 0x00000100, 0x00000000, 0x00000000, 0x00003210, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00100000, 0x0010f400, 0x00000100, 0x0001e800, 0x00000000,
+ 0x00000000, 0x00000000, 0x400000ff, 0x00080922, 0x00000000,
+ 0x40000000, 0x003e4180, 0x00000000, 0x0000002c, 0x0000002c,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000007, 0x00000302, 0x00000e00, 0x00000000,
+ 0x00000000, 0x000107ff, 0x00000000, 0x00000000, 0xaf268e30,
+ 0xfd14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000, 0x00000000,
+ 0x00200400, 0x206a01ae, 0x0040233c, 0x0040233c, 0x00000044,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000fff,
+ 0x04900000, 0x04900000, 0x00000001, 0x00000004, 0x1e1f2022,
+ 0x0a0b0c0d, 0x00000000, 0x9280c00a, 0x00020028, 0xe250a51e,
+ 0x3388ffff, 0x00781204, 0x004b6a8e, 0x000003ce, 0x190fb514,
+ 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000001, 0x201fff00, 0x006f00c4,
+ 0x03051000, 0x00000820, 0x00000000, 0x00000000, 0xaaaaaaaa,
+ 0x3c466478, 0x0cc80caa, 0x00001042, 0x4080a333, 0x40206c10,
+ 0x009c4060, 0x01834061, 0x00000400, 0x000003b5, 0x23277200,
+ 0x20202020, 0x20202020, 0x13c889af, 0x38490a20, 0x00007bb6,
+ 0x0fff3ffc, 0x00000001, 0x001da000, 0x00000000, 0x0cdbd380,
+ 0x0f0f0f01, 0xdfa91f01, 0x00000000, 0x0ebae9c6, 0x0ebae9c6,
+ 0x00820820, 0x1ce739ce, 0x050701ce, 0x7999aa0f, 0x07ffffef,
+ 0x0fffffe7, 0x17ffffe5, 0x1fffffe4, 0x37ffffe3, 0x3fffffe3,
+ 0x57ffffe3, 0x5fffffe2, 0x7fffffe2, 0x7f3c7bba, 0xf3307ff0,
+ 0x0c000000, 0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce,
+ 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000246, 0x20202020, 0x20202020, 0x20202020,
+ 0x1ce739ce, 0x000001ce, 0x00000000, 0x18c43433, 0x00f38081,
+ 0x00040000, 0xdb005012, 0x04924914, 0x21084210, 0x6d801300,
+ 0x0019beff, 0x07e40000, 0x00492000, 0x92492480, 0x00040000,
+ 0xdb005012, 0x04924914, 0x21084210, 0x6d801300, 0x0019beff,
+ 0x07e40000, 0x00492000, 0x92492480, 0x00120000, 0x54214514,
+ 0x92592692, 0x52802000, 0x0a8e370e, 0xc0102850, 0x812d4000,
+ 0x001b6db0, 0x00376b63, 0x06db6db6, 0x006d8000, 0xffeffffe,
+ 0xffeffffe, 0x00060aeb, 0x5a108000, 0x2a850160
+};
+
+static const struct athn_ini ar9280_1_0_ini = {
+ nitems(ar9280_1_0_regs),
+ ar9280_1_0_regs,
+ ar9280_1_0_vals_5g20,
+#ifndef IEEE80211_NO_HT
+ ar9280_1_0_vals_5g40,
+ ar9280_1_0_vals_2g40,
+#endif
+ ar9280_1_0_vals_2g20,
+ nitems(ar9280_1_0_cm_regs),
+ ar9280_1_0_cm_regs,
+ ar9280_1_0_cm_vals
+};
+
+/*
+ * AR9280 2.0 initialization values.
+ */
+static const uint16_t ar9280_2_0_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x08120), P(0x081d0), P(0x08318), P(0x09804),
+ P(0x09820), P(0x09824), P(0x09828), P(0x09834), P(0x09838),
+ P(0x09840), P(0x09844), P(0x09850), P(0x09858), P(0x0985c),
+ P(0x09860), P(0x09864), P(0x09868), P(0x0986c), P(0x09914),
+ P(0x09918), P(0x09924), P(0x09944), P(0x09960), P(0x0a960),
+ P(0x09964), P(0x0c968), P(0x099b8), P(0x099bc), P(0x099c0),
+ P(0x099c4), P(0x099c8), P(0x099cc), P(0x099d0), P(0x099d4),
+ P(0x099d8), P(0x0a204), P(0x0a20c), P(0x0b20c), P(0x0a21c),
+ P(0x0a230), P(0x0a23c), P(0x0a250), P(0x0a358), P(0x0a388),
+ P(0x0a3d8), P(0x07894)
+};
+
+static const uint32_t ar9280_2_0_vals_5g20[] = {
+ 0x00000230, 0x00000168, 0x00000e60, 0x00000000, 0x03e803e8,
+ 0x128d8027, 0x08f04800, 0x00003210, 0x00003e80, 0x00000300,
+ 0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
+ 0x206a022e, 0x0372161e, 0x6c4000e2, 0x7ec88d2e, 0x31395d5e,
+ 0x00048d18, 0x0001ce00, 0x5ac640d0, 0x06903081, 0x000007d0,
+ 0x0000000a, 0xd00a8a0b, 0xffbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003b5, 0x0000001c, 0x00000a00, 0x05eea6d4,
+ 0x06336f77, 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000444, 0x00000014, 0x00000014, 0x1883800a,
+ 0x00000000, 0x13c88000, 0x001ff000, 0x7999aa02, 0x0c000000,
+ 0x00000000, 0x5a508000
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar9280_2_0_vals_5g40[] = {
+ 0x00000460, 0x000002d0, 0x00001cc0, 0x00000000, 0x07d007d0,
+ 0x128d804f, 0x08f04800, 0x00003210, 0x00007d00, 0x000003c4,
+ 0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
+ 0x206a022e, 0x0372161e, 0x6d4000e2, 0x7ec88d2e, 0x3139605e,
+ 0x00048d18, 0x0001ce00, 0x5ac640d0, 0x06903081, 0x00000fa0,
+ 0x00000014, 0xd00a8a0b, 0xffbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003b5, 0x0000001c, 0x00000a00, 0x05eea6d4,
+ 0x06336f77, 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000444, 0x00000014, 0x00000014, 0x1883800a,
+ 0x00000000, 0x13c88000, 0x001ff000, 0x7999aa02, 0x0c000000,
+ 0x00000000, 0x5a508000
+};
+
+static const uint32_t ar9280_2_0_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00000000, 0x10801600,
+ 0x12e00057, 0x08f04810, 0x0000320a, 0x00006880, 0x000003c4,
+ 0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
+ 0x206a012e, 0x037216a0, 0x6d4000e2, 0x7ec84d2e, 0x3139605e,
+ 0x00048d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00001130,
+ 0x00000268, 0xd00a8a0d, 0xffbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
+ 0x06336f77, 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000444, 0x0001f019, 0x0001f019, 0x1883800a,
+ 0x00000210, 0x13c88001, 0x0004a000, 0x7999aa0e, 0x08000000,
+ 0x00000000, 0x5a508000
+};
+#endif
+
+static const uint32_t ar9280_2_0_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x00000000, 0x08400b00,
+ 0x12e0002b, 0x08f04810, 0x0000320a, 0x00003440, 0x00000300,
+ 0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
+ 0x206a012e, 0x037216a0, 0x6c4000e2, 0x7ec84d2e, 0x31395d5e,
+ 0x00048d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00000898,
+ 0x0000000b, 0xd00a8a0d, 0xffbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
+ 0x06336f77, 0x60f65329, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0x00000444, 0x0001f019, 0x0001f019, 0x1883800a,
+ 0x00000108, 0x13c88000, 0x0004a000, 0x7999aa0e, 0x0c000000,
+ 0x00000000, 0x5a508000
+};
+
+static const uint16_t ar9280_2_0_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x04060),
+ P(0x04064), P(0x07010), P(0x07034), P(0x07038), P(0x08004),
+ P(0x08008), P(0x0800c), P(0x08018), P(0x08020), P(0x08038),
+ P(0x0803c), P(0x08048), P(0x08054), P(0x08058), P(0x0805c),
+ P(0x08060), P(0x08064), P(0x08070), P(0x080c0), P(0x080c4),
+ P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
+ P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
+ P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
+ P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
+ P(0x08124), P(0x08128), P(0x0812c), P(0x08130), P(0x08134),
+ P(0x08138), P(0x0813c), P(0x08144), P(0x08168), P(0x0816c),
+ P(0x08170), P(0x08174), P(0x08178), P(0x0817c), P(0x081c0),
+ P(0x081ec), P(0x081f0), P(0x081f4), P(0x081f8), P(0x081fc),
+ P(0x08200), P(0x08204), P(0x08208), P(0x0820c), P(0x08210),
+ P(0x08214), P(0x08218), P(0x0821c), P(0x08220), P(0x08224),
+ P(0x08228), P(0x0822c), P(0x08230), P(0x08234), P(0x08238),
+ P(0x0823c), P(0x08240), P(0x08244), P(0x08248), P(0x0824c),
+ P(0x08250), P(0x08254), P(0x08258), P(0x0825c), P(0x08260),
+ P(0x08264), P(0x08270), P(0x08274), P(0x08278), P(0x0827c),
+ P(0x08284), P(0x08288), P(0x0828c), P(0x08294), P(0x08298),
+ P(0x0829c), P(0x08300), P(0x08314), P(0x08328), P(0x0832c),
+ P(0x08330), P(0x08334), P(0x08338), P(0x0833c), P(0x08340),
+ P(0x08344), P(0x09808), P(0x0980c), P(0x09810), P(0x09814),
+ P(0x0981c), P(0x0982c), P(0x09830), P(0x0983c), P(0x0984c),
+ P(0x0a84c), P(0x09854), P(0x09900), P(0x09904), P(0x09908),
+ P(0x0990c), P(0x09910), P(0x0991c), P(0x09920), P(0x0a920),
+ P(0x09928), P(0x0992c), P(0x09934), P(0x09938), P(0x0993c),
+ P(0x09948), P(0x0994c), P(0x09954), P(0x09958), P(0x09940),
+ P(0x0c95c), P(0x09970), P(0x09974), P(0x09978), P(0x0997c),
+ P(0x09980), P(0x09984), P(0x09988), P(0x0998c), P(0x09990),
+ P(0x09994), P(0x09998), P(0x0999c), P(0x099a0), P(0x099a4),
+ P(0x099a8), P(0x099ac), P(0x099b0), P(0x099b4), P(0x099dc),
+ P(0x099e0), P(0x099e4), P(0x099e8), P(0x099ec), P(0x099f0),
+ P(0x099fc), P(0x0a208), P(0x0a210), P(0x0a214), P(0x0a218),
+ P(0x0a220), P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234),
+ P(0x0a238), P(0x0a240), P(0x0a244), P(0x0a248), P(0x0a24c),
+ P(0x0a254), P(0x0a258), P(0x0a25c), P(0x0a260), P(0x0a268),
+ P(0x0a26c), P(0x0b26c), P(0x0d270), P(0x0a278), P(0x0d35c),
+ P(0x0d360), P(0x0d364), P(0x0d368), P(0x0d36c), P(0x0d370),
+ P(0x0d374), P(0x0d378), P(0x0d37c), P(0x0d380), P(0x0d384),
+ P(0x0a38c), P(0x0a390), P(0x0a394), P(0x0a398), P(0x0a39c),
+ P(0x0a3a0), P(0x0a3a4), P(0x0a3a8), P(0x0a3ac), P(0x0a3b0),
+ P(0x0a3b4), P(0x0a3b8), P(0x0a3bc), P(0x0a3c0), P(0x0a3c4),
+ P(0x0a3c8), P(0x0a3cc), P(0x0a3d0), P(0x0a3d4), P(0x0a3dc),
+ P(0x0a3e0), P(0x0a3e4), P(0x0a3e8), P(0x0a3ec), P(0x07800),
+ P(0x07804), P(0x07808), P(0x0780c), P(0x07810), P(0x07818),
+ P(0x07824), P(0x07828), P(0x0782c), P(0x07830), P(0x07834),
+ P(0x0783c), P(0x07848), P(0x0784c), P(0x07850), P(0x07854),
+ P(0x07858), P(0x07860), P(0x07864), P(0x07868), P(0x0786c),
+ P(0x07870), P(0x07874), P(0x07878), P(0x0787c), P(0x07880),
+ P(0x07884), P(0x07888), P(0x0788c), P(0x07890), P(0x07898)
+};
+
+static const uint32_t ar9280_2_0_cm_vals[] = {
+ 0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000033, 0x00000002, 0x000004c2, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000700, 0x00000000, 0x00000000,
+ 0x00000000, 0x40000000, 0x00000000, 0x00000000, 0x000fc78f,
+ 0x0000000f, 0x00000000, 0x00000000, 0x2a80001a, 0x05dc01e0,
+ 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
+ 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
+ 0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
+ 0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00100000, 0x0010f400, 0x00000100, 0x0001e800,
+ 0x00000000, 0x00000000, 0x00000000, 0x400000ff, 0x00080922,
+ 0xa8a00010, 0x00000000, 0x40000000, 0x003e4180, 0x00000000,
+ 0x0000002c, 0x0000002c, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000007,
+ 0x00000302, 0x00000e00, 0x00ff0000, 0x00000000, 0x000107ff,
+ 0x00481043, 0x00000000, 0xafa68e30, 0xfd14e000, 0x9c0a9f6b,
+ 0x00000000, 0x0000a000, 0x00000000, 0x00200400, 0x0040233c,
+ 0x0040233c, 0x00000044, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x01002310, 0x10000fff, 0x04900000, 0x04900000,
+ 0x00000001, 0x00000004, 0x1e1f2022, 0x0a0b0c0d, 0x00000000,
+ 0x9280c00a, 0x00020028, 0x5f3ca3de, 0x2108ecff, 0x14750604,
+ 0x004b6a8e, 0x190fb515, 0x00000000, 0x00000001, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
+ 0x201fff00, 0x006f0000, 0x03051000, 0x00000820, 0x00000000,
+ 0x00000000, 0xaaaaaaaa, 0x3c466478, 0x0cc80caa, 0x00000000,
+ 0x00001042, 0x803e4788, 0x4080a333, 0x40206c10, 0x009c4060,
+ 0x01834061, 0x00000400, 0x000003b5, 0x233f7180, 0x20202020,
+ 0x20202020, 0x38490a20, 0x00007bb6, 0x0fff3ffc, 0x00000000,
+ 0x00000000, 0x0cdbd380, 0x0f0f0f01, 0xdfa91f01, 0x00000000,
+ 0x0e79e5c6, 0x0e79e5c6, 0x00820820, 0x1ce739ce, 0x07ffffef,
+ 0x0fffffe7, 0x17ffffe5, 0x1fffffe4, 0x37ffffe3, 0x3fffffe3,
+ 0x57ffffe3, 0x5fffffe2, 0x7fffffe2, 0x7f3c7bba, 0xf3307ff0,
+ 0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce, 0x00000001,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000246, 0x20202020, 0x20202020, 0x20202020, 0x1ce739ce,
+ 0x000001ce, 0x00000000, 0x18c43433, 0x00f70081, 0x00040000,
+ 0xdb005012, 0x04924914, 0x21084210, 0x6d801300, 0x07e41000,
+ 0x00040000, 0xdb005012, 0x04924914, 0x21084210, 0x6d801300,
+ 0x07e40000, 0x00100000, 0x773f0567, 0x54214514, 0x12035828,
+ 0x9259269a, 0x52802000, 0x0a8e370e, 0xc0102850, 0x812d4000,
+ 0x807ec400, 0x001b6db0, 0x00376b63, 0x06db6db6, 0x006d8000,
+ 0xffeffffe, 0xffeffffe, 0x00010000, 0x02060aeb, 0x2a850160
+};
+
+static const struct athn_ini ar9280_2_0_ini = {
+ nitems(ar9280_2_0_regs),
+ ar9280_2_0_regs,
+ ar9280_2_0_vals_5g20,
+#ifndef IEEE80211_NO_HT
+ ar9280_2_0_vals_5g40,
+ ar9280_2_0_vals_2g40,
+#endif
+ ar9280_2_0_vals_2g20,
+ nitems(ar9280_2_0_cm_regs),
+ ar9280_2_0_cm_regs,
+ ar9280_2_0_cm_vals
+};
+
+/*
+ * AR9280 2.0 Tx gains.
+ */
+static const uint16_t ar9280_2_0_tx_gain_regs[] = {
+ P(0x0a274), P(0x0a27c), P(0x0a300), P(0x0a304), P(0x0a308),
+ P(0x0a30c), P(0x0a310), P(0x0a314), P(0x0a318), P(0x0a31c),
+ P(0x0a320), P(0x0a324), P(0x0a328), P(0x0a32c), P(0x0a330),
+ P(0x0a334), P(0x0a338), P(0x0a33c), P(0x0a340), P(0x0a344),
+ P(0x0a348), P(0x0a34c), P(0x0a350), P(0x0a354), P(0x07814),
+ P(0x07838), P(0x0781c), P(0x07840), P(0x07820), P(0x07844)
+};
+
+static const uint32_t ar9280_2_0_tx_gain_vals_5g[] = {
+ 0x0a19c652, 0x050701ce, 0x00000000, 0x00003002, 0x00006004,
+ 0x0000a006, 0x0000e012, 0x00011014, 0x0001504a, 0x0001904c,
+ 0x0001c04e, 0x00020092, 0x0002410a, 0x0002710c, 0x0002b18b,
+ 0x0002e1cc, 0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec,
+ 0x000321ec, 0x000321ec, 0x000321ec, 0x000321ec, 0x0019beff,
+ 0x0019beff, 0x00392000, 0x00392000, 0x92592480, 0x92592480
+};
+
+static const uint32_t ar9280_2_0_tx_gain_vals_2g[] = {
+ 0x0a1aa652, 0x050701ce, 0x00000000, 0x00003002, 0x00008009,
+ 0x0000b00b, 0x0000e012, 0x00012048, 0x0001604a, 0x0001a211,
+ 0x0001e213, 0x0002121b, 0x00024412, 0x00028414, 0x0002b44a,
+ 0x00030649, 0x0003364b, 0x00038a49, 0x0003be48, 0x0003ee4a,
+ 0x00042e88, 0x00046e8a, 0x00049ec9, 0x0004bf42, 0x0019beff,
+ 0x0019beff, 0x00392000, 0x00392000, 0x92592480, 0x92592480
+};
+
+static const struct athn_gain ar9280_2_0_tx_gain = {
+ nitems(ar9280_2_0_tx_gain_regs),
+ ar9280_2_0_tx_gain_regs,
+ ar9280_2_0_tx_gain_vals_5g,
+ ar9280_2_0_tx_gain_vals_2g
+};
+
+static const uint32_t ar9280_2_0_tx_gain_high_power_vals_5g[] = {
+ 0x0a19e652, 0x050739ce, 0x00000000, 0x00003002, 0x00006004,
+ 0x0000a006, 0x0000e012, 0x00011014, 0x0001504a, 0x0001904c,
+ 0x0001c04e, 0x00021092, 0x0002510a, 0x0002910c, 0x0002c18b,
+ 0x0002f1cc, 0x000321eb, 0x000341ec, 0x000341ec, 0x000341ec,
+ 0x000341ec, 0x000341ec, 0x000341ec, 0x000341ec, 0x00198eff,
+ 0x00198eff, 0x00172000, 0x00172000, 0xf258a480, 0xf258a480
+};
+
+static const uint32_t ar9280_2_0_tx_gain_high_power_vals_2g[] = {
+ 0x0a1aa652, 0x050739ce, 0x00000000, 0x00004002, 0x00007008,
+ 0x0000c010, 0x00010012, 0x00013014, 0x0001820a, 0x0001b211,
+ 0x0001e213, 0x00022411, 0x00025413, 0x00029811, 0x0002c813,
+ 0x00030a14, 0x00035a50, 0x00039c4c, 0x0003de8a, 0x00042e92,
+ 0x00046ed2, 0x0004bed5, 0x0004ff54, 0x00055fd5, 0x00198eff,
+ 0x00198eff, 0x00172000, 0x00172000, 0xf258a480, 0xf258a480
+};
+
+static const struct athn_gain ar9280_2_0_tx_gain_high_power = {
+ nitems(ar9280_2_0_tx_gain_regs),
+ ar9280_2_0_tx_gain_regs,
+ ar9280_2_0_tx_gain_high_power_vals_5g,
+ ar9280_2_0_tx_gain_high_power_vals_2g
+};
+
+/*
+ * AR9280 2.0 Rx gains.
+ */
+static const uint16_t ar9280_2_0_rx_gain_regs[] = {
+ P(0x09a00), P(0x09a04), P(0x09a08), P(0x09a0c), P(0x09a10),
+ P(0x09a14), P(0x09a18), P(0x09a1c), P(0x09a20), P(0x09a24),
+ P(0x09a28), P(0x09a2c), P(0x09a30), P(0x09a34), P(0x09a38),
+ P(0x09a3c), P(0x09a40), P(0x09a44), P(0x09a48), P(0x09a4c),
+ P(0x09a50), P(0x09a54), P(0x09a58), P(0x09a5c), P(0x09a60),
+ P(0x09a64), P(0x09a68), P(0x09a6c), P(0x09a70), P(0x09a74),
+ P(0x09a78), P(0x09a7c), P(0x09a80), P(0x09a84), P(0x09a88),
+ P(0x09a8c), P(0x09a90), P(0x09a94), P(0x09a98), P(0x09a9c),
+ P(0x09aa0), P(0x09aa4), P(0x09aa8), P(0x09aac), P(0x09ab0),
+ P(0x09ab4), P(0x09ab8), P(0x09abc), P(0x09ac0), P(0x09ac4),
+ P(0x09ac8), P(0x09acc), P(0x09ad0), P(0x09ad4), P(0x09ad8),
+ P(0x09adc), P(0x09ae0), P(0x09ae4), P(0x09ae8), P(0x09aec),
+ P(0x09af0), P(0x09af4), P(0x09af8), P(0x09afc), P(0x09b00),
+ P(0x09b04), P(0x09b08), P(0x09b0c), P(0x09b10), P(0x09b14),
+ P(0x09b18), P(0x09b1c), P(0x09b20), P(0x09b24), P(0x09b28),
+ P(0x09b2c), P(0x09b30), P(0x09b34), P(0x09b38), P(0x09b3c),
+ P(0x09b40), P(0x09b44), P(0x09b48), P(0x09b4c), P(0x09b50),
+ P(0x09b54), P(0x09b58), P(0x09b5c), P(0x09b60), P(0x09b64),
+ P(0x09b68), P(0x09b6c), P(0x09b70), P(0x09b74), P(0x09b78),
+ P(0x09b7c), P(0x09b80), P(0x09b84), P(0x09b88), P(0x09b8c),
+ P(0x09b90), P(0x09b94), P(0x09b98), P(0x09b9c), P(0x09ba0),
+ P(0x09ba4), P(0x09ba8), P(0x09bac), P(0x09bb0), P(0x09bb4),
+ P(0x09bb8), P(0x09bbc), P(0x09bc0), P(0x09bc4), P(0x09bc8),
+ P(0x09bcc), P(0x09bd0), P(0x09bd4), P(0x09bd8), P(0x09bdc),
+ P(0x09be0), P(0x09be4), P(0x09be8), P(0x09bec), P(0x09bf0),
+ P(0x09bf4), P(0x09bf8), P(0x09bfc), P(0x09848), P(0x0a848)
+};
+
+static const uint32_t ar9280_2_0_rx_gain_vals_5g[] = {
+ 0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
+ 0x00008200, 0x00008204, 0x00008208, 0x0000820c, 0x00008210,
+ 0x00008214, 0x00008280, 0x00008284, 0x00008288, 0x0000828c,
+ 0x00008290, 0x00008300, 0x00008304, 0x00008308, 0x0000830c,
+ 0x00008310, 0x00008314, 0x00008380, 0x00008384, 0x00008388,
+ 0x0000838c, 0x00008390, 0x00008394, 0x0000a380, 0x0000a384,
+ 0x0000a388, 0x0000a38c, 0x0000a390, 0x0000a394, 0x0000a780,
+ 0x0000a784, 0x0000a788, 0x0000a78c, 0x0000a790, 0x0000a794,
+ 0x0000ab84, 0x0000ab88, 0x0000ab8c, 0x0000ab90, 0x0000ab94,
+ 0x0000af80, 0x0000af84, 0x0000af88, 0x0000af8c, 0x0000af90,
+ 0x0000af94, 0x0000b380, 0x0000b384, 0x0000b388, 0x0000b38c,
+ 0x0000b390, 0x0000b394, 0x0000b398, 0x0000b780, 0x0000b784,
+ 0x0000b788, 0x0000b78c, 0x0000b790, 0x0000b794, 0x0000b798,
+ 0x0000d784, 0x0000d788, 0x0000d78c, 0x0000d790, 0x0000f780,
+ 0x0000f784, 0x0000f788, 0x0000f78c, 0x0000f790, 0x0000f794,
+ 0x0000f7a4, 0x0000f7a8, 0x0000f7ac, 0x0000f7b0, 0x0000f7b4,
+ 0x0000f7a1, 0x0000f7a5, 0x0000f7a9, 0x0000f7ad, 0x0000f7b1,
+ 0x0000f7b5, 0x0000f7c5, 0x0000f7c9, 0x0000f7cd, 0x0000f7d1,
+ 0x0000f7d5, 0x0000f7c2, 0x0000f7c6, 0x0000f7ca, 0x0000f7ce,
+ 0x0000f7d2, 0x0000f7d6, 0x0000f7c3, 0x0000f7c7, 0x0000f7cb,
+ 0x0000f7d3, 0x0000f7d7, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x00001066, 0x00001066
+};
+
+static const uint32_t ar9280_2_0_rx_gain_vals_2g[] = {
+ 0x00000290, 0x00000300, 0x00000304, 0x00000308, 0x0000030c,
+ 0x00008000, 0x00008004, 0x00008008, 0x0000800c, 0x00008080,
+ 0x00008084, 0x00008088, 0x0000808c, 0x00008100, 0x00008104,
+ 0x00008108, 0x0000810c, 0x00008110, 0x00008114, 0x00008180,
+ 0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
+ 0x000081a0, 0x0000820c, 0x000081a8, 0x00008284, 0x00008288,
+ 0x00008224, 0x00008290, 0x00008300, 0x00008304, 0x00008308,
+ 0x0000830c, 0x00008380, 0x00008384, 0x00008700, 0x00008704,
+ 0x00008708, 0x0000870c, 0x00008780, 0x00008784, 0x00008b00,
+ 0x00008b04, 0x00008b08, 0x00008b0c, 0x00008b80, 0x00008b84,
+ 0x00008b88, 0x00008b8c, 0x00008b90, 0x00008f80, 0x00008f84,
+ 0x00008f88, 0x00008f8c, 0x00008f90, 0x0000930c, 0x00009310,
+ 0x00009384, 0x00009388, 0x00009324, 0x00009704, 0x000096a4,
+ 0x000096a8, 0x00009710, 0x00009714, 0x00009720, 0x00009724,
+ 0x00009728, 0x0000972c, 0x000097a0, 0x000097a4, 0x000097a8,
+ 0x000097b0, 0x000097b4, 0x000097b8, 0x000097a5, 0x000097a9,
+ 0x000097ad, 0x000097b1, 0x000097b5, 0x000097b9, 0x000097c5,
+ 0x000097c9, 0x000097d1, 0x000097d5, 0x000097d9, 0x000097c6,
+ 0x000097ca, 0x000097ce, 0x000097d2, 0x000097d6, 0x000097c3,
+ 0x000097c7, 0x000097cb, 0x000097cf, 0x000097d7, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x000097db, 0x000097db,
+ 0x000097db, 0x000097db, 0x000097db, 0x00001063, 0x00001063
+};
+
+static const struct athn_gain ar9280_2_0_rx_gain = {
+ nitems(ar9280_2_0_rx_gain_regs),
+ ar9280_2_0_rx_gain_regs,
+ ar9280_2_0_rx_gain_vals_5g,
+ ar9280_2_0_rx_gain_vals_2g
+};
+
+static const uint32_t ar9280_2_0_rx_gain_13db_backoff_vals_5g[] = {
+ 0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
+ 0x00008200, 0x00008204, 0x00008208, 0x0000820c, 0x00008210,
+ 0x00008214, 0x00008280, 0x00008284, 0x00008288, 0x0000828c,
+ 0x00008290, 0x00008300, 0x00008304, 0x00008308, 0x0000830c,
+ 0x00008310, 0x00008314, 0x00008380, 0x00008384, 0x00008388,
+ 0x0000838c, 0x00008390, 0x00008394, 0x0000a380, 0x0000a384,
+ 0x0000a388, 0x0000a38c, 0x0000a390, 0x0000a394, 0x0000a780,
+ 0x0000a784, 0x0000a788, 0x0000a78c, 0x0000a790, 0x0000a794,
+ 0x0000ab84, 0x0000ab88, 0x0000ab8c, 0x0000ab90, 0x0000ab94,
+ 0x0000af80, 0x0000af84, 0x0000af88, 0x0000af8c, 0x0000af90,
+ 0x0000af94, 0x0000b380, 0x0000b384, 0x0000b388, 0x0000b38c,
+ 0x0000b390, 0x0000b394, 0x0000b398, 0x0000b780, 0x0000b784,
+ 0x0000b788, 0x0000b78c, 0x0000b790, 0x0000b794, 0x0000b798,
+ 0x0000d784, 0x0000d788, 0x0000d78c, 0x0000d790, 0x0000f780,
+ 0x0000f784, 0x0000f788, 0x0000f78c, 0x0000f790, 0x0000f794,
+ 0x0000f7a4, 0x0000f7a8, 0x0000f7ac, 0x0000f7b0, 0x0000f7b4,
+ 0x0000f7a1, 0x0000f7a5, 0x0000f7a9, 0x0000f7ad, 0x0000f7b1,
+ 0x0000f7b5, 0x0000f7c5, 0x0000f7c9, 0x0000f7cd, 0x0000f7d1,
+ 0x0000f7d5, 0x0000f7c2, 0x0000f7c6, 0x0000f7ca, 0x0000f7ce,
+ 0x0000f7d2, 0x0000f7d6, 0x0000f7c3, 0x0000f7c7, 0x0000f7cb,
+ 0x0000f7d3, 0x0000f7d7, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x00001066, 0x00001066
+};
+
+static const uint32_t ar9280_2_0_rx_gain_13db_backoff_vals_2g[] = {
+ 0x00000290, 0x00000300, 0x00000304, 0x00000308, 0x0000030c,
+ 0x00008000, 0x00008004, 0x00008008, 0x0000800c, 0x00008080,
+ 0x00008084, 0x00008088, 0x0000808c, 0x00008100, 0x00008104,
+ 0x00008108, 0x0000810c, 0x00008110, 0x00008114, 0x00008180,
+ 0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
+ 0x000081a0, 0x0000820c, 0x000081a8, 0x00008284, 0x00008288,
+ 0x00008224, 0x00008290, 0x00008300, 0x00008304, 0x00008308,
+ 0x0000830c, 0x00008380, 0x00008384, 0x00008700, 0x00008704,
+ 0x00008708, 0x0000870c, 0x00008780, 0x00008784, 0x00008b00,
+ 0x00008b04, 0x00008b08, 0x00008b0c, 0x00008b80, 0x00008b84,
+ 0x00008b88, 0x00008b8c, 0x00008b90, 0x00008f80, 0x00008f84,
+ 0x00008f88, 0x00008f8c, 0x00008f90, 0x00009310, 0x00009314,
+ 0x00009320, 0x00009324, 0x00009328, 0x0000932c, 0x00009330,
+ 0x00009334, 0x00009321, 0x00009325, 0x00009329, 0x0000932d,
+ 0x00009331, 0x00009335, 0x00009322, 0x00009326, 0x0000932a,
+ 0x0000932e, 0x00009332, 0x00009336, 0x00009323, 0x00009327,
+ 0x0000932b, 0x0000932f, 0x00009333, 0x00009337, 0x00009343,
+ 0x00009347, 0x0000934b, 0x0000934f, 0x00009353, 0x00009357,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b, 0x0000935b,
+ 0x0000935b, 0x0000935b, 0x0000935b, 0x0000105a, 0x0000105a
+};
+
+static const struct athn_gain ar9280_2_0_rx_gain_13db_backoff = {
+ nitems(ar9280_2_0_rx_gain_regs),
+ ar9280_2_0_rx_gain_regs,
+ ar9280_2_0_rx_gain_13db_backoff_vals_5g,
+ ar9280_2_0_rx_gain_13db_backoff_vals_2g
+};
+
+static const uint32_t ar9280_2_0_rx_gain_23db_backoff_vals_5g[] = {
+ 0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
+ 0x00008200, 0x00008204, 0x00008208, 0x0000820c, 0x00008210,
+ 0x00008214, 0x00008280, 0x00008284, 0x00008288, 0x0000828c,
+ 0x00008290, 0x00008300, 0x00008304, 0x00008308, 0x0000830c,
+ 0x00008310, 0x00008314, 0x00008380, 0x00008384, 0x00008388,
+ 0x0000838c, 0x00008390, 0x00008394, 0x0000a380, 0x0000a384,
+ 0x0000a388, 0x0000a38c, 0x0000a390, 0x0000a394, 0x0000a780,
+ 0x0000a784, 0x0000a788, 0x0000a78c, 0x0000a790, 0x0000a794,
+ 0x0000ab84, 0x0000ab88, 0x0000ab8c, 0x0000ab90, 0x0000ab94,
+ 0x0000af80, 0x0000af84, 0x0000af88, 0x0000af8c, 0x0000af90,
+ 0x0000af94, 0x0000b380, 0x0000b384, 0x0000b388, 0x0000b38c,
+ 0x0000b390, 0x0000b394, 0x0000b398, 0x0000b780, 0x0000b784,
+ 0x0000b788, 0x0000b78c, 0x0000b790, 0x0000b794, 0x0000b798,
+ 0x0000d784, 0x0000d788, 0x0000d78c, 0x0000d790, 0x0000f780,
+ 0x0000f784, 0x0000f788, 0x0000f78c, 0x0000f790, 0x0000f794,
+ 0x0000f7a4, 0x0000f7a8, 0x0000f7ac, 0x0000f7b0, 0x0000f7b4,
+ 0x0000f7a1, 0x0000f7a5, 0x0000f7a9, 0x0000f7ad, 0x0000f7b1,
+ 0x0000f7b5, 0x0000f7c5, 0x0000f7c9, 0x0000f7cd, 0x0000f7d1,
+ 0x0000f7d5, 0x0000f7c2, 0x0000f7c6, 0x0000f7ca, 0x0000f7ce,
+ 0x0000f7d2, 0x0000f7d6, 0x0000f7c3, 0x0000f7c7, 0x0000f7cb,
+ 0x0000f7d3, 0x0000f7d7, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x0000f7db,
+ 0x0000f7db, 0x0000f7db, 0x0000f7db, 0x00001066, 0x00001066
+};
+
+static const uint32_t ar9280_2_0_rx_gain_23db_backoff_vals_2g[] = {
+ 0x00000290, 0x00000300, 0x00000304, 0x00000308, 0x0000030c,
+ 0x00008000, 0x00008004, 0x00008008, 0x0000800c, 0x00008080,
+ 0x00008084, 0x00008088, 0x0000808c, 0x00008100, 0x00008104,
+ 0x00008108, 0x0000810c, 0x00008110, 0x00008114, 0x00008180,
+ 0x00008184, 0x00008188, 0x0000818c, 0x00008190, 0x00008194,
+ 0x000081a0, 0x0000820c, 0x000081a8, 0x00008284, 0x00008288,
+ 0x00008224, 0x00008290, 0x00008300, 0x00008304, 0x00008308,
+ 0x0000830c, 0x00008380, 0x00008384, 0x00008700, 0x00008704,
+ 0x00008708, 0x0000870c, 0x00008780, 0x00008784, 0x00008b00,
+ 0x00008b04, 0x00008b08, 0x00008b0c, 0x00008b10, 0x00008b14,
+ 0x00008b01, 0x00008b05, 0x00008b09, 0x00008b0d, 0x00008b11,
+ 0x00008b15, 0x00008b02, 0x00008b06, 0x00008b0a, 0x00008b0e,
+ 0x00008b12, 0x00008b16, 0x00008b03, 0x00008b07, 0x00008b0b,
+ 0x00008b0f, 0x00008b13, 0x00008b17, 0x00008b23, 0x00008b27,
+ 0x00008b2b, 0x00008b2f, 0x00008b33, 0x00008b37, 0x00008b43,
+ 0x00008b47, 0x00008b4b, 0x00008b4f, 0x00008b53, 0x00008b57,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00008b5b,
+ 0x00008b5b, 0x00008b5b, 0x00008b5b, 0x00001050, 0x00001050
+};
+
+static const struct athn_gain ar9280_2_0_rx_gain_23db_backoff = {
+ nitems(ar9280_2_0_rx_gain_regs),
+ ar9280_2_0_rx_gain_regs,
+ ar9280_2_0_rx_gain_23db_backoff_vals_5g,
+ ar9280_2_0_rx_gain_23db_backoff_vals_2g
+};
+
+/*
+ * Serializer/Deserializer programming.
+ */
+static const uint32_t ar9280_1_0_serdes[] = {
+ 0x9248fd00,
+ 0x24924924,
+ 0xa8000019,
+ 0x13160820,
+ 0xe5980560,
+#ifdef ATHN_PCIE_CLKREQ
+ 0x401deffc,
+#else
+ 0x401deffd,
+#endif
+ 0x1aaabe40,
+ 0xbe105554,
+ 0x00043007
+};
+
+static const uint32_t ar9280_2_0_serdes[] = {
+ 0x9248fd00,
+ 0x24924924,
+ 0xa8000019,
+ 0x13160820,
+ 0xe5980560,
+#ifdef ATHN_PCIE_CLKREQ
+ 0xc01dcffc,
+#else
+ 0xc01dcffd,
+#endif
+ 0x1aaabe41,
+ 0xbe105554,
+ 0x00043007
+};
diff --git a/sys/dev/ic/ar9285.c b/sys/dev/ic/ar9285.c
new file mode 100644
index 00000000000..02d678f40bd
--- /dev/null
+++ b/sys/dev/ic/ar9285.c
@@ -0,0 +1,680 @@
+/* $OpenBSD: ar9285.c,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for Atheros 802.11a/g/n chipsets.
+ * Routines for AR9285 chipsets.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/timeout.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/endian.h>
+#include <machine/intr.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/ic/athnreg.h>
+#include <dev/ic/athnvar.h>
+
+#include <dev/ic/ar9280reg.h>
+#include <dev/ic/ar9285reg.h>
+
+int ar9285_attach(struct athn_softc *);
+void ar9285_setup(struct athn_softc *);
+void ar9285_swap_rom(struct athn_softc *);
+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 *);
+int ar9285_1_2_init_calib(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar9285_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
+ int, uint8_t, uint8_t *, uint8_t *);
+void ar9285_set_power_calib(struct athn_softc *,
+ struct ieee80211_channel *);
+void ar9285_set_txpower(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+
+int
+ar9285_attach(struct athn_softc *sc)
+{
+ sc->eep_base = AR9285_EEP_START_LOC;
+ sc->eep_size = sizeof (struct ar9285_eeprom);
+ sc->def_nf = AR9285_PHY_CCA_MAX_GOOD_VALUE;
+ sc->ngpiopins = 12;
+ sc->workaround = AR9285_WA_DEFAULT;
+ sc->ops.setup = ar9285_setup;
+ sc->ops.swap_rom = ar9285_swap_rom;
+ sc->ops.init_from_rom = ar9285_init_from_rom;
+ sc->ops.set_txpower = ar9285_set_txpower;
+ sc->ops.set_synth = ar9280_set_synth;
+ sc->ops.spur_mitigate = ar9280_spur_mitigate;
+ sc->ops.get_spur_chans = ar9285_get_spur_chans;
+ sc->ops.olpc_init = NULL;
+ if (AR_SREV_9285_12_OR_LATER(sc))
+ sc->ini = &ar9285_1_2_ini;
+ else
+ sc->ini = &ar9285_1_0_ini;
+ sc->serdes = ar9280_2_0_serdes;
+ return (0);
+}
+
+void
+ar9285_setup(struct athn_softc *sc)
+{
+ const struct ar9285_eeprom *eep = sc->eep;
+ uint8_t type;
+
+ if (AR_SREV_9285_12(sc)) {
+ /* Select initialization values based on ROM. */
+ type = eep->baseEepHeader.txGainType;
+ DPRINTF(("Tx gain type=0x%x\n", type));
+ if (type == AR_EEP_TXGAIN_HIGH_POWER)
+ sc->tx_gain = &ar9285_1_2_tx_gain_high_power;
+ else
+ sc->tx_gain = &ar9285_1_2_tx_gain;
+ }
+}
+
+void
+ar9285_swap_rom(struct athn_softc *sc)
+{
+ struct ar9285_eeprom *eep = sc->eep;
+ int i;
+
+ eep->modalHeader.antCtrlCommon =
+ swap32(eep->modalHeader.antCtrlCommon);
+ eep->modalHeader.antCtrlChain =
+ swap32(eep->modalHeader.antCtrlChain);
+
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ eep->modalHeader.spurChans[i].spurChan =
+ swap16(eep->modalHeader.spurChans[i].spurChan);
+ }
+}
+
+const struct ar_spur_chan *
+ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz)
+{
+ const struct ar9285_eeprom *eep = sc->eep;
+
+ KASSERT(is2ghz);
+ return eep->modalHeader.spurChans;
+}
+
+void
+ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ const struct ar9285_eeprom *eep = sc->eep;
+ const struct ar9285_modal_eep_header *modal = &eep->modalHeader;
+ uint32_t reg, offset = 0x1000;
+ uint8_t ob[5], db1[5], db2[5];
+ uint8_t txRxAtten;
+
+ AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon & 0xffff);
+ AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0, modal->antCtrlChain);
+
+ reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, modal->iqCalI);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, modal->iqCalQ);
+ AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg);
+
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
+ reg = AR_READ(sc, AR_PHY_GAIN_2GHZ);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ modal->bswMargin);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ modal->bswAtten);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ modal->xatten2Margin);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ modal->xatten2Db);
+ AR_WRITE(sc, AR_PHY_GAIN_2GHZ, reg);
+
+ /* Duplicate values of chain 0 for chain 1. */
+ reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ modal->bswMargin);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ modal->bswAtten);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ modal->xatten2Margin);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ modal->xatten2Db);
+ AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
+ }
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
+ txRxAtten = modal->txRxAtten;
+ else /* Workaround for ROM versions < 14.3. */
+ txRxAtten = 23;
+ reg = AR_READ(sc, AR_PHY_RXGAIN);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
+ AR_WRITE(sc, AR_PHY_RXGAIN, reg);
+
+ /* Duplicate values of chain 0 for chain 1. */
+ reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
+ AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
+
+ if (AR_SREV_9285_11(sc))
+ AR_WRITE(sc, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT | 0x14);
+
+ if (modal->version >= 3) {
+ /* Setup antenna diversity from ROM. */
+ reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL);
+ reg = RW(reg, AR9285_PHY_ANT_DIV_CTL_ALL, 0);
+ reg = RW(reg, AR9285_PHY_ANT_DIV_CTL,
+ (modal->ob_234 >> 12) & 0x1);
+ reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_LNACONF,
+ (modal->db1_234 >> 12) & 0x3);
+ reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_LNACONF,
+ (modal->db1_234 >> 14) & 0x1);
+ reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_GAINTB,
+ (modal->ob_234 >> 13) & 0x1);
+ reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_GAINTB,
+ (modal->ob_234 >> 14) & 0x1);
+ AR_WRITE(sc, AR_PHY_MULTICHAIN_GAIN_CTL, reg);
+ reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL); /* Flush. */
+
+ reg = AR_READ(sc, AR_PHY_CCK_DETECT);
+ if (modal->ob_234 & (1 << 15))
+ reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ else
+ reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
+ reg = AR_READ(sc, AR_PHY_CCK_DETECT); /* Flush. */
+ }
+ if (modal->version >= 2) {
+ ob [0] = (modal->ob_01 >> 0) & 0xf;
+ ob [1] = (modal->ob_01 >> 4) & 0xf;
+ ob [2] = (modal->ob_234 >> 0) & 0xf;
+ ob [3] = (modal->ob_234 >> 4) & 0xf;
+ ob [4] = (modal->ob_234 >> 8) & 0xf;
+
+ db1[0] = (modal->db1_01 >> 0) & 0xf;
+ db1[1] = (modal->db1_01 >> 4) & 0xf;
+ db1[2] = (modal->db1_234 >> 0) & 0xf;
+ db1[3] = (modal->db1_234 >> 4) & 0xf;
+ db1[4] = (modal->db1_234 >> 8) & 0xf;
+
+ db2[0] = (modal->db2_01 >> 0) & 0xf;
+ db2[1] = (modal->db2_01 >> 4) & 0xf;
+ db2[2] = (modal->db2_234 >> 0) & 0xf;
+ db2[3] = (modal->db2_234 >> 4) & 0xf;
+ db2[4] = (modal->db2_234 >> 8) & 0xf;
+
+ } else if (modal->version == 1) {
+ ob [0] = (modal->ob_01 >> 0) & 0xf;
+ ob [1] = (modal->ob_01 >> 4) & 0xf;
+ /* Field ob_234 does not exist, use ob_01. */
+ ob [2] = ob [3] = ob [4] = ob [1];
+
+ db1[0] = (modal->db1_01 >> 0) & 0xf;
+ db1[1] = (modal->db1_01 >> 4) & 0xf;
+ /* Field db1_234 does not exist, use db1_01. */
+ db1[2] = db1[3] = db1[4] = db1[1];
+
+ db2[0] = (modal->db2_01 >> 0) & 0xf;
+ db2[1] = (modal->db2_01 >> 4) & 0xf;
+ /* Field db2_234 does not exist, use db2_01. */
+ db2[2] = db2[3] = db2[4] = db2[1];
+
+ } else {
+ ob [0] = modal->ob_01;
+ ob [1] = ob [2] = ob [3] = ob [4] = ob [0];
+
+ db1[0] = modal->db1_01;
+ db1[1] = db1[2] = db1[3] = db1[4] = db1[0];
+
+ /* Field db2_01 does not exist, use db1_01. */
+ 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);
+ 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);
+ DELAY(100);
+
+ if (AR_SREV_9285_11(sc))
+ AR_WRITE(sc, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+ reg = AR_READ(sc, AR_PHY_SETTLING);
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
+ AR_WRITE(sc, AR_PHY_SETTLING, reg);
+
+ reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
+ reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
+ AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
+
+ reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
+
+ reg = AR_READ(sc, AR_PHY_RF_CTL3);
+ reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
+
+ reg = AR_READ(sc, AR_PHY_CCA(0));
+ reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_CCA(0), reg);
+
+ reg = AR_READ(sc, AR_PHY_EXT_CCA0);
+ reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
+
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
+ reg = AR_READ(sc, AR_PHY_RF_CTL2);
+ reg = RW(reg, AR_PHY_TX_END_PA_ON,
+ modal->txFrameToPaOn);
+ reg = RW(reg, AR_PHY_TX_END_DATA_START,
+ modal->txFrameToDataStart);
+ AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
+ }
+#ifndef IEEE80211_NO_HT
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
+ reg = AR_READ(sc, AR_PHY_SETTLING);
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
+ AR_WRITE(sc, AR_PHY_SETTLING, reg);
+ }
+#endif
+}
+
+void
+ar9285_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;
+
+ /* No PA calibration needed for high power solutions. */
+ if (AR_SREV_9285(sc) &&
+ ((struct ar9285_base_eep_header *)sc->eep)->txGainType ==
+ AR_EEP_TXGAIN_HIGH_POWER) /* XXX AR9287? */
+ return;
+
+ if (AR_SREV_9285_11(sc)) {
+ /* XXX magic 0x14. */
+ AR_WRITE(sc, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT | 0x14);
+ DELAY(10);
+ }
+
+ /* 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_RF2G6);
+ /* Save compensation capacitor value. */
+ ccomp_svg = MS(reg, AR9285_AN_RF2G6_CCOMP);
+ /* Program compensation capacitor for dynamic PA. */
+ reg = RW(reg, AR9285_AN_RF2G6_CCOMP, 0xf);
+ AR_WRITE(sc, AR9285_AN_RF2G6, reg);
+
+ AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
+ DELAY(30);
+
+ /* Clear offsets 6-1. */
+ 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));
+ DELAY(1);
+ if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9) {
+ AR_SETBITS(sc, AR9285_AN_RF2G6,
+ AR9285_AN_RF2G6_OFFS(i));
+ } else {
+ AR_CLRBITS(sc, AR9285_AN_RF2G6,
+ AR9285_AN_RF2G6_OFFS(i));
+ }
+ }
+ /* Set offset 0. */
+ AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
+ DELAY(1);
+ if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9)
+ AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
+ else
+ AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
+
+ 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_RF2G6);
+ reg = RW(reg, AR9285_AN_RF2G6_CCOMP, ccomp_svg);
+ AR_WRITE(sc, AR9285_AN_RF2G6, reg);
+
+ if (AR_SREV_9285_11(sc))
+ AR_WRITE(sc, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+}
+
+/*
+ * Carrier Leak Calibration (>= AR9285 1.2 only.)
+ */
+int
+ar9285_1_2_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ int ntries;
+
+ AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+ if (extc == NULL) { /* XXX IS_CHAN_HT20!! */
+ AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+ AR_SETBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+ AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
+ AR_CLRBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+ for (ntries = 0; ntries < 10000; ntries++) {
+ if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_CAL))
+ break;
+ DELAY(10);
+ }
+ if (ntries == 10000)
+ return (ETIMEDOUT);
+ AR_CLRBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
+ AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
+ AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+ }
+ AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+ AR_SETBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
+ for (ntries = 0; ntries < 10000; ntries++) {
+ if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_CAL))
+ break;
+ DELAY(10);
+ }
+ if (ntries == 10000)
+ return (ETIMEDOUT);
+ AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+ AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+ AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+ return (0);
+}
+
+void
+ar9285_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
+ int nxpdgains, uint8_t overlap, uint8_t *boundaries, uint8_t *pdadcs)
+{
+ const struct ar9285_eeprom *eep = sc->eep;
+ const struct ar9285_cal_data_per_freq *pierdata;
+ const uint8_t *pierfreq;
+ struct athn_pier lopier, hipier;
+ uint8_t fbin;
+ int i, lo, hi, npiers;
+
+ pierfreq = eep->calFreqPier2G;
+ pierdata = eep->calPierData2G;
+ npiers = AR9285_NUM_2G_CAL_PIERS;
+
+ /* Find channel in ROM pier table. */
+ fbin = athn_chan2fbin(c);
+ athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
+
+ lopier.fbin = pierfreq[lo];
+ hipier.fbin = pierfreq[hi];
+ for (i = 0; i < nxpdgains; i++) {
+ lopier.pwr[i] = pierdata[lo].pwrPdg[i];
+ lopier.vpd[i] = pierdata[lo].vpdPdg[i];
+ hipier.pwr[i] = pierdata[lo].pwrPdg[i];
+ hipier.vpd[i] = pierdata[lo].vpdPdg[i];
+ }
+ athn_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
+ AR9285_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
+}
+
+void
+ar9285_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ const struct ar9285_eeprom *eep = sc->eep;
+ uint8_t boundaries[AR_PD_GAINS_IN_MASK];
+ uint8_t pdadcs[AR_NUM_PDADC_VALUES];
+ uint8_t xpdgains[AR9285_NUM_PD_GAINS];
+ uint8_t overlap;
+ uint32_t reg;
+ int i, nxpdgains;
+
+ if (sc->eep_rev < AR_EEP_MINOR_VER_2) {
+ overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+ } else
+ overlap = eep->modalHeader.pdGainOverlap;
+
+ nxpdgains = 0;
+ memset(xpdgains, 0, sizeof xpdgains);
+ for (i = AR9285_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
+ if (nxpdgains >= AR9285_NUM_PD_GAINS)
+ break;
+ if (eep->modalHeader.xpdGain & (1 << i))
+ xpdgains[nxpdgains++] = i;
+ }
+ reg = AR_READ(sc, AR_PHY_TPCRG1);
+ reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
+ reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
+ reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
+ AR_WRITE(sc, AR_PHY_TPCRG1, reg);
+
+ /* NB: No open loop power control for AR9285. */
+ ar9285_get_pdadcs(sc, c, nxpdgains, overlap, boundaries, pdadcs);
+
+ /* Write boundaries. */
+ reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP, overlap);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1, boundaries[0]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2, boundaries[1]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3, boundaries[2]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4, boundaries[3]);
+ AR_WRITE(sc, AR_PHY_TPCRG5, reg);
+
+ /* Write PDADC values. */
+ for (i = 0; i < AR_NUM_PDADC_VALUES; i += 4) {
+ AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + i,
+ pdadcs[i + 0] << 0 |
+ pdadcs[i + 1] << 8 |
+ pdadcs[i + 2] << 16 |
+ pdadcs[i + 3] << 24);
+ }
+}
+
+void
+ar9285_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ const struct ar9285_eeprom *eep = sc->eep;
+ const struct ar9285_modal_eep_header *modal = &eep->modalHeader;
+ uint8_t tpow_cck[4], tpow_ofdm[4];
+ uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
+ uint8_t tpow_ht20[8], tpow_ht40[8];
+ int16_t max_ant_gain, power[ATHN_POWER_COUNT];
+ uint8_t ht40inc;
+ int i;
+
+ ar9285_set_power_calib(sc, c);
+
+ /* Compute transmit power reduction due to antenna gain. */
+ max_ant_gain = modal->antennaGain;
+ /* XXX */
+
+ /* Get CCK target powers. */
+ athn_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
+ AR9285_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
+
+ /* Get OFDM target powers. */
+ athn_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
+ AR9285_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
+
+#ifndef IEEE80211_NO_HT
+ /* Get HT-20 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20,
+ AR9285_NUM_2G_20_TARGET_POWERS, tpow_ht20);
+
+ if (extc != NULL) {
+ /* Get HT-40 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_2GHT40,
+ eep->calTargetPower2GHT40, AR9285_NUM_2G_40_TARGET_POWERS,
+ tpow_ht40);
+
+ /* Get secondary channel CCK target powers. */
+ athn_get_lg_tpow(sc, extc, AR_CTL_11B, eep->calTargetPowerCck,
+ AR9285_NUM_2G_CCK_TARGET_POWERS, tpow_cck_ext);
+
+ /* Get secondary channel OFDM target powers. */
+ athn_get_lg_tpow(sc, extc, AR_CTL_11G,
+ eep->calTargetPower2G, AR9285_NUM_2G_20_TARGET_POWERS,
+ tpow_ofdm_ext);
+ }
+#endif
+
+ memset(power, 0, sizeof power);
+ /* Shuffle target powers accross transmit rates. */
+ power[ATHN_POWER_OFDM6 ] =
+ power[ATHN_POWER_OFDM9 ] =
+ power[ATHN_POWER_OFDM12 ] =
+ power[ATHN_POWER_OFDM18 ] =
+ power[ATHN_POWER_OFDM24 ] = tpow_ofdm[0];
+ power[ATHN_POWER_OFDM36 ] = tpow_ofdm[1];
+ power[ATHN_POWER_OFDM48 ] = tpow_ofdm[2];
+ power[ATHN_POWER_OFDM54 ] = tpow_ofdm[3];
+ power[ATHN_POWER_XR ] = tpow_ofdm[0];
+ power[ATHN_POWER_CCK1_LP ] = tpow_cck[0];
+ power[ATHN_POWER_CCK2_LP ] =
+ power[ATHN_POWER_CCK2_SP ] = tpow_cck[1];
+ power[ATHN_POWER_CCK55_LP] =
+ power[ATHN_POWER_CCK55_SP] = tpow_cck[2];
+ power[ATHN_POWER_CCK11_LP] =
+ power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
+#ifndef IEEE80211_NO_HT
+ for (i = 0; i < nitems(tpow_ht20); i++)
+ power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
+ if (extc != NULL) {
+ /* Correct PAR difference between HT40 and HT20/Legacy. */
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2)
+ ht40inc = modal->ht40PowerIncForPdadc;
+ else
+ ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
+ for (i = 0; i < nitems(tpow_ht40); i++)
+ power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
+ power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
+ power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0];
+ power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
+ power[ATHN_POWER_CCK_EXT ] = tpow_cck_ext[0];
+ }
+#endif
+
+ for (i = 0; i < ATHN_POWER_COUNT; i++) {
+ power[i] -= AR_PWR_TABLE_OFFSET_DB * 2; /* In half dB. */
+ if (power[i] > AR_MAX_RATE_POWER)
+ power[i] = AR_MAX_RATE_POWER;
+ }
+
+ /* Commit transmit power values to hardware. */
+ athn_write_txpower(sc, power);
+}
diff --git a/sys/dev/ic/ar9285reg.h b/sys/dev/ic/ar9285reg.h
new file mode 100644
index 00000000000..0887ca38021
--- /dev/null
+++ b/sys/dev/ic/ar9285reg.h
@@ -0,0 +1,991 @@
+/* $OpenBSD: ar9285reg.h,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define AR9285_MAX_CHAINS 1
+
+#define AR9285_PHY_CCA_MAX_GOOD_VALUE (-118)
+
+/*
+ * Analog registers.
+ */
+#define AR9285_AN_RF2G1 0x7820
+#define AR9285_AN_RF2G2 0x7824
+#define AR9285_AN_RF2G3 0x7828
+#define AR9285_AN_RF2G4 0x782c
+#define AR9285_AN_RF2G6 0x7834
+#define AR9285_AN_RF2G7 0x7838
+#define AR9285_AN_RF2G8 0x783c
+#define AR9285_AN_RF2G9 0x7840
+#define AR9285_AN_RXTXBB1 0x7854
+#define AR9285_AN_TOP2 0x7868
+#define AR9285_AN_TOP3 0x786c
+#define AR9285_AN_TOP4 0x7870
+
+/* Bits for AR9285_AN_RF2G1. */
+#define AR9285_AN_RF2G1_ENPACAL 0x00000800
+#define AR9285_AN_RF2G1_PDPADRV1 0x02000000
+#define AR9285_AN_RF2G1_PDPADRV2 0x01000000
+#define AR9285_AN_RF2G1_PDPAOUT 0x00800000
+
+/* Bits for AR9285_AN_RF2G2. */
+#define AR9285_AN_RF2G2_OFFCAL 0x00001000
+
+/* Bits for AR9285_AN_RF2G3. */
+#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000
+#define AR9285_AN_RF2G3_OB_0_M 0x00e00000
+#define AR9285_AN_RF2G3_OB_0_S 21
+#define AR9285_AN_RF2G3_OB_1_M 0x001c0000
+#define AR9285_AN_RF2G3_OB_1_S 18
+#define AR9285_AN_RF2G3_OB_2_M 0x00038000
+#define AR9285_AN_RF2G3_OB_2_S 15
+#define AR9285_AN_RF2G3_OB_3_M 0x00007000
+#define AR9285_AN_RF2G3_OB_3_S 12
+#define AR9285_AN_RF2G3_OB_4_M 0x00000e00
+#define AR9285_AN_RF2G3_OB_4_S 9
+#define AR9285_AN_RF2G3_DB1_0_M 0x000001c0
+#define AR9285_AN_RF2G3_DB1_0_S 6
+#define AR9285_AN_RF2G3_DB1_1_M 0x00000038
+#define AR9285_AN_RF2G3_DB1_1_S 3
+#define AR9285_AN_RF2G3_DB1_2_M 0x00000007
+#define AR9285_AN_RF2G3_DB1_2_S 0
+
+/* Bits for AR9285_AN_RF2G4. */
+#define AR9285_AN_RF2G4_DB1_3_M 0xe0000000
+#define AR9285_AN_RF2G4_DB1_3_S 29
+#define AR9285_AN_RF2G4_DB1_4_M 0x1c000000
+#define AR9285_AN_RF2G4_DB1_4_S 26
+#define AR9285_AN_RF2G4_DB2_0_M 0x03800000
+#define AR9285_AN_RF2G4_DB2_0_S 23
+#define AR9285_AN_RF2G4_DB2_1_M 0x00700000
+#define AR9285_AN_RF2G4_DB2_1_S 20
+#define AR9285_AN_RF2G4_DB2_2_M 0x000e0000
+#define AR9285_AN_RF2G4_DB2_2_S 17
+#define AR9285_AN_RF2G4_DB2_3_M 0x0001c000
+#define AR9285_AN_RF2G4_DB2_3_S 14
+#define AR9285_AN_RF2G4_DB2_4_M 0x00003800
+#define AR9285_AN_RF2G4_DB2_4_S 11
+
+/* Bits for AR9285_AN_RF2G6. */
+#define AR9285_AN_RF2G6_CCOMP_M 0x00007800
+#define AR9285_AN_RF2G6_CCOMP_S 11
+#define AR9285_AN_RF2G6_OFFS_6_1 0x03f00000
+#define AR9285_AN_RF2G6_OFFS(i) (1 << (19 + (i)))
+
+/* Bits for AR9285_AN_RF2G7. */
+#define AR9285_AN_RF2G7_PWDDB 0x00000002
+#define AR9285_AN_RF2G7_PADRVGN2TAB0_M 0xe0000000
+#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29
+
+/* Bits for AR9285_AN_RF2G8. */
+#define AR9285_AN_RF2G8_PADRVGN2TAB0_M 0x0001c000
+#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14
+
+/* Bits for AR9285_AN_RXTXBB1. */
+#define AR9285_AN_RXTXBB1_SPARE9 0x00000001
+#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020
+#define AR9285_AN_RXTXBB1_PDV2I 0x00000080
+#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100
+
+/* Bits for AR9285_AN_TOP2. */
+#define AR9285_AN_TOP2_DEFAULT 0xca0358a0 /* XXX magic */
+
+/* Bits for AR9285_AN_TOP3. */
+#define AR9285_AN_TOP3_XPABIAS_LVL_M 0x0000000c
+#define AR9285_AN_TOP3_XPABIAS_LVL_S 2
+#define AR9285_AN_TOP3_PWDDAC 0x00800000
+
+/* Bits for AR9285_AN_TOP4. */
+#define AR9285_AN_TOP4_DEFAULT 0x10142c00
+
+/* Bits for AR_PHY_MULTICHAIN_GAIN_CTL. */
+#define AR9285_PHY_ANT_DIV_CTL_ALL_M 0x7f000000
+#define AR9285_PHY_ANT_DIV_CTL_ALL_S 24
+#define AR9285_PHY_ANT_DIV_CTL_M 0x01000000
+#define AR9285_PHY_ANT_DIV_CTL_S 24
+#define AR9285_PHY_ANT_DIV_ALT_LNACONF_M 0x06000000
+#define AR9285_PHY_ANT_DIV_ALT_LNACONF_S 25
+#define AR9285_PHY_ANT_DIV_LNA1 2
+#define AR9285_PHY_ANT_DIV_LNA2 1
+#define AR9285_PHY_ANT_DIV_MAIN_LNACONF_M 0x18000000
+#define AR9285_PHY_ANT_DIV_MAIN_LNACONF_S 27
+#define AR9285_PHY_ANT_DIV_ALT_GAINTB_M 0x20000000
+#define AR9285_PHY_ANT_DIV_ALT_GAINTB_S 29
+#define AR9285_PHY_ANT_DIV_GAINTB_0 0
+#define AR9285_PHY_ANT_DIV_GAINTB_1 1
+#define AR9285_PHY_ANT_DIV_MAIN_GAINTB_M 0x40000000
+#define AR9285_PHY_ANT_DIV_MAIN_GAINTB_S 30
+#define AR9285_PHY_ANT_DIV_LNA1_PLUS_LNA2 3
+#define AR9285_PHY_ANT_DIV_LNA1_MINUS_LNA2 0
+
+/*
+ * ROM layout used by AR9285 (single-stream, 2GHz only).
+ */
+#define AR9285_EEP_START_LOC 64
+#define AR9285_NUM_2G_CAL_PIERS 3
+#define AR9285_NUM_2G_CCK_TARGET_POWERS 3
+#define AR9285_NUM_2G_20_TARGET_POWERS 3
+#define AR9285_NUM_2G_40_TARGET_POWERS 3
+#define AR9285_NUM_CTLS 12
+#define AR9285_NUM_BAND_EDGES 4
+#define AR9285_NUM_PD_GAINS 2
+#define AR9285_PD_GAINS_IN_MASK 4
+#define AR9285_PD_GAIN_ICEPTS 5
+
+struct ar9285_base_eep_header {
+ uint16_t length;
+ uint16_t checksum;
+ uint16_t version;
+ uint8_t opCapFlags;
+ uint8_t eepMisc;
+ uint16_t regDmn[2];
+ uint8_t macAddr[6];
+ uint8_t rxMask;
+ uint8_t txMask;
+ uint16_t rfSilent;
+ uint16_t blueToothOptions;
+ uint16_t deviceCap;
+ uint32_t binBuildNumber;
+ uint8_t deviceType;
+ /* End of common header. */
+ uint8_t txGainType;
+} __packed;
+
+struct ar9285_modal_eep_header {
+ uint32_t antCtrlChain;
+ uint32_t antCtrlCommon;
+ uint8_t antennaGain;
+ uint8_t switchSettling;
+ uint8_t txRxAtten;
+ uint8_t rxTxMargin;
+ uint8_t adcDesiredSize;
+ uint8_t pgaDesiredSize;
+ uint8_t xlnaGain;
+ uint8_t txEndToXpaOff;
+ uint8_t txEndToRxOn;
+ uint8_t txFrameToXpaOn;
+ uint8_t thresh62;
+ uint8_t noiseFloorThresh;
+ uint8_t xpdGain;
+ uint8_t xpd;
+ uint8_t iqCalI;
+ uint8_t iqCalQ;
+ uint8_t pdGainOverlap;
+ uint8_t ob_01;
+ uint8_t db1_01;
+ uint8_t xpaBiasLvl;
+ uint8_t txFrameToDataStart;
+ uint8_t txFrameToPaOn;
+ uint8_t ht40PowerIncForPdadc;
+ uint8_t bswAtten;
+ uint8_t bswMargin;
+ uint8_t swSettleHt40;
+ uint8_t xatten2Db;
+ uint8_t xatten2Margin;
+ uint8_t db2_01;
+ uint8_t version;
+ uint16_t ob_234;
+ uint16_t db1_234;
+ uint16_t db2_234;
+ uint8_t futureModal[4];
+ struct ar_spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __packed;
+
+struct ar9285_cal_data_per_freq {
+ uint8_t pwrPdg[AR9285_NUM_PD_GAINS][AR9285_PD_GAIN_ICEPTS];
+ uint8_t vpdPdg[AR9285_NUM_PD_GAINS][AR9285_PD_GAIN_ICEPTS];
+} __packed;
+
+struct ar9285_cal_ctl_data {
+ struct ar_cal_ctl_edges ctlEdges[AR9285_NUM_BAND_EDGES];
+} __packed;
+
+struct ar9285_eeprom {
+ struct ar9285_base_eep_header baseEepHeader;
+ uint8_t custData[20];
+ struct ar9285_modal_eep_header modalHeader;
+ uint8_t calFreqPier2G[AR9285_NUM_2G_CAL_PIERS];
+ struct ar9285_cal_data_per_freq
+ calPierData2G[AR9285_NUM_2G_CAL_PIERS];
+ struct ar_cal_target_power_leg
+ calTargetPowerCck[AR9285_NUM_2G_CCK_TARGET_POWERS];
+ struct ar_cal_target_power_leg
+ calTargetPower2G[AR9285_NUM_2G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower2GHT20[AR9285_NUM_2G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower2GHT40[AR9285_NUM_2G_40_TARGET_POWERS];
+ uint8_t ctlIndex[AR9285_NUM_CTLS];
+ struct ar9285_cal_ctl_data ctlData[AR9285_NUM_CTLS];
+ uint8_t padding;
+} __packed;
+
+/* Macro to "pack" registers to 16-bit to save some .rodata space. */
+#define P(x) (x)
+
+/*
+ * AR9285 1.0 initialization values.
+ */
+static const uint16_t ar9285_1_0_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x08318), P(0x09804), P(0x09820), P(0x09824),
+ P(0x09828), P(0x09834), P(0x09838), P(0x09840), P(0x09844),
+ P(0x09848), P(0x09850), P(0x09858), P(0x0985c), P(0x09860),
+ P(0x09864), P(0x09868), P(0x0986c), P(0x09914), P(0x09918),
+ P(0x09924), P(0x09944), P(0x09960), P(0x09964), P(0x099b8),
+ P(0x099bc), P(0x099c0), P(0x099c4), P(0x099c8), P(0x099cc),
+ P(0x099d0), P(0x099d4), P(0x099d8), P(0x09a00), P(0x09a04),
+ P(0x09a08), P(0x09a0c), P(0x09a10), P(0x09a14), P(0x09a18),
+ P(0x09a1c), P(0x09a20), P(0x09a24), P(0x09a28), P(0x09a2c),
+ P(0x09a30), P(0x09a34), P(0x09a38), P(0x09a3c), P(0x09a40),
+ P(0x09a44), P(0x09a48), P(0x09a4c), P(0x09a50), P(0x09a54),
+ P(0x09a58), P(0x09a5c), P(0x09a60), P(0x09a64), P(0x09a68),
+ P(0x09a6c), P(0x09a70), P(0x09a74), P(0x09a78), P(0x09a7c),
+ P(0x09a80), P(0x09a84), P(0x09a88), P(0x09a8c), P(0x09a90),
+ P(0x09a94), P(0x09a98), P(0x09a9c), P(0x09aa0), P(0x09aa4),
+ P(0x09aa8), P(0x09aac), P(0x09ab0), P(0x09ab4), P(0x09ab8),
+ P(0x09abc), P(0x09ac0), P(0x09ac4), P(0x09ac8), P(0x09acc),
+ P(0x09ad0), P(0x09ad4), P(0x09ad8), P(0x09adc), P(0x09ae0),
+ P(0x09ae4), P(0x09ae8), P(0x09aec), P(0x09af0), P(0x09af4),
+ P(0x09af8), P(0x09afc), P(0x09b00), P(0x09b04), P(0x09b08),
+ P(0x09b0c), P(0x09b10), P(0x09b14), P(0x09b18), P(0x09b1c),
+ P(0x09b20), P(0x09b24), P(0x09b28), P(0x09b2c), P(0x09b30),
+ P(0x09b34), P(0x09b38), P(0x09b3c), P(0x09b40), P(0x09b44),
+ P(0x09b48), P(0x09b4c), P(0x09b50), P(0x09b54), P(0x09b58),
+ P(0x09b5c), P(0x09b60), P(0x09b64), P(0x09b68), P(0x09b6c),
+ P(0x09b70), P(0x09b74), P(0x09b78), P(0x09b7c), P(0x09b80),
+ P(0x09b84), P(0x09b88), P(0x09b8c), P(0x09b90), P(0x09b94),
+ P(0x09b98), P(0x09b9c), P(0x09ba0), P(0x09ba4), P(0x09ba8),
+ P(0x09bac), P(0x09bb0), P(0x09bb4), P(0x09bb8), P(0x09bbc),
+ P(0x09bc0), P(0x09bc4), P(0x09bc8), P(0x09bcc), P(0x09bd0),
+ P(0x09bd4), P(0x09bd8), P(0x09bdc), P(0x09be0), P(0x09be4),
+ P(0x09be8), P(0x09bec), P(0x09bf0), P(0x09bf4), P(0x09bf8),
+ P(0x09bfc), P(0x0aa00), P(0x0aa04), P(0x0aa08), P(0x0aa0c),
+ P(0x0aa10), P(0x0aa14), P(0x0aa18), P(0x0aa1c), P(0x0aa20),
+ P(0x0aa24), P(0x0aa28), P(0x0aa2c), P(0x0aa30), P(0x0aa34),
+ P(0x0aa38), P(0x0aa3c), P(0x0aa40), P(0x0aa44), P(0x0aa48),
+ P(0x0aa4c), P(0x0aa50), P(0x0aa54), P(0x0aa58), P(0x0aa5c),
+ P(0x0aa60), P(0x0aa64), P(0x0aa68), P(0x0aa6c), P(0x0aa70),
+ P(0x0aa74), P(0x0aa78), P(0x0aa7c), P(0x0aa80), P(0x0aa84),
+ P(0x0aa88), P(0x0aa8c), P(0x0aa90), P(0x0aa94), P(0x0aa98),
+ P(0x0aa9c), P(0x0aaa0), P(0x0aaa4), P(0x0aaa8), P(0x0aaac),
+ P(0x0aab0), P(0x0aab4), P(0x0aab8), P(0x0aabc), P(0x0aac0),
+ P(0x0aac4), P(0x0aac8), P(0x0aacc), P(0x0aad0), P(0x0aad4),
+ P(0x0aad8), P(0x0aadc), P(0x0aae0), P(0x0aae4), P(0x0aae8),
+ P(0x0aaec), P(0x0aaf0), P(0x0aaf4), P(0x0aaf8), P(0x0aafc),
+ P(0x0ab00), P(0x0ab04), P(0x0ab08), P(0x0ab0c), P(0x0ab10),
+ P(0x0ab14), P(0x0ab18), P(0x0ab1c), P(0x0ab20), P(0x0ab24),
+ P(0x0ab28), P(0x0ab2c), P(0x0ab30), P(0x0ab34), P(0x0ab38),
+ P(0x0ab3c), P(0x0ab40), P(0x0ab44), P(0x0ab48), P(0x0ab4c),
+ P(0x0ab50), P(0x0ab54), P(0x0ab58), P(0x0ab5c), P(0x0ab60),
+ P(0x0ab64), P(0x0ab68), P(0x0ab6c), P(0x0ab70), P(0x0ab74),
+ P(0x0ab78), P(0x0ab7c), P(0x0ab80), P(0x0ab84), P(0x0ab88),
+ P(0x0ab8c), P(0x0ab90), P(0x0ab94), P(0x0ab98), P(0x0ab9c),
+ P(0x0aba0), P(0x0aba4), P(0x0aba8), P(0x0abac), P(0x0abb0),
+ P(0x0abb4), P(0x0abb8), P(0x0abbc), P(0x0abc0), P(0x0abc4),
+ P(0x0abc8), P(0x0abcc), P(0x0abd0), P(0x0abd4), P(0x0abd8),
+ P(0x0abdc), P(0x0abe0), P(0x0abe4), P(0x0abe8), P(0x0abec),
+ P(0x0abf0), P(0x0abf4), P(0x0abf8), P(0x0abfc), P(0x0a204),
+ P(0x0a20c), P(0x0a21c), P(0x0a230), P(0x0a250), P(0x0a274),
+ P(0x0a300), P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310),
+ P(0x0a314), P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324),
+ P(0x0a328), P(0x0a32c), P(0x0a330), P(0x0a334), P(0x0a338),
+ P(0x0a33c), P(0x0a340), P(0x0a344), P(0x0a358)
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar9285_1_0_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00000000, 0x10801600,
+ 0x12e00057, 0x00006880, 0x000003c4, 0x02020200, 0x00000e0e,
+ 0x0a020001, 0x00000e0e, 0x00000007, 0x206a012e, 0x03720020,
+ 0x0000004e, 0x6d4000e2, 0x7ec84d2e, 0x3136605e, 0x00058d20,
+ 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00001130, 0x00000016,
+ 0xd00a800d, 0xdfbc1020, 0x00000000, 0x00000000, 0x00cf4d1c,
+ 0x00000c00, 0x05eea6d4, 0x06336f77, 0x60f65329, 0x08f186c8,
+ 0x00046384, 0x00000000, 0x00000000, 0x00068084, 0x00068088,
+ 0x0006808c, 0x00068100, 0x00068104, 0x00068108, 0x0006810c,
+ 0x00068110, 0x00068114, 0x00068180, 0x00068184, 0x00068188,
+ 0x0006818c, 0x00068190, 0x00068194, 0x000681a0, 0x0006820c,
+ 0x000681a8, 0x00068284, 0x00068288, 0x00068220, 0x00068290,
+ 0x00068300, 0x00068304, 0x00068308, 0x0006830c, 0x00068380,
+ 0x00068384, 0x00068700, 0x00068704, 0x00068708, 0x0006870c,
+ 0x00068780, 0x00068784, 0x00068b04, 0x00068b08, 0x00068b08,
+ 0x00068b0c, 0x00068b80, 0x00068b84, 0x00068b88, 0x00068b8c,
+ 0x000b8b90, 0x000b8f80, 0x000b8f84, 0x000b8f88, 0x000b8f8c,
+ 0x000b8f90, 0x000bb30c, 0x000bb310, 0x000bb384, 0x000bb388,
+ 0x000bb324, 0x000bb704, 0x000f96a4, 0x000f96a8, 0x000f9710,
+ 0x000f9714, 0x000f9720, 0x000f9724, 0x000f9728, 0x000f972c,
+ 0x000f97a0, 0x000f97a4, 0x000fb7a8, 0x000fb7b0, 0x000fb7b4,
+ 0x000fb7b8, 0x000fb7a5, 0x000fb7a9, 0x000fb7ad, 0x000fb7b1,
+ 0x000fb7b5, 0x000fb7b9, 0x000fb7c5, 0x000fb7c9, 0x000fb7d1,
+ 0x000fb7d5, 0x000fb7d9, 0x000fb7c6, 0x000fb7ca, 0x000fb7ce,
+ 0x000fb7d2, 0x000fb7d6, 0x000fb7c3, 0x000fb7c7, 0x000fb7cb,
+ 0x000fb7cf, 0x000fb7d7, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x0006801c, 0x00068080, 0x00068084, 0x00068088,
+ 0x0006808c, 0x00068100, 0x00068104, 0x00068108, 0x0006810c,
+ 0x00068110, 0x00068110, 0x00068180, 0x00068184, 0x00068188,
+ 0x0006818c, 0x00068190, 0x00068194, 0x000681a0, 0x0006820c,
+ 0x000681a8, 0x000681ac, 0x0006821c, 0x00068224, 0x00068290,
+ 0x00068300, 0x00068308, 0x0006830c, 0x00068310, 0x00068788,
+ 0x0006878c, 0x00068790, 0x00068794, 0x00068798, 0x0006879c,
+ 0x00068b89, 0x00068b8d, 0x00068b91, 0x00068b95, 0x00068b99,
+ 0x00068ba5, 0x00068ba9, 0x00068bad, 0x000b8b0c, 0x000b8f10,
+ 0x000b8f14, 0x000b8f84, 0x000b8f84, 0x000b8f88, 0x000bb380,
+ 0x000bb384, 0x000bb388, 0x000bb38c, 0x000bb394, 0x000bb798,
+ 0x000f970c, 0x000f9710, 0x000f9714, 0x000f9718, 0x000f9705,
+ 0x000f9709, 0x000f970d, 0x000f9711, 0x000f9715, 0x000f9719,
+ 0x000fb7a4, 0x000fb7a8, 0x000fb7ac, 0x000fb7ac, 0x000fb7b0,
+ 0x000fb7b8, 0x000fb7bc, 0x000fb7a1, 0x000fb7a5, 0x000fb7a9,
+ 0x000fb7b1, 0x000fb7b5, 0x000fb7bd, 0x000fb7c9, 0x000fb7cd,
+ 0x000fb7d1, 0x000fb7d9, 0x000fb7c2, 0x000fb7c6, 0x000fb7ca,
+ 0x000fb7ce, 0x000fb7d2, 0x000fb7d6, 0x000fb7c3, 0x000fb7cb,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x00000004,
+ 0x00000000, 0x1883800a, 0x00000210, 0x001ca000, 0x0a820652,
+ 0x00000000, 0x00007201, 0x00010408, 0x0001860a, 0x00020818,
+ 0x00024858, 0x00026859, 0x0002985b, 0x0002c89a, 0x0002e89b,
+ 0x0003089c, 0x0003289d, 0x0003489e, 0x000388de, 0x0003b91e,
+ 0x0003d95e, 0x000419df, 0x0003e9df, 0x7999aa0e
+};
+#endif
+
+static const uint32_t ar9285_1_0_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x00000000, 0x08400b00,
+ 0x12e0002b, 0x00003440, 0x00000300, 0x02020200, 0x00000e0e,
+ 0x0a020001, 0x00000e0e, 0x00000007, 0x206a012e, 0x03720020,
+ 0x0000004e, 0x6d4000e2, 0x7ec84d2e, 0x3136605e, 0x00058d20,
+ 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00000898, 0x0000000b,
+ 0xd00a800d, 0xdfbc1020, 0x00000000, 0x00000000, 0x00cf4d1c,
+ 0x00000c00, 0x05eea6d4, 0x06336f77, 0x60f65329, 0x08f186c8,
+ 0x00046384, 0x00000000, 0x00000000, 0x00068084, 0x00068088,
+ 0x0006808c, 0x00068100, 0x00068104, 0x00068108, 0x0006810c,
+ 0x00068110, 0x00068114, 0x00068180, 0x00068184, 0x00068188,
+ 0x0006818c, 0x00068190, 0x00068194, 0x000681a0, 0x0006820c,
+ 0x000681a8, 0x00068284, 0x00068288, 0x00068220, 0x00068290,
+ 0x00068300, 0x00068304, 0x00068308, 0x0006830c, 0x00068380,
+ 0x00068384, 0x00068700, 0x00068704, 0x00068708, 0x0006870c,
+ 0x00068780, 0x00068784, 0x00068b04, 0x00068b08, 0x00068b08,
+ 0x00068b0c, 0x00068b80, 0x00068b84, 0x00068b88, 0x00068b8c,
+ 0x000b8b90, 0x000b8f80, 0x000b8f84, 0x000b8f88, 0x000b8f8c,
+ 0x000b8f90, 0x000bb30c, 0x000bb310, 0x000bb384, 0x000bb388,
+ 0x000bb324, 0x000bb704, 0x000f96a4, 0x000f96a8, 0x000f9710,
+ 0x000f9714, 0x000f9720, 0x000f9724, 0x000f9728, 0x000f972c,
+ 0x000f97a0, 0x000f97a4, 0x000fb7a8, 0x000fb7b0, 0x000fb7b4,
+ 0x000fb7b8, 0x000fb7a5, 0x000fb7a9, 0x000fb7ad, 0x000fb7b1,
+ 0x000fb7b5, 0x000fb7b9, 0x000fb7c5, 0x000fb7c9, 0x000fb7d1,
+ 0x000fb7d5, 0x000fb7d9, 0x000fb7c6, 0x000fb7ca, 0x000fb7ce,
+ 0x000fb7d2, 0x000fb7d6, 0x000fb7c3, 0x000fb7c7, 0x000fb7cb,
+ 0x000fb7cf, 0x000fb7d7, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db, 0x000fb7db,
+ 0x000fb7db, 0x0006801c, 0x00068080, 0x00068084, 0x00068088,
+ 0x0006808c, 0x00068100, 0x00068104, 0x00068108, 0x0006810c,
+ 0x00068110, 0x00068110, 0x00068180, 0x00068184, 0x00068188,
+ 0x0006818c, 0x00068190, 0x00068194, 0x000681a0, 0x0006820c,
+ 0x000681a8, 0x000681ac, 0x0006821c, 0x00068224, 0x00068290,
+ 0x00068300, 0x00068308, 0x0006830c, 0x00068310, 0x00068788,
+ 0x0006878c, 0x00068790, 0x00068794, 0x00068798, 0x0006879c,
+ 0x00068b89, 0x00068b8d, 0x00068b91, 0x00068b95, 0x00068b99,
+ 0x00068ba5, 0x00068ba9, 0x00068bad, 0x000b8b0c, 0x000b8f10,
+ 0x000b8f14, 0x000b8f84, 0x000b8f84, 0x000b8f88, 0x000bb380,
+ 0x000bb384, 0x000bb388, 0x000bb38c, 0x000bb394, 0x000bb798,
+ 0x000f970c, 0x000f9710, 0x000f9714, 0x000f9718, 0x000f9705,
+ 0x000f9709, 0x000f970d, 0x000f9711, 0x000f9715, 0x000f9719,
+ 0x000fb7a4, 0x000fb7a8, 0x000fb7ac, 0x000fb7ac, 0x000fb7b0,
+ 0x000fb7b8, 0x000fb7bc, 0x000fb7a1, 0x000fb7a5, 0x000fb7a9,
+ 0x000fb7b1, 0x000fb7b5, 0x000fb7bd, 0x000fb7c9, 0x000fb7cd,
+ 0x000fb7d1, 0x000fb7d9, 0x000fb7c2, 0x000fb7c6, 0x000fb7ca,
+ 0x000fb7ce, 0x000fb7d2, 0x000fb7d6, 0x000fb7c3, 0x000fb7cb,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3,
+ 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x000fb7d3, 0x00000004,
+ 0x00000000, 0x1883800a, 0x00000108, 0x001ca000, 0x0a820652,
+ 0x00000000, 0x00007201, 0x00010408, 0x0001860a, 0x00020818,
+ 0x00024858, 0x00026859, 0x0002985b, 0x0002c89a, 0x0002e89b,
+ 0x0003089c, 0x0003289d, 0x0003489e, 0x000388de, 0x0003b91e,
+ 0x0003d95e, 0x000419df, 0x0003e9df, 0x7999aa0e
+};
+
+static const uint16_t ar9285_1_0_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x04060),
+ P(0x04064), P(0x07010), P(0x07034), P(0x07038), P(0x08004),
+ P(0x08008), P(0x0800c), P(0x08018), P(0x08020), P(0x08038),
+ P(0x0803c), P(0x08048), P(0x08054), P(0x08058), P(0x0805c),
+ P(0x08060), P(0x08064), P(0x08070), P(0x080c0), P(0x080c4),
+ P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
+ P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
+ P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
+ P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
+ P(0x08120), P(0x08124), P(0x08128), P(0x0812c), P(0x08130),
+ P(0x08134), P(0x08138), P(0x0813c), P(0x08144), P(0x08168),
+ P(0x0816c), P(0x08170), P(0x08174), P(0x08178), P(0x0817c),
+ P(0x081c0), P(0x081d0), P(0x081ec), P(0x081f0), P(0x081f4),
+ P(0x081f8), P(0x081fc), P(0x08200), P(0x08204), P(0x08208),
+ P(0x0820c), P(0x08210), P(0x08214), P(0x08218), P(0x0821c),
+ P(0x08220), P(0x08224), P(0x08228), P(0x0822c), P(0x08230),
+ P(0x08234), P(0x08238), P(0x0823c), P(0x08240), P(0x08244),
+ P(0x08248), P(0x0824c), P(0x08250), P(0x08254), P(0x08258),
+ P(0x0825c), P(0x08260), P(0x08264), P(0x08270), P(0x08274),
+ P(0x08278), P(0x0827c), P(0x08284), P(0x08288), P(0x0828c),
+ P(0x08294), P(0x08298), P(0x0829c), P(0x08300), P(0x08314),
+ P(0x08328), P(0x0832c), P(0x08330), P(0x08334), P(0x08338),
+ P(0x0833c), P(0x08340), P(0x08344), P(0x09808), P(0x0980c),
+ P(0x09810), P(0x09814), P(0x0981c), P(0x0982c), P(0x09830),
+ P(0x0983c), P(0x0984c), P(0x09854), P(0x09900), P(0x09904),
+ P(0x09908), P(0x0990c), P(0x09910), P(0x0991c), P(0x09920),
+ P(0x09928), P(0x0992c), P(0x09934), P(0x09938), P(0x0993c),
+ P(0x09940), P(0x09948), P(0x0994c), P(0x09954), P(0x09958),
+ P(0x09968), P(0x09970), P(0x09974), P(0x09978), P(0x0997c),
+ P(0x09980), P(0x09984), P(0x09988), P(0x0998c), P(0x09990),
+ P(0x09994), P(0x09998), P(0x0999c), P(0x099a0), P(0x099a4),
+ P(0x099a8), P(0x099ac), P(0x099b0), P(0x099b4), P(0x099dc),
+ P(0x099e0), P(0x099e4), P(0x099e8), P(0x099ec), P(0x099f0),
+ P(0x0a208), P(0x0a210), P(0x0a214), P(0x0a218), P(0x0a220),
+ P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234), P(0x0a238),
+ P(0x0a244), P(0x0a248), P(0x0a24c), P(0x0a254), P(0x0a258),
+ P(0x0a25c), P(0x0a260), P(0x0a268), P(0x0a26c), P(0x0d270),
+ P(0x0a278), P(0x0a27c), P(0x0d35c), P(0x0d360), P(0x0d364),
+ P(0x0d368), P(0x0d36c), P(0x0d370), P(0x0d374), P(0x0d378),
+ P(0x0d37c), P(0x0d380), P(0x0d384), P(0x0a388), P(0x0a38c),
+ P(0x0a390), P(0x0a394), P(0x0a398), P(0x0a39c), P(0x0a3a0),
+ P(0x0a3a4), P(0x0a3a8), P(0x0a3ac), P(0x0a3b0), P(0x0a3b4),
+ P(0x0a3b8), P(0x0a3bc), P(0x0a3c0), P(0x0a3c4), P(0x0a3cc),
+ P(0x0a3d0), P(0x0a3d4), P(0x0a3dc), P(0x0a3e0), P(0x0a3e4),
+ P(0x0a3e8), P(0x0a3ec), P(0x07800), P(0x07804), P(0x07808),
+ P(0x0780c), P(0x07810), P(0x07814), P(0x0781c), P(0x07820),
+ P(0x07824), P(0x07828), P(0x0782c), P(0x07830), P(0x07834),
+ P(0x07838), P(0x0783c), P(0x07840), P(0x07844), P(0x07848),
+ P(0x0784c), P(0x07850), P(0x07854), P(0x07858), P(0x0785c),
+ P(0x07860), P(0x07864), P(0x07868), P(0x0786c), P(0x07870)
+};
+
+static const uint32_t ar9285_1_0_cm_vals[] = {
+ 0x00000000, 0x00020045, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000031, 0x00000002, 0x000004c2, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000700, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000fc78f,
+ 0x0000000f, 0x00000000, 0x00000000, 0x2a80001a, 0x05dc01e0,
+ 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
+ 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
+ 0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
+ 0x08f04800, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000,
+ 0x00000000, 0x00003210, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00100000, 0x0010f400,
+ 0x00000100, 0x0001e800, 0x00000000, 0x00000000, 0x00000000,
+ 0x400000ff, 0x00080922, 0xa8a00010, 0x00000000, 0x40000000,
+ 0x003e4180, 0x00000000, 0x0000002c, 0x0000002c, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000000,
+ 0x00000000, 0x00000001, 0x00000302, 0x00000e00, 0x00000000,
+ 0x00000000, 0x00010380, 0x00481043, 0x00000000, 0xafe68e30,
+ 0xfd14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000, 0x00000000,
+ 0x00200400, 0x0040233c, 0x00000044, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x01002310, 0x10000fff, 0x04900000,
+ 0x00000001, 0x00000004, 0x1e1f2022, 0x0a0b0c0d, 0x00000000,
+ 0x14750604, 0x9280c00a, 0x00020028, 0x5f3ca3de, 0x2108ecff,
+ 0x000003ce, 0x1927b515, 0x00000000, 0x00000001, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
+ 0x201fff00, 0x2def0a00, 0x03051000, 0x00000820, 0x00000000,
+ 0x00000000, 0xaaaaaaaa, 0x3c466478, 0x0cc80caa, 0x00000000,
+ 0x803e6788, 0x4080a333, 0x00206c10, 0x009c4060, 0x01834061,
+ 0x00000400, 0x000003b5, 0x00000000, 0x20202020, 0x20202020,
+ 0x00000000, 0xfffffffc, 0x00000000, 0x00000000, 0x0ccb5380,
+ 0x15151501, 0xdfa90f01, 0x00000000, 0x0ebae9e6, 0x0d820820,
+ 0x39ce739c, 0x050e039c, 0x07ffffef, 0x0fffffe7, 0x17ffffe5,
+ 0x1fffffe4, 0x37ffffe3, 0x3fffffe3, 0x57ffffe3, 0x5fffffe2,
+ 0x7fffffe2, 0x7f3c7bba, 0xf3307ff0, 0x0c000000, 0x20202020,
+ 0x20202020, 0x39ce739c, 0x0000039c, 0x00000001, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x20202020,
+ 0x20202020, 0x20202020, 0x39ce739c, 0x0000039c, 0x00000000,
+ 0x18c43433, 0x00f70081, 0x00140000, 0x0e4548d8, 0x54214514,
+ 0x02025820, 0x71c0d388, 0x924934a8, 0x00000000, 0x00000c04,
+ 0x00d86fff, 0x26d2491b, 0x6e36d97b, 0xedb6d96c, 0x71400086,
+ 0xfac68800, 0x0001fffe, 0xffeb1a20, 0x000c0db6, 0x6db61b6f,
+ 0x6d9b66db, 0x6d8c6dba, 0x00040000, 0xdb003012, 0x04924914,
+ 0x21084210, 0xf7d7ffde, 0xc2034080, 0x48609eb4, 0x10142c00
+};
+
+static const struct athn_ini ar9285_1_0_ini = {
+ nitems(ar9285_1_0_regs),
+ ar9285_1_0_regs,
+ NULL, /* 2GHz only. */
+#ifndef IEEE80211_NO_HT
+ NULL, /* 2GHz only. */
+ ar9285_1_0_vals_2g40,
+#endif
+ ar9285_1_0_vals_2g20,
+ nitems(ar9285_1_0_cm_regs),
+ ar9285_1_0_cm_regs,
+ ar9285_1_0_cm_vals
+};
+
+/*
+ * AR9285 1.2 initialization values.
+ */
+static const uint16_t ar9285_1_2_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x08318), P(0x09804), P(0x09820), P(0x09824),
+ P(0x09828), P(0x09834), P(0x09838), P(0x09840), P(0x09844),
+ P(0x09848), P(0x0a848), P(0x09850), P(0x09858), P(0x0985c),
+ P(0x09860), P(0x09864), P(0x09868), P(0x0986c), P(0x09914),
+ P(0x09918), P(0x09924), P(0x09944), P(0x09960), P(0x09964),
+ P(0x099b8), P(0x099bc), P(0x099c0), P(0x099c4), P(0x099c8),
+ P(0x099cc), P(0x099d0), P(0x099d4), P(0x099d8), P(0x09a00),
+ P(0x09a04), P(0x09a08), P(0x09a0c), P(0x09a10), P(0x09a14),
+ P(0x09a18), P(0x09a1c), P(0x09a20), P(0x09a24), P(0x09a28),
+ P(0x09a2c), P(0x09a30), P(0x09a34), P(0x09a38), P(0x09a3c),
+ P(0x09a40), P(0x09a44), P(0x09a48), P(0x09a4c), P(0x09a50),
+ P(0x09a54), P(0x09a58), P(0x09a5c), P(0x09a60), P(0x09a64),
+ P(0x09a68), P(0x09a6c), P(0x09a70), P(0x09a74), P(0x09a78),
+ P(0x09a7c), P(0x09a80), P(0x09a84), P(0x09a88), P(0x09a8c),
+ P(0x09a90), P(0x09a94), P(0x09a98), P(0x09a9c), P(0x09aa0),
+ P(0x09aa4), P(0x09aa8), P(0x09aac), P(0x09ab0), P(0x09ab4),
+ P(0x09ab8), P(0x09abc), P(0x09ac0), P(0x09ac4), P(0x09ac8),
+ P(0x09acc), P(0x09ad0), P(0x09ad4), P(0x09ad8), P(0x09adc),
+ P(0x09ae0), P(0x09ae4), P(0x09ae8), P(0x09aec), P(0x09af0),
+ P(0x09af4), P(0x09af8), P(0x09afc), P(0x09b00), P(0x09b04),
+ P(0x09b08), P(0x09b0c), P(0x09b10), P(0x09b14), P(0x09b18),
+ P(0x09b1c), P(0x09b20), P(0x09b24), P(0x09b28), P(0x09b2c),
+ P(0x09b30), P(0x09b34), P(0x09b38), P(0x09b3c), P(0x09b40),
+ P(0x09b44), P(0x09b48), P(0x09b4c), P(0x09b50), P(0x09b54),
+ P(0x09b58), P(0x09b5c), P(0x09b60), P(0x09b64), P(0x09b68),
+ P(0x09b6c), P(0x09b70), P(0x09b74), P(0x09b78), P(0x09b7c),
+ P(0x09b80), P(0x09b84), P(0x09b88), P(0x09b8c), P(0x09b90),
+ P(0x09b94), P(0x09b98), P(0x09b9c), P(0x09ba0), P(0x09ba4),
+ P(0x09ba8), P(0x09bac), P(0x09bb0), P(0x09bb4), P(0x09bb8),
+ P(0x09bbc), P(0x09bc0), P(0x09bc4), P(0x09bc8), P(0x09bcc),
+ P(0x09bd0), P(0x09bd4), P(0x09bd8), P(0x09bdc), P(0x09be0),
+ P(0x09be4), P(0x09be8), P(0x09bec), P(0x09bf0), P(0x09bf4),
+ P(0x09bf8), P(0x09bfc), P(0x0aa00), P(0x0aa04), P(0x0aa08),
+ P(0x0aa0c), P(0x0aa10), P(0x0aa14), P(0x0aa18), P(0x0aa1c),
+ P(0x0aa20), P(0x0aa24), P(0x0aa28), P(0x0aa2c), P(0x0aa30),
+ P(0x0aa34), P(0x0aa38), P(0x0aa3c), P(0x0aa40), P(0x0aa44),
+ P(0x0aa48), P(0x0aa4c), P(0x0aa50), P(0x0aa54), P(0x0aa58),
+ P(0x0aa5c), P(0x0aa60), P(0x0aa64), P(0x0aa68), P(0x0aa6c),
+ P(0x0aa70), P(0x0aa74), P(0x0aa78), P(0x0aa7c), P(0x0aa80),
+ P(0x0aa84), P(0x0aa88), P(0x0aa8c), P(0x0aa90), P(0x0aa94),
+ P(0x0aa98), P(0x0aa9c), P(0x0aaa0), P(0x0aaa4), P(0x0aaa8),
+ P(0x0aaac), P(0x0aab0), P(0x0aab4), P(0x0aab8), P(0x0aabc),
+ P(0x0aac0), P(0x0aac4), P(0x0aac8), P(0x0aacc), P(0x0aad0),
+ P(0x0aad4), P(0x0aad8), P(0x0aadc), P(0x0aae0), P(0x0aae4),
+ P(0x0aae8), P(0x0aaec), P(0x0aaf0), P(0x0aaf4), P(0x0aaf8),
+ P(0x0aafc), P(0x0ab00), P(0x0ab04), P(0x0ab08), P(0x0ab0c),
+ P(0x0ab10), P(0x0ab14), P(0x0ab18), P(0x0ab1c), P(0x0ab20),
+ P(0x0ab24), P(0x0ab28), P(0x0ab2c), P(0x0ab30), P(0x0ab34),
+ P(0x0ab38), P(0x0ab3c), P(0x0ab40), P(0x0ab44), P(0x0ab48),
+ P(0x0ab4c), P(0x0ab50), P(0x0ab54), P(0x0ab58), P(0x0ab5c),
+ P(0x0ab60), P(0x0ab64), P(0x0ab68), P(0x0ab6c), P(0x0ab70),
+ P(0x0ab74), P(0x0ab78), P(0x0ab7c), P(0x0ab80), P(0x0ab84),
+ P(0x0ab88), P(0x0ab8c), P(0x0ab90), P(0x0ab94), P(0x0ab98),
+ P(0x0ab9c), P(0x0aba0), P(0x0aba4), P(0x0aba8), P(0x0abac),
+ P(0x0abb0), P(0x0abb4), P(0x0abb8), P(0x0abbc), P(0x0abc0),
+ P(0x0abc4), P(0x0abc8), P(0x0abcc), P(0x0abd0), P(0x0abd4),
+ P(0x0abd8), P(0x0abdc), P(0x0abe0), P(0x0abe4), P(0x0abe8),
+ P(0x0abec), P(0x0abf0), P(0x0abf4), P(0x0abf8), P(0x0abfc),
+ P(0x0a204), P(0x0a20c), P(0x0b20c), P(0x0a21c), P(0x0a230),
+ P(0x0a250), P(0x0a358)
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar9285_1_2_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00000000, 0x10801600,
+ 0x12e00057, 0x00006880, 0x000003c4, 0x02020200, 0x01000e0e,
+ 0x0a020001, 0x00000e0e, 0x00000007, 0x206a012e, 0x03721620,
+ 0x00001053, 0x00001053, 0x6d4000e2, 0x7ec84d2e, 0x3137605e,
+ 0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00001130,
+ 0x00000016, 0xd00a800d, 0xffbc1020, 0x00000000, 0x00000000,
+ 0x0000421c, 0x00000c00, 0x05eea6d4, 0x06336f77, 0x6af6532f,
+ 0x08f186c8, 0x00046384, 0x00000000, 0x00000000, 0x00058084,
+ 0x00058088, 0x0005808c, 0x00058100, 0x00058104, 0x00058108,
+ 0x0005810c, 0x00058110, 0x00058114, 0x00058180, 0x00058184,
+ 0x00058188, 0x0005818c, 0x00058190, 0x00058194, 0x000581a0,
+ 0x0005820c, 0x000581a8, 0x00058284, 0x00058288, 0x00058220,
+ 0x00058290, 0x00058300, 0x00058304, 0x00058308, 0x0005830c,
+ 0x00058380, 0x00058384, 0x00068700, 0x00068704, 0x00068708,
+ 0x0006870c, 0x00068780, 0x00068784, 0x00078b04, 0x00078b08,
+ 0x00078b08, 0x00078b0c, 0x00078b80, 0x00078b84, 0x00078b88,
+ 0x00078b8c, 0x00078b90, 0x000caf80, 0x000caf84, 0x000caf88,
+ 0x000caf8c, 0x000caf90, 0x000db30c, 0x000db310, 0x000db384,
+ 0x000db388, 0x000db324, 0x000eb704, 0x000eb6a4, 0x000eb6a8,
+ 0x000eb710, 0x000eb714, 0x000eb720, 0x000eb724, 0x000eb728,
+ 0x000eb72c, 0x000eb7a0, 0x000eb7a4, 0x000eb7a8, 0x000eb7b0,
+ 0x000eb7b4, 0x000eb7b8, 0x000eb7a5, 0x000eb7a9, 0x000eb7ad,
+ 0x000eb7b1, 0x000eb7b5, 0x000eb7b9, 0x000eb7c5, 0x000eb7c9,
+ 0x000eb7d1, 0x000eb7d5, 0x000eb7d9, 0x000eb7c6, 0x000eb7ca,
+ 0x000eb7ce, 0x000eb7d2, 0x000eb7d6, 0x000eb7c3, 0x000eb7c7,
+ 0x000eb7cb, 0x000eb7cf, 0x000eb7d7, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x00058084, 0x00058088, 0x0005808c,
+ 0x00058100, 0x00058104, 0x00058108, 0x0005810c, 0x00058110,
+ 0x00058114, 0x00058180, 0x00058184, 0x00058188, 0x0005818c,
+ 0x00058190, 0x00058194, 0x000581a0, 0x0005820c, 0x000581a8,
+ 0x00058284, 0x00058288, 0x00058220, 0x00058290, 0x00058300,
+ 0x00058304, 0x00058308, 0x0005830c, 0x00058380, 0x00058384,
+ 0x00068700, 0x00068704, 0x00068708, 0x0006870c, 0x00068780,
+ 0x00068784, 0x00078b04, 0x00078b08, 0x00078b08, 0x00078b0c,
+ 0x00078b80, 0x00078b84, 0x00078b88, 0x00078b8c, 0x00078b90,
+ 0x000caf80, 0x000caf84, 0x000caf88, 0x000caf8c, 0x000caf90,
+ 0x000db30c, 0x000db310, 0x000db384, 0x000db388, 0x000db324,
+ 0x000eb704, 0x000eb6a4, 0x000eb6a8, 0x000eb710, 0x000eb714,
+ 0x000eb720, 0x000eb724, 0x000eb728, 0x000eb72c, 0x000eb7a0,
+ 0x000eb7a4, 0x000eb7a8, 0x000eb7b0, 0x000eb7b4, 0x000eb7b8,
+ 0x000eb7a5, 0x000eb7a9, 0x000eb7ad, 0x000eb7b1, 0x000eb7b5,
+ 0x000eb7b9, 0x000eb7c5, 0x000eb7c9, 0x000eb7d1, 0x000eb7d5,
+ 0x000eb7d9, 0x000eb7c6, 0x000eb7ca, 0x000eb7ce, 0x000eb7d2,
+ 0x000eb7d6, 0x000eb7c3, 0x000eb7c7, 0x000eb7cb, 0x000eb7cf,
+ 0x000eb7d7, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x00000004, 0x0001f000, 0x0001f000, 0x1883800a, 0x00000210,
+ 0x0004a000, 0x7999aa0e
+};
+#endif
+
+static const uint32_t ar9285_1_2_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x00000000, 0x08400b00,
+ 0x12e0002b, 0x00003440, 0x00000300, 0x02020200, 0x01000e0e,
+ 0x0a020001, 0x00000e0e, 0x00000007, 0x206a012e, 0x03721620,
+ 0x00001053, 0x00001053, 0x6d4000e2, 0x7ec84d2e, 0x3137605e,
+ 0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00000898,
+ 0x0000000b, 0xd00a800d, 0xffbc1020, 0x00000000, 0x00000000,
+ 0x0000421c, 0x00000c00, 0x05eea6d4, 0x06336f77, 0x6af6532f,
+ 0x08f186c8, 0x00046384, 0x00000000, 0x00000000, 0x00058084,
+ 0x00058088, 0x0005808c, 0x00058100, 0x00058104, 0x00058108,
+ 0x0005810c, 0x00058110, 0x00058114, 0x00058180, 0x00058184,
+ 0x00058188, 0x0005818c, 0x00058190, 0x00058194, 0x000581a0,
+ 0x0005820c, 0x000581a8, 0x00058284, 0x00058288, 0x00058220,
+ 0x00058290, 0x00058300, 0x00058304, 0x00058308, 0x0005830c,
+ 0x00058380, 0x00058384, 0x00068700, 0x00068704, 0x00068708,
+ 0x0006870c, 0x00068780, 0x00068784, 0x00078b04, 0x00078b08,
+ 0x00078b08, 0x00078b0c, 0x00078b80, 0x00078b84, 0x00078b88,
+ 0x00078b8c, 0x00078b90, 0x000caf80, 0x000caf84, 0x000caf88,
+ 0x000caf8c, 0x000caf90, 0x000db30c, 0x000db310, 0x000db384,
+ 0x000db388, 0x000db324, 0x000eb704, 0x000eb6a4, 0x000eb6a8,
+ 0x000eb710, 0x000eb714, 0x000eb720, 0x000eb724, 0x000eb728,
+ 0x000eb72c, 0x000eb7a0, 0x000eb7a4, 0x000eb7a8, 0x000eb7b0,
+ 0x000eb7b4, 0x000eb7b8, 0x000eb7a5, 0x000eb7a9, 0x000eb7ad,
+ 0x000eb7b1, 0x000eb7b5, 0x000eb7b9, 0x000eb7c5, 0x000eb7c9,
+ 0x000eb7d1, 0x000eb7d5, 0x000eb7d9, 0x000eb7c6, 0x000eb7ca,
+ 0x000eb7ce, 0x000eb7d2, 0x000eb7d6, 0x000eb7c3, 0x000eb7c7,
+ 0x000eb7cb, 0x000eb7cf, 0x000eb7d7, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x00058084, 0x00058088, 0x0005808c,
+ 0x00058100, 0x00058104, 0x00058108, 0x0005810c, 0x00058110,
+ 0x00058114, 0x00058180, 0x00058184, 0x00058188, 0x0005818c,
+ 0x00058190, 0x00058194, 0x000581a0, 0x0005820c, 0x000581a8,
+ 0x00058284, 0x00058288, 0x00058220, 0x00058290, 0x00058300,
+ 0x00058304, 0x00058308, 0x0005830c, 0x00058380, 0x00058384,
+ 0x00068700, 0x00068704, 0x00068708, 0x0006870c, 0x00068780,
+ 0x00068784, 0x00078b04, 0x00078b08, 0x00078b08, 0x00078b0c,
+ 0x00078b80, 0x00078b84, 0x00078b88, 0x00078b8c, 0x00078b90,
+ 0x000caf80, 0x000caf84, 0x000caf88, 0x000caf8c, 0x000caf90,
+ 0x000db30c, 0x000db310, 0x000db384, 0x000db388, 0x000db324,
+ 0x000eb704, 0x000eb6a4, 0x000eb6a8, 0x000eb710, 0x000eb714,
+ 0x000eb720, 0x000eb724, 0x000eb728, 0x000eb72c, 0x000eb7a0,
+ 0x000eb7a4, 0x000eb7a8, 0x000eb7b0, 0x000eb7b4, 0x000eb7b8,
+ 0x000eb7a5, 0x000eb7a9, 0x000eb7ad, 0x000eb7b1, 0x000eb7b5,
+ 0x000eb7b9, 0x000eb7c5, 0x000eb7c9, 0x000eb7d1, 0x000eb7d5,
+ 0x000eb7d9, 0x000eb7c6, 0x000eb7ca, 0x000eb7ce, 0x000eb7d2,
+ 0x000eb7d6, 0x000eb7c3, 0x000eb7c7, 0x000eb7cb, 0x000eb7cf,
+ 0x000eb7d7, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db, 0x000eb7db,
+ 0x00000004, 0x0001f000, 0x0001f000, 0x1883800a, 0x00000108,
+ 0x0004a000, 0x7999aa0e
+};
+
+static const uint16_t ar9285_1_2_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x04060),
+ P(0x04064), P(0x07010), P(0x07034), P(0x07038), P(0x08004),
+ P(0x08008), P(0x0800c), P(0x08018), P(0x08020), P(0x08038),
+ P(0x0803c), P(0x08048), P(0x08054), P(0x08058), P(0x0805c),
+ P(0x08060), P(0x08064), P(0x08070), P(0x080c0), P(0x080c4),
+ P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4), P(0x080d8),
+ P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec), P(0x080f0),
+ P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100), P(0x08104),
+ P(0x08108), P(0x0810c), P(0x08110), P(0x08118), P(0x0811c),
+ P(0x08120), P(0x08124), P(0x08128), P(0x0812c), P(0x08130),
+ P(0x08134), P(0x08138), P(0x0813c), P(0x08144), P(0x08168),
+ P(0x0816c), P(0x08170), P(0x08174), P(0x08178), P(0x0817c),
+ P(0x081c0), P(0x081d0), P(0x081ec), P(0x081f0), P(0x081f4),
+ P(0x081f8), P(0x081fc), P(0x08200), P(0x08204), P(0x08208),
+ P(0x0820c), P(0x08210), P(0x08214), P(0x08218), P(0x0821c),
+ P(0x08220), P(0x08224), P(0x08228), P(0x0822c), P(0x08230),
+ P(0x08234), P(0x08238), P(0x0823c), P(0x08240), P(0x08244),
+ P(0x08248), P(0x0824c), P(0x08250), P(0x08254), P(0x08258),
+ P(0x0825c), P(0x08260), P(0x08264), P(0x08270), P(0x08274),
+ P(0x08278), P(0x0827c), P(0x08284), P(0x08288), P(0x0828c),
+ P(0x08294), P(0x08298), P(0x0829c), P(0x08300), P(0x08314),
+ P(0x08328), P(0x0832c), P(0x08330), P(0x08334), P(0x08338),
+ P(0x0833c), P(0x08340), P(0x08344), P(0x09808), P(0x0980c),
+ P(0x09810), P(0x09814), P(0x0981c), P(0x0982c), P(0x09830),
+ P(0x0983c), P(0x0984c), P(0x09854), P(0x09900), P(0x09904),
+ P(0x09908), P(0x0990c), P(0x09910), P(0x0991c), P(0x09920),
+ P(0x09928), P(0x0992c), P(0x09934), P(0x09938), P(0x0993c),
+ P(0x09940), P(0x09948), P(0x0994c), P(0x09954), P(0x09958),
+ P(0x09968), P(0x09970), P(0x09974), P(0x09978), P(0x0997c),
+ P(0x09980), P(0x09984), P(0x09988), P(0x0998c), P(0x09990),
+ P(0x09994), P(0x09998), P(0x0999c), P(0x099a0), P(0x099a4),
+ P(0x099a8), P(0x099ac), P(0x099b0), P(0x099b4), P(0x099dc),
+ P(0x099e0), P(0x099e4), P(0x099e8), P(0x099ec), P(0x099f0),
+ P(0x0a208), P(0x0a210), P(0x0a214), P(0x0a218), P(0x0a220),
+ P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234), P(0x0a238),
+ P(0x0a244), P(0x0a248), P(0x0a24c), P(0x0a254), P(0x0a258),
+ P(0x0a25c), P(0x0a260), P(0x0a268), P(0x0a26c), P(0x0d270),
+ P(0x0d35c), P(0x0d360), P(0x0d364), P(0x0d368), P(0x0d36c),
+ P(0x0d370), P(0x0d374), P(0x0d378), P(0x0d37c), P(0x0d380),
+ P(0x0d384), P(0x0a388), P(0x0a38c), P(0x0a390), P(0x0a39c),
+ P(0x0a3a0), P(0x0a3a4), P(0x0a3a8), P(0x0a3ac), P(0x0a3b0),
+ P(0x0a3b4), P(0x0a3b8), P(0x0a3bc), P(0x0a3c0), P(0x0a3c4),
+ P(0x0a3cc), P(0x0a3d0), P(0x0a3d4), P(0x0a3e4), P(0x0a3e8),
+ P(0x0a3ec), P(0x07800), P(0x07804), P(0x07808), P(0x0780c),
+ P(0x07810), P(0x07814), P(0x0781c), P(0x07824), P(0x07828),
+ P(0x0782c), P(0x07830), P(0x07834), P(0x0783c), P(0x07840),
+ P(0x07844), P(0x07848), P(0x0784c), P(0x07850), P(0x07854),
+ P(0x07858), P(0x0785c), P(0x07860), P(0x07864), P(0x07868),
+ P(0x07870)
+};
+
+static const uint32_t ar9285_1_2_cm_vals[] = {
+ 0x00000000, 0x00020045, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000031, 0x00000002, 0x000004c2, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000700, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000fc78f,
+ 0x0000000f, 0x00000000, 0x00000000, 0x2a80001a, 0x05dc01e0,
+ 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000, 0x00400000,
+ 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00020000, 0x00020000, 0x00000001,
+ 0x00000052, 0x00000000, 0x00000168, 0x000100aa, 0x00003210,
+ 0x08f04810, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000,
+ 0x00000000, 0x32143320, 0xfaa4fa50, 0x00000100, 0x00000000,
+ 0x00000000, 0x0000320a, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00100000, 0x0010f400,
+ 0x00000100, 0x0001e800, 0x00000000, 0x00000000, 0x00000000,
+ 0x400000ff, 0x00080922, 0x88a00010, 0x00000000, 0x40000000,
+ 0x003e4180, 0x00000000, 0x0000002c, 0x0000002c, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000000,
+ 0x00000000, 0x00000001, 0x00000302, 0x00000e00, 0x00ff0000,
+ 0x00000000, 0x00010380, 0x00481043, 0x00000000, 0xafe68e30,
+ 0xfd14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000, 0x00000000,
+ 0x00200400, 0x0040233c, 0x00000044, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x01002310, 0x10000fff, 0x04900000,
+ 0x00000001, 0x00000004, 0x1e1f2022, 0x0a0b0c0d, 0x00000000,
+ 0x14750604, 0x9280c00a, 0x00020028, 0x5f3ca3de, 0x2108ecff,
+ 0x000003ce, 0x192bb514, 0x00000000, 0x00000001, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
+ 0x201fff00, 0x2def0400, 0x03051000, 0x00000820, 0x00000000,
+ 0x00000000, 0xaaaaaaaa, 0x3c466478, 0x0cc80caa, 0x00000000,
+ 0x803e68c8, 0x4080a333, 0x00206c10, 0x009c4060, 0x01834061,
+ 0x00000400, 0x000003b5, 0x00000000, 0x20202020, 0x20202020,
+ 0x00000000, 0xfffffffc, 0x00000000, 0x00000000, 0x0ccb5380,
+ 0x15151501, 0xdfa90f01, 0x00000000, 0x0ebae9e6, 0x0d820820,
+ 0x07ffffef, 0x0fffffe7, 0x17ffffe5, 0x1fffffe4, 0x37ffffe3,
+ 0x3fffffe3, 0x57ffffe3, 0x5fffffe2, 0x7fffffe2, 0x7f3c7bba,
+ 0xf3307ff0, 0x0c000000, 0x20202020, 0x20202020, 0x00000001,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x20202020, 0x20202020, 0x20202020, 0x00000000, 0x18c43433,
+ 0x00f70081, 0x00140000, 0x0e4548d8, 0x54214514, 0x02025830,
+ 0x71c0d388, 0x924934a8, 0x00000000, 0x00d86fff, 0x26d2491b,
+ 0x6e36d97b, 0xedb6d96e, 0x71400087, 0x0001fffe, 0xffeb1a20,
+ 0x000c0db6, 0x6db61b6f, 0x6d9b66db, 0x6d8c6dba, 0x00040000,
+ 0xdb003012, 0x04924914, 0x21084210, 0xf7d7ffde, 0xc2034080,
+ 0x10142c00
+};
+
+static const struct athn_ini ar9285_1_2_ini = {
+ nitems(ar9285_1_2_regs),
+ ar9285_1_2_regs,
+ NULL, /* 2GHz only. */
+#ifndef IEEE80211_NO_HT
+ NULL, /* 2GHz only. */
+ ar9285_1_2_vals_2g40,
+#endif
+ ar9285_1_2_vals_2g20,
+ nitems(ar9285_1_2_cm_regs),
+ ar9285_1_2_cm_regs,
+ ar9285_1_2_cm_vals
+};
+
+/*
+ * AR9285 1.2 Tx gains.
+ */
+static const uint16_t ar9285_1_2_tx_gain_regs[] = {
+ P(0x0a300), P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310),
+ P(0x0a314), P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324),
+ P(0x0a328), P(0x0a32c), P(0x0a330), P(0x0a334), P(0x0a338),
+ P(0x0a33c), P(0x0a340), P(0x0a344), P(0x0a348), P(0x0a34c),
+ P(0x0a350), P(0x0a354), P(0x07838), P(0x0786c), P(0x07820),
+ P(0x0a274), P(0x0a278), P(0x0a27c), P(0x0a394), P(0x0a398),
+ P(0x0a3dc), P(0x0a3e0)
+};
+
+static const uint32_t ar9285_1_2_tx_gain_vals_2g[] = {
+ 0x00000000, 0x00009200, 0x00010208, 0x00019608, 0x00022618,
+ 0x0002a6c9, 0x00031710, 0x00035718, 0x00038758, 0x0003c75a,
+ 0x0004075c, 0x0004475e, 0x0004679f, 0x000487df, 0x0003891e,
+ 0x0003a95e, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df,
+ 0x0003e9df, 0x0003e9df, 0xfac68801, 0x48609eb4, 0x00000c04,
+ 0x0a21a652, 0x39ce739c, 0x050e039c, 0x39ce739c, 0x0000039c,
+ 0x39ce739c, 0x0000039c
+};
+
+static const struct athn_gain ar9285_1_2_tx_gain = {
+ nitems(ar9285_1_2_tx_gain_regs),
+ ar9285_1_2_tx_gain_regs,
+ NULL, /* 2GHz only. */
+ ar9285_1_2_tx_gain_vals_2g
+};
+
+static const uint32_t ar9285_1_2_tx_gain_high_power_vals_2g[] = {
+ 0x00000000, 0x00006200, 0x00008201, 0x0000b240, 0x0000d241,
+ 0x0000f600, 0x00012800, 0x00016802, 0x0001b805, 0x00021a80,
+ 0x00028b00, 0x0002ab40, 0x0002cd80, 0x00033d82, 0x0003891e,
+ 0x0003a95e, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df,
+ 0x0003e9df, 0x0003e9df, 0xfac68803, 0x08609ebe, 0x00000c00,
+ 0x0a216652, 0x0e739ce7, 0x050380e7, 0x0e739ce7, 0x000000e7,
+ 0x0e739ce7, 0x000000e7
+};
+
+static const struct athn_gain ar9285_1_2_tx_gain_high_power = {
+ nitems(ar9285_1_2_tx_gain_regs),
+ ar9285_1_2_tx_gain_regs,
+ NULL, /* 2GHz only. */
+ ar9285_1_2_tx_gain_high_power_vals_2g
+};
diff --git a/sys/dev/ic/ar9287.c b/sys/dev/ic/ar9287.c
new file mode 100644
index 00000000000..7a472f97fc8
--- /dev/null
+++ b/sys/dev/ic/ar9287.c
@@ -0,0 +1,605 @@
+/* $OpenBSD: ar9287.c,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for Atheros 802.11a/g/n chipsets.
+ * Routines for AR9227 and AR9287 chipsets.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/timeout.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/endian.h>
+#include <machine/intr.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/ic/athnreg.h>
+#include <dev/ic/athnvar.h>
+
+#include <dev/ic/ar9280reg.h>
+#include <dev/ic/ar9287reg.h>
+
+int ar9287_attach(struct athn_softc *);
+void ar9287_setup(struct athn_softc *);
+void ar9287_swap_rom(struct athn_softc *);
+const struct ar_spur_chan *ar9287_get_spur_chans(struct athn_softc *, int);
+void ar9287_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar9287_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
+ int, int, uint8_t, uint8_t *, uint8_t *);
+void ar9287_olpc_get_pdgain(struct athn_softc *, struct ieee80211_channel *,
+ int, int8_t *);
+void ar9287_set_power_calib(struct athn_softc *,
+ struct ieee80211_channel *);
+void ar9287_set_txpower(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar9287_olpc_init(struct athn_softc *);
+void ar9287_olpc_temp_compensation(struct athn_softc *);
+
+int
+ar9287_attach(struct athn_softc *sc)
+{
+ sc->eep_base = AR9287_EEP_START_LOC;
+ sc->eep_size = sizeof (struct ar9287_eeprom);
+ sc->def_nf = AR9287_PHY_CCA_MAX_GOOD_VALUE;
+ sc->ngpiopins = 11;
+ sc->workaround = AR9285_WA_DEFAULT;
+ sc->ops.setup = ar9287_setup;
+ sc->ops.swap_rom = ar9287_swap_rom;
+ sc->ops.init_from_rom = ar9287_init_from_rom;
+ sc->ops.set_txpower = ar9287_set_txpower;
+ sc->ops.set_synth = ar9280_set_synth;
+ sc->ops.spur_mitigate = ar9280_spur_mitigate;
+ sc->ops.get_spur_chans = ar9287_get_spur_chans;
+ sc->ops.olpc_init = ar9287_olpc_init;
+ if (AR_SREV_9287_11_OR_LATER(sc))
+ sc->ini = &ar9287_1_1_ini;
+ else
+ sc->ini = &ar9287_1_0_ini;
+ sc->serdes = ar9280_2_0_serdes;
+ return (0);
+}
+
+void
+ar9287_setup(struct athn_softc *sc)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+
+ /* Determine if open loop power control should be used. */
+ if (eep->baseEepHeader.openLoopPwrCntl)
+ sc->flags |= ATHN_FLAG_OLPC;
+ if (AR_SREV_9287_10(sc))
+ sc->rx_gain = &ar9287_1_0_rx_gain;
+ else
+ sc->rx_gain = &ar9287_1_1_rx_gain;
+ if (AR_SREV_9287_10(sc))
+ sc->tx_gain = &ar9287_1_0_tx_gain;
+ else
+ sc->tx_gain = &ar9287_1_1_tx_gain;
+}
+
+void
+ar9287_swap_rom(struct athn_softc *sc)
+{
+ struct ar9287_eeprom *eep = sc->eep;
+ int i;
+
+ eep->modalHeader.antCtrlCommon =
+ swap32(eep->modalHeader.antCtrlCommon);
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ eep->modalHeader.antCtrlChain[i] =
+ swap32(eep->modalHeader.antCtrlChain[i]);
+ }
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ eep->modalHeader.spurChans[i].spurChan =
+ swap16(eep->modalHeader.spurChans[i].spurChan);
+ }
+}
+
+const struct ar_spur_chan *
+ar9287_get_spur_chans(struct athn_softc *sc, int is2ghz)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+
+ KASSERT(is2ghz);
+ return eep->modalHeader.spurChans;
+}
+
+void
+ar9287_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+ const struct ar9287_modal_eep_header *modal = &eep->modalHeader;
+ uint32_t reg, offset;
+ int i;
+
+ AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon & 0xffff);
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ offset = i * 0x1000;
+
+ AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
+ modal->antCtrlChain[i]);
+
+ reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+ modal->iqCalICh[i]);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+ modal->iqCalQCh[i]);
+ AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
+
+ reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ modal->bswMargin[i]);
+ reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ modal->bswAtten[i]);
+ AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
+
+ reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN,
+ modal->rxTxMarginCh[i]);
+ reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN,
+ modal->txRxAttenCh[i]);
+ AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
+ }
+
+ reg = AR_READ(sc, AR_PHY_SETTLING);
+#ifndef IEEE80211_NO_HT
+ if (extc != NULL)
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
+ else
+#endif
+ reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
+ AR_WRITE(sc, AR_PHY_SETTLING, reg);
+
+ reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
+ reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
+ AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
+
+ reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
+ reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
+
+ reg = AR_READ(sc, AR_PHY_RF_CTL3);
+ reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
+
+ reg = AR_READ(sc, AR_PHY_CCA(0));
+ reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_CCA(0), reg);
+
+ reg = AR_READ(sc, AR_PHY_EXT_CCA0);
+ reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
+ AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
+
+ reg = AR_READ(sc, AR9287_AN_RF2G3_CH0);
+ reg = RW(reg, AR9287_AN_RF2G3_DB1, modal->db1);
+ reg = RW(reg, AR9287_AN_RF2G3_DB2, modal->db2);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_CCK, modal->ob_cck);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_PSK, modal->ob_psk);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_QAM, modal->ob_qam);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_PAL_OFF, modal->ob_pal_off);
+ AR_WRITE(sc, AR9287_AN_RF2G3_CH0, reg);
+ DELAY(100);
+
+ reg = AR_READ(sc, AR9287_AN_RF2G3_CH1);
+ reg = RW(reg, AR9287_AN_RF2G3_DB1, modal->db1);
+ reg = RW(reg, AR9287_AN_RF2G3_DB2, modal->db2);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_CCK, modal->ob_cck);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_PSK, modal->ob_psk);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_QAM, modal->ob_qam);
+ reg = RW(reg, AR9287_AN_RF2G3_OB_PAL_OFF, modal->ob_pal_off);
+ AR_WRITE(sc, AR9287_AN_RF2G3_CH1, reg);
+ DELAY(100);
+
+ reg = AR_READ(sc, AR_PHY_RF_CTL2);
+ reg = RW(reg, AR_PHY_TX_END_DATA_START, modal->txFrameToDataStart);
+ reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
+ AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
+
+ reg = AR_READ(sc, AR9287_AN_TOP2);
+ reg = RW(reg, AR9287_AN_TOP2_XPABIAS_LVL, modal->xpaBiasLvl);
+ AR_WRITE(sc, AR9287_AN_TOP2, reg);
+ DELAY(100);
+}
+
+void
+ar9287_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
+ int chain, int nxpdgains, uint8_t overlap, uint8_t *boundaries,
+ uint8_t *pdadcs)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+ const struct ar9287_cal_data_per_freq *pierdata;
+ const uint8_t *pierfreq;
+ struct athn_pier lopier, hipier;
+ int16_t delta;
+ uint8_t fbin;
+ int i, lo, hi, npiers;
+
+ pierfreq = eep->calFreqPier2G;
+ pierdata = (const struct ar9287_cal_data_per_freq *)
+ eep->calPierData2G[chain];
+ npiers = AR9287_NUM_2G_CAL_PIERS;
+
+ /* Find channel in ROM pier table. */
+ fbin = athn_chan2fbin(c);
+ athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
+
+ lopier.fbin = pierfreq[lo];
+ hipier.fbin = pierfreq[hi];
+ for (i = 0; i < nxpdgains; i++) {
+ lopier.pwr[i] = pierdata[lo].pwrPdg[i];
+ lopier.vpd[i] = pierdata[lo].vpdPdg[i];
+ hipier.pwr[i] = pierdata[lo].pwrPdg[i];
+ hipier.vpd[i] = pierdata[lo].vpdPdg[i];
+ }
+ athn_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
+ AR9287_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
+
+ delta = (eep->baseEepHeader.pwrTableOffset -
+ AR_PWR_TABLE_OFFSET_DB) * 2; /* In half dB. */
+ if (delta != 0) {
+ /* Shift the PDADC table to start at the new offset. */
+ /* XXX Our padding value differs from Linux. */
+ for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
+ pdadcs[i] = pdadcs[MIN(i + delta,
+ AR_NUM_PDADC_VALUES - 1)];
+ }
+}
+
+void
+ar9287_olpc_get_pdgain(struct athn_softc *sc, struct ieee80211_channel *c,
+ int chain, int8_t *pwr)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+ const struct ar_cal_data_per_freq_olpc *pierdata;
+ const uint8_t *pierfreq;
+ uint8_t fbin;
+ int lo, hi, npiers;
+
+ pierfreq = eep->calFreqPier2G;
+ pierdata = (const struct ar_cal_data_per_freq_olpc *)
+ eep->calPierData2G[chain];
+ npiers = AR9287_NUM_2G_CAL_PIERS;
+
+ /* Find channel in ROM pier table. */
+ fbin = athn_chan2fbin(c);
+ athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
+
+#if 0
+ *pwr = athn_interpolate(fbin,
+ pierfreq[lo], pierdata[lo].pwrPdg[0][0],
+ pierfreq[hi], pierdata[hi].pwrPdg[0][0]);
+#else
+ *pwr = (pierdata[lo].pwrPdg[0][0] + pierdata[hi].pwrPdg[0][0]) / 2;
+#endif
+}
+
+void
+ar9287_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+ uint8_t boundaries[AR_PD_GAINS_IN_MASK];
+ uint8_t pdadcs[AR_NUM_PDADC_VALUES];
+ uint8_t xpdgains[AR9287_NUM_PD_GAINS];
+ int8_t txpower;
+ uint8_t overlap;
+ uint32_t reg, offset;
+ int i, j, nxpdgains;
+
+ if (sc->eep_rev < AR_EEP_MINOR_VER_2) {
+ overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
+ } else
+ overlap = eep->modalHeader.pdGainOverlap;
+
+ if (sc->flags & ATHN_FLAG_OLPC) {
+ /* XXX not here. */
+ sc->pdadc =
+ ((const struct ar_cal_data_per_freq_olpc *)
+ eep->calPierData2G[0])->vpdPdg[0][0];
+ }
+
+ nxpdgains = 0;
+ memset(xpdgains, 0, sizeof xpdgains);
+ for (i = AR9287_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
+ if (nxpdgains >= AR9287_NUM_PD_GAINS)
+ break; /* Can't happen. */
+ if (eep->modalHeader.xpdGain & (1 << i))
+ xpdgains[nxpdgains++] = i;
+ }
+ reg = AR_READ(sc, AR_PHY_TPCRG1);
+ reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
+ reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
+ reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
+ AR_WRITE(sc, AR_PHY_TPCRG1, reg);
+
+ for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+ if (!(sc->txchainmask & (1 << i)))
+ continue;
+
+ offset = i * 0x1000;
+
+ if (sc->flags & ATHN_FLAG_OLPC) {
+ ar9287_olpc_get_pdgain(sc, c, i, &txpower);
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_0);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+ AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_0, reg);
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_1);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
+ AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_1, reg);
+
+ /* NB: txpower is in half dB. */
+ reg = AR_READ(sc, AR_PHY_CH0_TX_PWRCTRL11 + offset);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_PWR, txpower);
+ AR_WRITE(sc, AR_PHY_CH0_TX_PWRCTRL11 + offset, reg);
+
+ continue; /* That's it for open loop mode. */
+ }
+
+ /* Closed loop power control. */
+ ar9287_get_pdadcs(sc, c, i, nxpdgains, overlap,
+ boundaries, pdadcs);
+
+ /* Write boundaries. */
+ if (i == 0) {
+ reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP,
+ overlap);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1,
+ boundaries[0]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2,
+ boundaries[1]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3,
+ boundaries[2]);
+ reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4,
+ boundaries[3]);
+ AR_WRITE(sc, AR_PHY_TPCRG5 + offset, reg);
+ }
+ /* Write PDADC values. */
+ for (j = 0; j < AR_NUM_PDADC_VALUES; j += 4) {
+ AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + offset + j,
+ pdadcs[j + 0] << 0 |
+ pdadcs[j + 1] << 8 |
+ pdadcs[j + 2] << 16 |
+ pdadcs[j + 3] << 24);
+ }
+ }
+}
+
+void
+ar9287_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+ const struct ar9287_modal_eep_header *modal = &eep->modalHeader;
+ uint8_t tpow_cck[4], tpow_ofdm[4];
+ uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
+ uint8_t tpow_ht20[8], tpow_ht40[8];
+ int16_t pwr, max_ant_gain, power[ATHN_POWER_COUNT];
+ uint8_t ht40inc;
+ int i;
+
+ /* Compute transmit power reduction due to antenna gain. */
+ max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1]);
+ /* XXX */
+
+ /*
+ * Reduce scaled power by number of active chains to get per-chain
+ * transmit power level.
+ */
+ if (sc->ntxchains == 2)
+ pwr -= AR_PWR_DECREASE_FOR_2_CHAIN;
+ if (pwr < 0)
+ pwr = 0;
+
+ /* Get CCK target powers. */
+ athn_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
+ AR9287_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
+
+ /* Get OFDM target powers. */
+ athn_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
+ AR9287_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
+
+#ifndef IEEE80211_NO_HT
+ /* Get HT-20 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20,
+ AR9287_NUM_2G_20_TARGET_POWERS, tpow_ht20);
+
+ if (extc != NULL) {
+ /* Get HT-40 target powers. */
+ athn_get_ht_tpow(sc, c, AR_CTL_2GHT40,
+ eep->calTargetPower2GHT40, AR9287_NUM_2G_40_TARGET_POWERS,
+ tpow_ht40);
+
+ /* Get secondary channel CCK target powers. */
+ athn_get_lg_tpow(sc, extc, AR_CTL_11B, eep->calTargetPowerCck,
+ AR9287_NUM_2G_CCK_TARGET_POWERS, tpow_cck_ext);
+
+ /* Get secondary channel OFDM target powers. */
+ athn_get_lg_tpow(sc, extc, AR_CTL_11G, eep->calTargetPower2G,
+ AR9287_NUM_2G_20_TARGET_POWERS, tpow_ofdm_ext);
+ }
+#endif
+
+ memset(power, 0, sizeof power);
+ /* Shuffle target powers accross transmit rates. */
+ power[ATHN_POWER_OFDM6 ] =
+ power[ATHN_POWER_OFDM9 ] =
+ power[ATHN_POWER_OFDM12 ] =
+ power[ATHN_POWER_OFDM18 ] =
+ power[ATHN_POWER_OFDM24 ] = tpow_ofdm[0];
+ power[ATHN_POWER_OFDM36 ] = tpow_ofdm[1];
+ power[ATHN_POWER_OFDM48 ] = tpow_ofdm[2];
+ power[ATHN_POWER_OFDM54 ] = tpow_ofdm[3];
+ power[ATHN_POWER_XR ] = tpow_ofdm[0];
+ power[ATHN_POWER_CCK1_LP ] = tpow_cck[0];
+ power[ATHN_POWER_CCK2_LP ] =
+ power[ATHN_POWER_CCK2_SP ] = tpow_cck[1];
+ power[ATHN_POWER_CCK55_LP] =
+ power[ATHN_POWER_CCK55_SP] = tpow_cck[2];
+ power[ATHN_POWER_CCK11_LP] =
+ power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
+#ifndef IEEE80211_NO_HT
+ for (i = 0; i < nitems(tpow_ht20); i++)
+ power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
+ if (extc != NULL) {
+ /* Correct PAR difference between HT40 and HT20/Legacy. */
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2)
+ ht40inc = modal->ht40PowerIncForPdadc;
+ else
+ ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
+ for (i = 0; i < nitems(tpow_ht40); i++)
+ power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
+ power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
+ power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0];
+ power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ power[ATHN_POWER_CCK_EXT] = tpow_cck_ext[0];
+ }
+#endif
+
+ for (i = 0; i < ATHN_POWER_COUNT; i++) {
+ power[i] -= AR_PWR_TABLE_OFFSET_DB * 2; /* In half dB. */
+ if (power[i] > AR_MAX_RATE_POWER)
+ power[i] = AR_MAX_RATE_POWER;
+ }
+ /* Commit transmit power values to hardware. */
+ athn_write_txpower(sc, power);
+}
+
+void
+ar9287_olpc_init(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ AR_SETBITS(sc, AR_PHY_TX_PWRCTRL9, AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
+
+ reg = AR_READ(sc, AR9287_AN_TXPC0);
+ reg = RW(reg, AR9287_AN_TXPC0_TXPCMODE,
+ AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
+ AR_WRITE(sc, AR9287_AN_TXPC0, reg);
+ DELAY(100);
+}
+
+void
+ar9287_olpc_temp_compensation(struct athn_softc *sc)
+{
+ const struct ar9287_eeprom *eep = sc->eep;
+ int8_t pdadc, slope, tcomp;
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_PHY_TX_PWRCTRL4);
+ pdadc = MS(reg, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
+ DPRINTF(("PD Avg Out=%d\n", pdadc));
+
+ if (sc->pdadc == 0 || pdadc == 0)
+ return; /* No frames transmitted yet. */
+
+ /* Compute Tx gain temperature compensation. */
+ if (sc->eep_rev >= AR_EEP_MINOR_VER_2)
+ slope = eep->baseEepHeader.tempSensSlope;
+ else
+ slope = 0;
+ if (slope != 0) /* Prevents division by zero. */
+ tcomp = ((pdadc - sc->pdadc) * 4) / slope;
+ else
+ tcomp = 0;
+ DPRINTF(("OLPC temp compensation=%d\n", tcomp));
+
+ /* Write compensation value for both Tx chains. */
+ reg = AR_READ(sc, AR_PHY_CH0_TX_PWRCTRL11);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, tcomp);
+ AR_WRITE(sc, AR_PHY_CH0_TX_PWRCTRL11, reg);
+
+ reg = AR_READ(sc, AR_PHY_CH1_TX_PWRCTRL11);
+ reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, tcomp);
+ AR_WRITE(sc, AR_PHY_CH1_TX_PWRCTRL11, reg);
+}
+
+void
+ar9287_1_2_enable_async_fifo(struct athn_softc *sc)
+{
+ /* Enable ASYNC FIFO. */
+ AR_SETBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL);
+ AR_SETBITS(sc, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO);
+ AR_CLRBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+ AR_SETBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,
+ AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET);
+}
+
+void
+ar9287_1_2_setup_async_fifo(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ AR_WRITE(sc, AR_D_GBL_IFS_SIFS, AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
+ AR_WRITE(sc, AR_D_GBL_IFS_SLOT, AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
+ AR_WRITE(sc, AR_D_GBL_IFS_EIFS, AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
+
+ AR_WRITE(sc, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
+ AR_WRITE(sc, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
+
+ AR_SETBITS(sc, AR_MAC_PCU_LOGIC_ANALYZER,
+ AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
+
+ reg = AR_READ(sc, AR_AHB_MODE);
+ reg = RW(reg, AR_AHB_CUSTOM_BURST, AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
+ AR_WRITE(sc, AR_AHB_MODE, reg);
+
+ AR_SETBITS(sc, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
+}
diff --git a/sys/dev/ic/ar9287reg.h b/sys/dev/ic/ar9287reg.h
new file mode 100644
index 00000000000..19d1b8df617
--- /dev/null
+++ b/sys/dev/ic/ar9287reg.h
@@ -0,0 +1,896 @@
+/* $OpenBSD: ar9287reg.h,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define AR9287_MAX_CHAINS 2
+
+#define AR9287_PHY_CCA_MAX_GOOD_VALUE (-118)
+
+/*
+ * Analog registers.
+ */
+#define AR9287_AN_RF2G3_CH0 0x7808
+#define AR9287_AN_RF2G3_CH1 0x785c
+#define AR9287_AN_TXPC0 0x7898
+#define AR9287_AN_TOP2 0x78b4
+
+/* Bits for AR9287_AN_RF2G3_CH[01]. */
+#define AR9287_AN_RF2G3_DB1_M 0xe0000000
+#define AR9287_AN_RF2G3_DB1_S 29
+#define AR9287_AN_RF2G3_DB2_M 0x1c000000
+#define AR9287_AN_RF2G3_DB2_S 26
+#define AR9287_AN_RF2G3_OB_CCK_M 0x03800000
+#define AR9287_AN_RF2G3_OB_CCK_S 23
+#define AR9287_AN_RF2G3_OB_PSK_M 0x00700000
+#define AR9287_AN_RF2G3_OB_PSK_S 20
+#define AR9287_AN_RF2G3_OB_QAM_M 0x000e0000
+#define AR9287_AN_RF2G3_OB_QAM_S 17
+#define AR9287_AN_RF2G3_OB_PAL_OFF_M 0x0001c000
+#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14
+
+/* Bits for AR9287_AN_TXPC0. */
+#define AR9287_AN_TXPC0_TXPCMODE_M 0x0000c000
+#define AR9287_AN_TXPC0_TXPCMODE_S 14
+#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0
+#define AR9287_AN_TXPC0_TXPCMODE_TEST 1
+#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2
+#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3
+
+/* Bits for AR9287_AN_TOP2. */
+#define AR9287_AN_TOP2_XPABIAS_LVL_M 0xc0000000
+#define AR9287_AN_TOP2_XPABIAS_LVL_S 30
+
+/*
+ * ROM layout used by AR9287 (2GHz only).
+ */
+#define AR9287_EEP_START_LOC 128
+#define AR9287_NUM_2G_CAL_PIERS 3
+#define AR9287_NUM_2G_CCK_TARGET_POWERS 3
+#define AR9287_NUM_2G_20_TARGET_POWERS 3
+#define AR9287_NUM_2G_40_TARGET_POWERS 3
+#define AR9287_NUM_CTLS 12
+#define AR9287_NUM_BAND_EDGES 4
+#define AR9287_NUM_PD_GAINS 4
+#define AR9287_PD_GAINS_IN_MASK 4
+#define AR9287_PD_GAIN_ICEPTS 1
+#define AR9287_MAX_RATE_POWER 63
+#define AR9287_NUM_RATES 16
+
+struct ar9287_base_eep_header {
+ uint16_t length;
+ uint16_t checksum;
+ uint16_t version;
+ uint8_t opCapFlags;
+ uint8_t eepMisc;
+#define AR9287_EEPMISC_BIG_ENDIAN 0x01
+#define AR9287_EEPMISC_WOW 0x02
+
+ uint16_t regDmn[2];
+ uint8_t macAddr[6];
+ uint8_t rxMask;
+ uint8_t txMask;
+ uint16_t rfSilent;
+ uint16_t blueToothOptions;
+ uint16_t deviceCap;
+ uint32_t binBuildNumber;
+ uint8_t deviceType;
+ /* End of common header. */
+ uint8_t openLoopPwrCntl;
+ int8_t pwrTableOffset;
+ int8_t tempSensSlope;
+ int8_t tempSensSlopePalOn;
+ uint8_t futureBase[29];
+} __packed;
+
+struct ar9287_modal_eep_header {
+ uint32_t antCtrlChain[AR9287_MAX_CHAINS];
+ uint32_t antCtrlCommon;
+ int8_t antennaGainCh[AR9287_MAX_CHAINS];
+ uint8_t switchSettling;
+ uint8_t txRxAttenCh[AR9287_MAX_CHAINS];
+ uint8_t rxTxMarginCh[AR9287_MAX_CHAINS];
+ int8_t adcDesiredSize;
+ uint8_t txEndToXpaOff;
+ uint8_t txEndToRxOn;
+ uint8_t txFrameToXpaOn;
+ uint8_t thresh62;
+ int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
+ uint8_t xpdGain;
+ uint8_t xpd;
+ int8_t iqCalICh[AR9287_MAX_CHAINS];
+ int8_t iqCalQCh[AR9287_MAX_CHAINS];
+ uint8_t pdGainOverlap;
+ uint8_t xpaBiasLvl;
+ uint8_t txFrameToDataStart;
+ uint8_t txFrameToPaOn;
+ uint8_t ht40PowerIncForPdadc;
+ uint8_t bswAtten[AR9287_MAX_CHAINS];
+ uint8_t bswMargin[AR9287_MAX_CHAINS];
+ uint8_t swSettleHt40;
+ uint8_t version;
+ uint8_t db1;
+ uint8_t db2;
+ uint8_t ob_cck;
+ uint8_t ob_psk;
+ uint8_t ob_qam;
+ uint8_t ob_pal_off;
+ uint8_t futureModal[30];
+ struct ar_spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
+} __packed;
+
+struct ar9287_cal_data_per_freq {
+ uint8_t pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+ uint8_t vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
+} __packed;
+
+union ar9287_cal_data_per_freq_u {
+ struct ar_cal_data_per_freq_olpc calDataOpen;
+ struct ar9287_cal_data_per_freq calDataClose;
+} __packed;
+
+struct ar9287_cal_ctl_data {
+ struct ar_cal_ctl_edges
+ ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES];
+} __packed;
+
+struct ar9287_eeprom {
+ struct ar9287_base_eep_header baseEepHeader;
+ uint8_t custData[32];
+ struct ar9287_modal_eep_header modalHeader;
+ uint8_t calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
+ union ar9287_cal_data_per_freq_u
+ calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
+ struct ar_cal_target_power_leg
+ calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
+ struct ar_cal_target_power_leg
+ calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
+ struct ar_cal_target_power_ht
+ calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
+ uint8_t ctlIndex[AR9287_NUM_CTLS];
+ struct ar9287_cal_ctl_data ctlData[AR9287_NUM_CTLS];
+ uint8_t padding;
+} __packed;
+
+/* Macro to "pack" registers to 16-bit to save some .rodata space. */
+#define P(x) (x)
+
+/*
+ * AR9287 1.0 initialization values.
+ */
+static const uint16_t ar9287_1_0_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x08120), P(0x081d0), P(0x08318), P(0x09804),
+ P(0x09820), P(0x09824), P(0x09828), P(0x09834), P(0x09838),
+ P(0x09840), P(0x09844), P(0x09850), P(0x09858), P(0x0985c),
+ P(0x09860), P(0x09864), P(0x09868), P(0x0986c), P(0x09914),
+ P(0x09918), P(0x09924), P(0x09944), P(0x09960), P(0x0a960),
+ P(0x09964), P(0x0c968), P(0x099b8), P(0x099bc), P(0x099c0),
+ P(0x0a204), P(0x0a20c), P(0x0b20c), P(0x0a21c), P(0x0a230),
+ P(0x0a250), P(0x0a358), P(0x0a3d8)
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar9287_1_0_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00000000, 0x10801600,
+ 0x12e00057, 0x08f04810, 0x0000320a, 0x00006880, 0x000003c4,
+ 0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
+ 0x206a012e, 0x037216a0, 0x6d4000e2, 0x7ec84d2e, 0x3139605e,
+ 0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00001130,
+ 0x00000016, 0xd00a8a0d, 0xefbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
+ 0x00000444, 0x00000000, 0x00000000, 0x1883800a, 0x00000210,
+ 0x0004a000, 0x7999aa0e, 0x00000000
+};
+#endif
+
+static const uint32_t ar9287_1_0_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x00000000, 0x08400b00,
+ 0x12e0002b, 0x08f04810, 0x0000320a, 0x00003440, 0x00000300,
+ 0x02020200, 0x01000e0e, 0x0a020001, 0x00000e0e, 0x00000007,
+ 0x206a012e, 0x037216a0, 0x6c4000e2, 0x7ec84d2e, 0x31395d5e,
+ 0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00000898,
+ 0x0000000b, 0xd00a8a0d, 0xefbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
+ 0x00000444, 0x00000000, 0x00000000, 0x1883800a, 0x00000108,
+ 0x0004a000, 0x7999aa0e, 0x00000000
+};
+
+static const uint16_t ar9287_1_0_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x04060),
+ P(0x04064), P(0x07010), P(0x07020), P(0x07034), P(0x07038),
+ P(0x08004), P(0x08008), P(0x0800c), P(0x08018), P(0x08020),
+ P(0x08038), P(0x0803c), P(0x08048), P(0x08054), P(0x08058),
+ P(0x0805c), P(0x08060), P(0x08064), P(0x08070), P(0x080c0),
+ P(0x080c4), P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4),
+ P(0x080d8), P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec),
+ P(0x080f0), P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100),
+ P(0x08104), P(0x08108), P(0x0810c), P(0x08110), P(0x08118),
+ P(0x0811c), P(0x08124), P(0x08128), P(0x0812c), P(0x08130),
+ P(0x08134), P(0x08138), P(0x0813c), P(0x08144), P(0x08168),
+ P(0x0816c), P(0x08170), P(0x08174), P(0x08178), P(0x0817c),
+ P(0x081c0), P(0x081c4), P(0x081d4), P(0x081ec), P(0x081f0),
+ P(0x081f4), P(0x081f8), P(0x081fc), P(0x08200), P(0x08204),
+ P(0x08208), P(0x0820c), P(0x08210), P(0x08214), P(0x08218),
+ P(0x0821c), P(0x08220), P(0x08224), P(0x08228), P(0x0822c),
+ P(0x08230), P(0x08234), P(0x08238), P(0x0823c), P(0x08240),
+ P(0x08244), P(0x08248), P(0x0824c), P(0x08250), P(0x08254),
+ P(0x08258), P(0x0825c), P(0x08260), P(0x08264), P(0x08270),
+ P(0x08274), P(0x08278), P(0x0827c), P(0x08284), P(0x08288),
+ P(0x0828c), P(0x08294), P(0x08298), P(0x0829c), P(0x08300),
+ P(0x08314), P(0x08328), P(0x0832c), P(0x08330), P(0x08334),
+ P(0x08338), P(0x0833c), P(0x08340), P(0x08344), P(0x08360),
+ P(0x08364), P(0x08368), P(0x08370), P(0x08374), P(0x08378),
+ P(0x0837c), P(0x08380), P(0x08384), P(0x08390), P(0x08394),
+ P(0x08398), P(0x0839c), P(0x083a0), P(0x09808), P(0x0980c),
+ P(0x09810), P(0x09814), P(0x0981c), P(0x0982c), P(0x09830),
+ P(0x0983c), P(0x0984c), P(0x0a84c), P(0x09854), P(0x09900),
+ P(0x09904), P(0x09908), P(0x0990c), P(0x09910), P(0x0991c),
+ P(0x09920), P(0x0a920), P(0x09928), P(0x0992c), P(0x09930),
+ P(0x0a930), P(0x09934), P(0x09938), P(0x0993c), P(0x09948),
+ P(0x0994c), P(0x09954), P(0x09958), P(0x09940), P(0x0c95c),
+ P(0x09970), P(0x09974), P(0x09978), P(0x0997c), P(0x099a0),
+ P(0x099a4), P(0x099a8), P(0x099ac), P(0x099b0), P(0x099b4),
+ P(0x099c4), P(0x099c8), P(0x099cc), P(0x099d0), P(0x099dc),
+ P(0x099e0), P(0x099e4), P(0x099e8), P(0x099ec), P(0x099f0),
+ P(0x099fc), P(0x0a1f4), P(0x0a1f8), P(0x0a1fc), P(0x0a208),
+ P(0x0a210), P(0x0a214), P(0x0a218), P(0x0a220), P(0x0a224),
+ P(0x0a228), P(0x0a22c), P(0x0a234), P(0x0a238), P(0x0a23c),
+ P(0x0a240), P(0x0a244), P(0x0a248), P(0x0a24c), P(0x0a254),
+ P(0x0a258), P(0x0a25c), P(0x0a260), P(0x0a264), P(0x0b264),
+ P(0x0a268), P(0x0a26c), P(0x0b26c), P(0x0d270), P(0x0a278),
+ P(0x0a27c), P(0x0d35c), P(0x0d360), P(0x0d364), P(0x0d368),
+ P(0x0d36c), P(0x0d370), P(0x0d374), P(0x0d378), P(0x0d37c),
+ P(0x0d380), P(0x0d384), P(0x0a388), P(0x0a38c), P(0x0a390),
+ P(0x0a394), P(0x0a398), P(0x0b398), P(0x0a39c), P(0x0a3c8),
+ P(0x0a3cc), P(0x0a3d0), P(0x0a3d4), P(0x0a3dc), P(0x0a3e0),
+ P(0x0a3e4), P(0x0a3e8), P(0x0a3ec), P(0x0a3f0), P(0x0a3f4),
+ P(0x0b3f4), P(0x0a7d8), P(0x07800), P(0x07804), P(0x07808),
+ P(0x0780c), P(0x07810), P(0x07814), P(0x07818), P(0x0781c),
+ P(0x07820), P(0x07824), P(0x07828), P(0x0782c), P(0x07830),
+ P(0x07834), P(0x07838), P(0x0783c), P(0x07840), P(0x07844),
+ P(0x07848), P(0x07850), P(0x07854), P(0x07858), P(0x0785c),
+ P(0x07860), P(0x07864), P(0x07868), P(0x0786c), P(0x07870),
+ P(0x07874), P(0x07878), P(0x0787c), P(0x07880), P(0x07884),
+ P(0x07888), P(0x0788c), P(0x07890), P(0x07894), P(0x07898),
+ P(0x0789c), P(0x078a0), P(0x078a4), P(0x078a8), P(0x078ac),
+ P(0x078b0), P(0x078b4), P(0x078b8)
+};
+
+static const uint32_t ar9287_1_0_cm_vals[] = {
+ 0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000033, 0x00000000, 0x00000002, 0x000004c2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000,
+ 0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000,
+ 0x000fc78f, 0x0000000f, 0x00000000, 0x00000000, 0x2a80001a,
+ 0x05dc01e0, 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000,
+ 0x00400000, 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00020000, 0x00020000,
+ 0x00000001, 0x00000052, 0x00000000, 0x00000168, 0x000100aa,
+ 0x00003210, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000,
+ 0x00000000, 0x18487320, 0xfaa4fa50, 0x00000100, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00100000,
+ 0x0010f400, 0x00000100, 0x0001e800, 0x00000000, 0x00000000,
+ 0x00000000, 0x400000ff, 0x00080922, 0xa8a00010, 0x00000000,
+ 0x40000000, 0x003e4180, 0x00000000, 0x0000002c, 0x0000002c,
+ 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000040,
+ 0x00000000, 0x00000000, 0x00000007, 0x00000302, 0x00000e00,
+ 0x00ff0000, 0x00000000, 0x000107ff, 0x01c81043, 0xffffffff,
+ 0xffffffff, 0x00000000, 0x00000000, 0x000000ff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x0fffffff, 0x0fffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xafe68e30,
+ 0xfd14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000, 0x00000000,
+ 0x00200400, 0x0040233c, 0x0040233c, 0x00000044, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x10002310, 0x10000fff,
+ 0x04900000, 0x04900000, 0x00000001, 0x00000004, 0x00000000,
+ 0x00000000, 0x1e1f2022, 0x0a0b0c0d, 0x00000000, 0x9280c00a,
+ 0x00020028, 0x5f3ca3de, 0x0108ecff, 0x14750604, 0x004b6a8e,
+ 0x990bb515, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000001, 0x201fff00, 0x0c6f0000, 0x03051000, 0x00000820,
+ 0x06336f77, 0x6af65329, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0xaaaaaaaa, 0x3c466478, 0x0cc80caa, 0x00000000,
+ 0x00001042, 0x00fffeff, 0x00f5f9ff, 0xb79f6427, 0x803e4788,
+ 0x4080a333, 0x40206c10, 0x009c4060, 0x01834061, 0x00000400,
+ 0x000003b5, 0x233f7180, 0x20202020, 0x20202020, 0x13c889af,
+ 0x38490a20, 0x00000000, 0xfffffffc, 0x00000000, 0x00000000,
+ 0x0cdbd380, 0x0f0f0f01, 0xdfa91f01, 0x00418a11, 0x00418a11,
+ 0x00000000, 0x0e79e5c6, 0x0e79e5c6, 0x00820820, 0x1ce739ce,
+ 0x050701ce, 0x07ffffef, 0x0fffffe7, 0x17ffffe5, 0x1fffffe4,
+ 0x37ffffe3, 0x3fffffe3, 0x57ffffe3, 0x5fffffe2, 0x7fffffe2,
+ 0x7f3c7bba, 0xf3307ff0, 0x0c000000, 0x20202020, 0x20202020,
+ 0x1ce739ce, 0x000001ce, 0x000001ce, 0x00000001, 0x00000246,
+ 0x20202020, 0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce,
+ 0x00000000, 0x18c43433, 0x00f70081, 0x01036a1e, 0x00000000,
+ 0x00000000, 0x00000001, 0x00000800, 0x6c35ffb0, 0x6db6c000,
+ 0x6db6cb30, 0x6db6cb6c, 0x0501e200, 0x0094128d, 0x976ee392,
+ 0xf75ff6fc, 0x00040000, 0xdb003012, 0x04924914, 0x21084210,
+ 0x00140000, 0x0e4548d8, 0x54214514, 0x02025820, 0x71c0d388,
+ 0x934934a8, 0x00000000, 0x00000800, 0x6c35ffb0, 0x6db6c000,
+ 0x6db6cb2c, 0x6db6cb6c, 0x0501e200, 0x0094128d, 0x976ee392,
+ 0xf75ff6fc, 0x00040000, 0xdb003012, 0x04924914, 0x21084210,
+ 0x001b6db0, 0x00376b63, 0x06db6db6, 0x006d8000, 0x48100000,
+ 0x00000000, 0x08000000, 0x0007ffd8, 0x0007ffd8, 0x001c0020,
+ 0x000611eb, 0x40008080, 0x2a850160
+};
+
+static const struct athn_ini ar9287_1_0_ini = {
+ nitems(ar9287_1_0_regs),
+ ar9287_1_0_regs,
+ NULL, /* 2GHz only. */
+#ifndef IEEE80211_NO_HT
+ NULL, /* 2GHz only. */
+ ar9287_1_0_vals_2g40,
+#endif
+ ar9287_1_0_vals_2g20,
+ nitems(ar9287_1_0_cm_regs),
+ ar9287_1_0_cm_regs,
+ ar9287_1_0_cm_vals
+};
+
+/*
+ * AR9287 1.1 initialization values.
+ */
+static const uint16_t ar9287_1_1_regs[] = {
+ P(0x01030), P(0x01070), P(0x010b0), P(0x010f0), P(0x08014),
+ P(0x0801c), P(0x08120), P(0x081d0), P(0x08318), P(0x09804),
+ P(0x09820), P(0x09824), P(0x09828), P(0x09834), P(0x09838),
+ P(0x09840), P(0x09844), P(0x09850), P(0x09858), P(0x0985c),
+ P(0x09860), P(0x09864), P(0x09868), P(0x0986c), P(0x09914),
+ P(0x09918), P(0x09924), P(0x09944), P(0x09960), P(0x0a960),
+ P(0x09964), P(0x0c968), P(0x099b8), P(0x099bc), P(0x099c0),
+ P(0x0a204), P(0x0a20c), P(0x0b20c), P(0x0a21c), P(0x0a230),
+ P(0x0a250), P(0x0a358), P(0x0a3d8)
+};
+
+#ifndef IEEE80211_NO_HT
+static const uint32_t ar9287_1_1_vals_2g40[] = {
+ 0x000002c0, 0x00000318, 0x00007c70, 0x00000000, 0x10801600,
+ 0x12e00057, 0x08f04810, 0x0000320a, 0x00006880, 0x000003c4,
+ 0x02020200, 0x01000e0e, 0x3a020001, 0x00000e0e, 0x00000007,
+ 0x206a012e, 0x037216a0, 0x6d4000e2, 0x7ec84d2e, 0x3139605e,
+ 0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00001130,
+ 0x00000016, 0xd00a8a0d, 0xefbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
+ 0x00000444, 0x00000000, 0x00000000, 0x1883800a, 0x00000210,
+ 0x0004a000, 0x7999aa0e, 0x00000000
+};
+#endif
+
+static const uint32_t ar9287_1_1_vals_2g20[] = {
+ 0x00000160, 0x0000018c, 0x00003e38, 0x00000000, 0x08400b00,
+ 0x12e0002b, 0x08f04810, 0x0000320a, 0x00003440, 0x00000300,
+ 0x02020200, 0x01000e0e, 0x3a020001, 0x00000e0e, 0x00000007,
+ 0x206a012e, 0x037216a0, 0x6c4000e2, 0x7ec84d2e, 0x31395d5e,
+ 0x00058d20, 0x0001ce00, 0x5ac640d0, 0x06903881, 0x00000898,
+ 0x0000000b, 0xd00a8a0d, 0xefbc1010, 0x00000010, 0x00000010,
+ 0x00000210, 0x000003ce, 0x0000001c, 0x00000c00, 0x05eea6d4,
+ 0x00000444, 0x00000000, 0x00000000, 0x1883800a, 0x00000108,
+ 0x0004a000, 0x7999aa0e, 0x00000000
+};
+
+static const uint16_t ar9287_1_1_cm_regs[] = {
+ P(0x0000c), P(0x00030), P(0x00034), P(0x00040), P(0x00044),
+ P(0x00048), P(0x0004c), P(0x00050), P(0x00054), P(0x00800),
+ P(0x00804), P(0x00808), P(0x0080c), P(0x00810), P(0x00814),
+ P(0x00818), P(0x0081c), P(0x00820), P(0x00824), P(0x01040),
+ P(0x01044), P(0x01048), P(0x0104c), P(0x01050), P(0x01054),
+ P(0x01058), P(0x0105c), P(0x01060), P(0x01064), P(0x01230),
+ P(0x01270), P(0x01038), P(0x01078), P(0x010b8), P(0x010f8),
+ P(0x01138), P(0x01178), P(0x011b8), P(0x011f8), P(0x01238),
+ P(0x01278), P(0x012b8), P(0x012f8), P(0x01338), P(0x01378),
+ P(0x013b8), P(0x013f8), P(0x01438), P(0x01478), P(0x014b8),
+ P(0x014f8), P(0x01538), P(0x01578), P(0x015b8), P(0x015f8),
+ P(0x01638), P(0x01678), P(0x016b8), P(0x016f8), P(0x01738),
+ P(0x01778), P(0x017b8), P(0x017f8), P(0x0103c), P(0x0107c),
+ P(0x010bc), P(0x010fc), P(0x0113c), P(0x0117c), P(0x011bc),
+ P(0x011fc), P(0x0123c), P(0x0127c), P(0x012bc), P(0x012fc),
+ P(0x0133c), P(0x0137c), P(0x013bc), P(0x013fc), P(0x0143c),
+ P(0x0147c), P(0x04030), P(0x0403c), P(0x04024), P(0x04060),
+ P(0x04064), P(0x07010), P(0x07020), P(0x07034), P(0x07038),
+ P(0x08004), P(0x08008), P(0x0800c), P(0x08018), P(0x08020),
+ P(0x08038), P(0x0803c), P(0x08048), P(0x08054), P(0x08058),
+ P(0x0805c), P(0x08060), P(0x08064), P(0x08070), P(0x080c0),
+ P(0x080c4), P(0x080c8), P(0x080cc), P(0x080d0), P(0x080d4),
+ P(0x080d8), P(0x080e0), P(0x080e4), P(0x080e8), P(0x080ec),
+ P(0x080f0), P(0x080f4), P(0x080f8), P(0x080fc), P(0x08100),
+ P(0x08104), P(0x08108), P(0x0810c), P(0x08110), P(0x08118),
+ P(0x0811c), P(0x08124), P(0x08128), P(0x0812c), P(0x08130),
+ P(0x08134), P(0x08138), P(0x0813c), P(0x08144), P(0x08168),
+ P(0x0816c), P(0x08170), P(0x08174), P(0x08178), P(0x0817c),
+ P(0x081c0), P(0x081c4), P(0x081d4), P(0x081ec), P(0x081f0),
+ P(0x081f4), P(0x081f8), P(0x081fc), P(0x08200), P(0x08204),
+ P(0x08208), P(0x0820c), P(0x08210), P(0x08214), P(0x08218),
+ P(0x0821c), P(0x08220), P(0x08224), P(0x08228), P(0x0822c),
+ P(0x08230), P(0x08234), P(0x08238), P(0x0823c), P(0x08240),
+ P(0x08244), P(0x08248), P(0x0824c), P(0x08250), P(0x08254),
+ P(0x08258), P(0x0825c), P(0x08260), P(0x08264), P(0x08270),
+ P(0x08274), P(0x08278), P(0x0827c), P(0x08284), P(0x08288),
+ P(0x0828c), P(0x08294), P(0x08298), P(0x0829c), P(0x08300),
+ P(0x08314), P(0x08328), P(0x0832c), P(0x08330), P(0x08334),
+ P(0x08338), P(0x0833c), P(0x08340), P(0x08344), P(0x08360),
+ P(0x08364), P(0x08368), P(0x08370), P(0x08374), P(0x08378),
+ P(0x0837c), P(0x08380), P(0x08384), P(0x08390), P(0x08394),
+ P(0x08398), P(0x0839c), P(0x083a0), P(0x09808), P(0x0980c),
+ P(0x09810), P(0x09814), P(0x0981c), P(0x0982c), P(0x09830),
+ P(0x0983c), P(0x0984c), P(0x0a84c), P(0x09854), P(0x09900),
+ P(0x09904), P(0x09908), P(0x0990c), P(0x09910), P(0x0991c),
+ P(0x09920), P(0x0a920), P(0x09928), P(0x0992c), P(0x09930),
+ P(0x0a930), P(0x09934), P(0x09938), P(0x0993c), P(0x09948),
+ P(0x0994c), P(0x09954), P(0x09958), P(0x09940), P(0x0c95c),
+ P(0x09970), P(0x09974), P(0x09978), P(0x0997c), P(0x099a0),
+ P(0x099a4), P(0x099a8), P(0x099ac), P(0x099b0), P(0x099b4),
+ P(0x099c4), P(0x099c8), P(0x099cc), P(0x099d0), P(0x099dc),
+ P(0x099e0), P(0x099e4), P(0x099e8), P(0x099ec), P(0x099f0),
+ P(0x099fc), P(0x0a208), P(0x0a210), P(0x0a214), P(0x0a218),
+ P(0x0a220), P(0x0a224), P(0x0a228), P(0x0a22c), P(0x0a234),
+ P(0x0a238), P(0x0a23c), P(0x0a240), P(0x0a244), P(0x0a248),
+ P(0x0a24c), P(0x0a254), P(0x0a258), P(0x0a25c), P(0x0a260),
+ P(0x0a264), P(0x0b264), P(0x0a268), P(0x0a26c), P(0x0b26c),
+ P(0x0d270), P(0x0a278), P(0x0a27c), P(0x0d35c), P(0x0d360),
+ P(0x0d364), P(0x0d368), P(0x0d36c), P(0x0d370), P(0x0d374),
+ P(0x0d378), P(0x0d37c), P(0x0d380), P(0x0d384), P(0x0a388),
+ P(0x0a38c), P(0x0a390), P(0x0a394), P(0x0a398), P(0x0b398),
+ P(0x0a39c), P(0x0a3c8), P(0x0a3cc), P(0x0a3d0), P(0x0a3d4),
+ P(0x0a3dc), P(0x0a3e0), P(0x0a3e4), P(0x0a3e8), P(0x0a3ec),
+ P(0x0a3f0), P(0x0a3f4), P(0x0b3f4), P(0x0a7d8), P(0x07800),
+ P(0x07804), P(0x07808), P(0x0780c), P(0x07810), P(0x07814),
+ P(0x07818), P(0x0781c), P(0x07820), P(0x07824), P(0x07828),
+ P(0x0782c), P(0x07830), P(0x07834), P(0x07838), P(0x0783c),
+ P(0x07840), P(0x07844), P(0x07848), P(0x07850), P(0x07854),
+ P(0x07858), P(0x0785c), P(0x07860), P(0x07864), P(0x07868),
+ P(0x0786c), P(0x07870), P(0x07874), P(0x07878), P(0x0787c),
+ P(0x07880), P(0x07884), P(0x07888), P(0x0788c), P(0x07890),
+ P(0x07894), P(0x07898), P(0x0789c), P(0x078a0), P(0x078a4),
+ P(0x078a8), P(0x078ac), P(0x078b0), P(0x078b4), P(0x078b8)
+};
+
+static const uint32_t ar9287_1_1_cm_vals[] = {
+ 0x00000000, 0x00020015, 0x00000005, 0x00000000, 0x00000008,
+ 0x00000008, 0x00000010, 0x00000000, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f,
+ 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x002ffc0f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000002, 0x00000002, 0x0000001f, 0x00000000,
+ 0x00000000, 0x00000033, 0x00000000, 0x00000002, 0x000004c2,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000700, 0x00000000,
+ 0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000,
+ 0x000fc78f, 0x0000000f, 0x00000000, 0x00000000, 0x2a80001a,
+ 0x05dc01e0, 0x1f402710, 0x01f40000, 0x00001e00, 0x00000000,
+ 0x00400000, 0xffffffff, 0x0000ffff, 0x003f3f3f, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00020000, 0x00020000,
+ 0x00000001, 0x00000052, 0x00000000, 0x00000168, 0x000100aa,
+ 0x00003210, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000,
+ 0x00000000, 0x18487320, 0xfaa4fa50, 0x00000100, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00100000,
+ 0x0010f400, 0x00000100, 0x0001e800, 0x00000000, 0x00000000,
+ 0x00000000, 0x400000ff, 0x00080922, 0x88a00010, 0x00000000,
+ 0x40000000, 0x003e4180, 0x00000000, 0x0000002c, 0x0000002c,
+ 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000040,
+ 0x00000000, 0x00000000, 0x00000007, 0x00000302, 0x00000e00,
+ 0x00ff0000, 0x00000000, 0x000107ff, 0x01c81043, 0xffffffff,
+ 0xffffffff, 0x00000000, 0x00000000, 0x000000ff, 0x00000000,
+ 0x00000000, 0xffffffff, 0xffffffff, 0x0fffffff, 0x0fffffff,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xafe68e30,
+ 0xfd14e000, 0x9c0a9f6b, 0x00000000, 0x0000a000, 0x00000000,
+ 0x00200400, 0x0040233c, 0x0040233c, 0x00000044, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x10002310, 0x10000fff,
+ 0x04900000, 0x04900000, 0x00000001, 0x00000004, 0x00000000,
+ 0x00000000, 0x1e1f2022, 0x0a0b0c0d, 0x00000000, 0x9280c00a,
+ 0x00020028, 0x5f3ca3de, 0x0108ecff, 0x14750604, 0x004b6a8e,
+ 0x990bb514, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000001, 0x201fff00, 0x0c6f0000, 0x03051000, 0x00000820,
+ 0x06336f77, 0x6af6532f, 0x08f186c8, 0x00046384, 0x00000000,
+ 0x00000000, 0xaaaaaaaa, 0x3c466478, 0x0cc80caa, 0x00000000,
+ 0x00001042, 0x803e4788, 0x4080a333, 0x40206c10, 0x009c4060,
+ 0x01834061, 0x00000400, 0x000003b5, 0x233f7180, 0x20202020,
+ 0x20202020, 0x13c889af, 0x38490a20, 0x00000000, 0xfffffffc,
+ 0x00000000, 0x00000000, 0x0cdbd380, 0x0f0f0f01, 0xdfa91f01,
+ 0x00418a11, 0x00418a11, 0x00000000, 0x0e79e5c6, 0x0e79e5c6,
+ 0x00820820, 0x1ce739ce, 0x050701ce, 0x07ffffef, 0x0fffffe7,
+ 0x17ffffe5, 0x1fffffe4, 0x37ffffe3, 0x3fffffe3, 0x57ffffe3,
+ 0x5fffffe2, 0x7fffffe2, 0x7f3c7bba, 0xf3307ff0, 0x0c000000,
+ 0x20202020, 0x20202020, 0x1ce739ce, 0x000001ce, 0x000001ce,
+ 0x00000001, 0x00000246, 0x20202020, 0x20202020, 0x20202020,
+ 0x1ce739ce, 0x000001ce, 0x00000000, 0x18c43433, 0x00f70081,
+ 0x01036a1e, 0x00000000, 0x00000000, 0x000003f1, 0x00000800,
+ 0x6c35ffd2, 0x6db6c000, 0x6db6cb30, 0x6db6cb6c, 0x0501e200,
+ 0x0094128d, 0x976ee392, 0xf75ff6fc, 0x00040000, 0xdb003012,
+ 0x04924914, 0x21084210, 0x00140000, 0x0e4548d8, 0x54214514,
+ 0x02025830, 0x71c0d388, 0x934934a8, 0x00000000, 0x00000800,
+ 0x6c35ffd2, 0x6db6c000, 0x6db6cb30, 0x6db6cb6c, 0x0501e200,
+ 0x0094128d, 0x976ee392, 0xf75ff6fc, 0x00040000, 0xdb003012,
+ 0x04924914, 0x21084210, 0x001b6db0, 0x00376b63, 0x06db6db6,
+ 0x006d8000, 0x48100000, 0x00000000, 0x08000000, 0x0007ffd8,
+ 0x0007ffd8, 0x001c0020, 0x00060aeb, 0x40008080, 0x2a850160
+};
+
+static const struct athn_ini ar9287_1_1_ini = {
+ nitems(ar9287_1_1_regs),
+ ar9287_1_1_regs,
+ NULL, /* 2GHz only. */
+#ifndef IEEE80211_NO_HT
+ NULL, /* 2GHz only. */
+ ar9287_1_1_vals_2g40,
+#endif
+ ar9287_1_1_vals_2g20,
+ nitems(ar9287_1_1_cm_regs),
+ ar9287_1_1_cm_regs,
+ ar9287_1_1_cm_vals
+};
+
+/*
+ * AR9287 1.0 Tx gains.
+ */
+static const uint16_t ar9287_1_0_tx_gain_regs[] = {
+ P(0x0a300), P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310),
+ P(0x0a314), P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324),
+ P(0x0a328), P(0x0a32c), P(0x0a330), P(0x0a334), P(0x0a338),
+ P(0x0a33c), P(0x0a340), P(0x0a344), P(0x0a348), P(0x0a34c),
+ P(0x0a350), P(0x0a354), P(0x0a780), P(0x0a784), P(0x0a788),
+ P(0x0a78c), P(0x0a790), P(0x0a794), P(0x0a798), P(0x0a79c),
+ P(0x0a7a0), P(0x0a7a4), P(0x0a7a8), P(0x0a7ac), P(0x0a7b0),
+ P(0x0a7b4), P(0x0a7b8), P(0x0a7bc), P(0x0a7c0), P(0x0a7c4),
+ P(0x0a7c8), P(0x0a7cc), P(0x0a7d0), P(0x0a7d4), P(0x0a274)
+};
+
+static const uint32_t ar9287_1_0_tx_gain_vals_2g[] = {
+ 0x00000000, 0x00004002, 0x00008004, 0x0000c00a, 0x0001000c,
+ 0x0001420b, 0x0001824a, 0x0001c44a, 0x0002064a, 0x0002484a,
+ 0x00028a4a, 0x0002cc4a, 0x00030e4a, 0x00034e8a, 0x00038e8c,
+ 0x0003cecc, 0x00040ed4, 0x00044edc, 0x00048ede, 0x0004cf1e,
+ 0x00050f5e, 0x00054f9e, 0x00000060, 0x00004062, 0x00008064,
+ 0x0000c0a4, 0x000100b0, 0x000140b2, 0x000180b4, 0x0001c0f4,
+ 0x00020134, 0x000240fe, 0x0002813e, 0x0002c17e, 0x000301be,
+ 0x000341fe, 0x000341fe, 0x000341fe, 0x000341fe, 0x000341fe,
+ 0x000341fe, 0x000341fe, 0x000341fe, 0x000341fe, 0x0a1aa000
+};
+
+static const struct athn_gain ar9287_1_0_tx_gain = {
+ nitems(ar9287_1_0_tx_gain_regs),
+ ar9287_1_0_tx_gain_regs,
+ NULL, /* 2GHz only. */
+ ar9287_1_0_tx_gain_vals_2g
+};
+
+/*
+ * AR9287 1.1 Tx gains.
+ */
+static const uint16_t ar9287_1_1_tx_gain_regs[] = {
+ P(0x0a300), P(0x0a304), P(0x0a308), P(0x0a30c), P(0x0a310),
+ P(0x0a314), P(0x0a318), P(0x0a31c), P(0x0a320), P(0x0a324),
+ P(0x0a328), P(0x0a32c), P(0x0a330), P(0x0a334), P(0x0a338),
+ P(0x0a33c), P(0x0a340), P(0x0a344), P(0x0a348), P(0x0a34c),
+ P(0x0a350), P(0x0a354), P(0x0a780), P(0x0a784), P(0x0a788),
+ P(0x0a78c), P(0x0a790), P(0x0a794), P(0x0a798), P(0x0a79c),
+ P(0x0a7a0), P(0x0a7a4), P(0x0a7a8), P(0x0a7ac), P(0x0a7b0),
+ P(0x0a7b4), P(0x0a7b8), P(0x0a7bc), P(0x0a7c0), P(0x0a7c4),
+ P(0x0a7c8), P(0x0a7cc), P(0x0a7d0), P(0x0a7d4), P(0x0a274)
+};
+
+static const uint32_t ar9287_1_1_tx_gain_vals_2g[] = {
+ 0x00000000, 0x00004002, 0x00008004, 0x0000c00a, 0x0001000c,
+ 0x0001420b, 0x0001824a, 0x0001c44a, 0x0002064a, 0x0002484a,
+ 0x00028a4a, 0x0002cc4a, 0x00030e4a, 0x00034e8a, 0x00038e8c,
+ 0x0003cecc, 0x00040ed4, 0x00044edc, 0x00048ede, 0x0004cf1e,
+ 0x00050f5e, 0x00054f9e, 0x00000062, 0x00004064, 0x000080a4,
+ 0x0000c0aa, 0x000100ac, 0x000140b4, 0x000180f4, 0x0001c134,
+ 0x00020174, 0x0002417c, 0x0002817e, 0x0002c1be, 0x000301fe,
+ 0x000301fe, 0x000301fe, 0x000301fe, 0x000301fe, 0x000301fe,
+ 0x000301fe, 0x000301fe, 0x000301fe, 0x000301fe, 0x0a1aa000
+};
+
+static const struct athn_gain ar9287_1_1_tx_gain = {
+ nitems(ar9287_1_1_tx_gain_regs),
+ ar9287_1_1_tx_gain_regs,
+ NULL, /* 2GHz only. */
+ ar9287_1_1_tx_gain_vals_2g
+};
+
+/*
+ * AR9287 1.0 Rx gains.
+ */
+static const uint16_t ar9287_1_0_rx_gain_regs[] = {
+ P(0x09a00), P(0x09a04), P(0x09a08), P(0x09a0c), P(0x09a10),
+ P(0x09a14), P(0x09a18), P(0x09a1c), P(0x09a20), P(0x09a24),
+ P(0x09a28), P(0x09a2c), P(0x09a30), P(0x09a34), P(0x09a38),
+ P(0x09a3c), P(0x09a40), P(0x09a44), P(0x09a48), P(0x09a4c),
+ P(0x09a50), P(0x09a54), P(0x09a58), P(0x09a5c), P(0x09a60),
+ P(0x09a64), P(0x09a68), P(0x09a6c), P(0x09a70), P(0x09a74),
+ P(0x09a78), P(0x09a7c), P(0x09a80), P(0x09a84), P(0x09a88),
+ P(0x09a8c), P(0x09a90), P(0x09a94), P(0x09a98), P(0x09a9c),
+ P(0x09aa0), P(0x09aa4), P(0x09aa8), P(0x09aac), P(0x09ab0),
+ P(0x09ab4), P(0x09ab8), P(0x09abc), P(0x09ac0), P(0x09ac4),
+ P(0x09ac8), P(0x09acc), P(0x09ad0), P(0x09ad4), P(0x09ad8),
+ P(0x09adc), P(0x09ae0), P(0x09ae4), P(0x09ae8), P(0x09aec),
+ P(0x09af0), P(0x09af4), P(0x09af8), P(0x09afc), P(0x09b00),
+ P(0x09b04), P(0x09b08), P(0x09b0c), P(0x09b10), P(0x09b14),
+ P(0x09b18), P(0x09b1c), P(0x09b20), P(0x09b24), P(0x09b28),
+ P(0x09b2c), P(0x09b30), P(0x09b34), P(0x09b38), P(0x09b3c),
+ P(0x09b40), P(0x09b44), P(0x09b48), P(0x09b4c), P(0x09b50),
+ P(0x09b54), P(0x09b58), P(0x09b5c), P(0x09b60), P(0x09b64),
+ P(0x09b68), P(0x09b6c), P(0x09b70), P(0x09b74), P(0x09b78),
+ P(0x09b7c), P(0x09b80), P(0x09b84), P(0x09b88), P(0x09b8c),
+ P(0x09b90), P(0x09b94), P(0x09b98), P(0x09b9c), P(0x09ba0),
+ P(0x09ba4), P(0x09ba8), P(0x09bac), P(0x09bb0), P(0x09bb4),
+ P(0x09bb8), P(0x09bbc), P(0x09bc0), P(0x09bc4), P(0x09bc8),
+ P(0x09bcc), P(0x09bd0), P(0x09bd4), P(0x09bd8), P(0x09bdc),
+ P(0x09be0), P(0x09be4), P(0x09be8), P(0x09bec), P(0x09bf0),
+ P(0x09bf4), P(0x09bf8), P(0x09bfc), P(0x0aa00), P(0x0aa04),
+ P(0x0aa08), P(0x0aa0c), P(0x0aa10), P(0x0aa14), P(0x0aa18),
+ P(0x0aa1c), P(0x0aa20), P(0x0aa24), P(0x0aa28), P(0x0aa2c),
+ P(0x0aa30), P(0x0aa34), P(0x0aa38), P(0x0aa3c), P(0x0aa40),
+ P(0x0aa44), P(0x0aa48), P(0x0aa4c), P(0x0aa50), P(0x0aa54),
+ P(0x0aa58), P(0x0aa5c), P(0x0aa60), P(0x0aa64), P(0x0aa68),
+ P(0x0aa6c), P(0x0aa70), P(0x0aa74), P(0x0aa78), P(0x0aa7c),
+ P(0x0aa80), P(0x0aa84), P(0x0aa88), P(0x0aa8c), P(0x0aa90),
+ P(0x0aa94), P(0x0aa98), P(0x0aa9c), P(0x0aaa0), P(0x0aaa4),
+ P(0x0aaa8), P(0x0aaac), P(0x0aab0), P(0x0aab4), P(0x0aab8),
+ P(0x0aabc), P(0x0aac0), P(0x0aac4), P(0x0aac8), P(0x0aacc),
+ P(0x0aad0), P(0x0aad4), P(0x0aad8), P(0x0aadc), P(0x0aae0),
+ P(0x0aae4), P(0x0aae8), P(0x0aaec), P(0x0aaf0), P(0x0aaf4),
+ P(0x0aaf8), P(0x0aafc), P(0x0ab00), P(0x0ab04), P(0x0ab08),
+ P(0x0ab0c), P(0x0ab10), P(0x0ab14), P(0x0ab18), P(0x0ab1c),
+ P(0x0ab20), P(0x0ab24), P(0x0ab28), P(0x0ab2c), P(0x0ab30),
+ P(0x0ab34), P(0x0ab38), P(0x0ab3c), P(0x0ab40), P(0x0ab44),
+ P(0x0ab48), P(0x0ab4c), P(0x0ab50), P(0x0ab54), P(0x0ab58),
+ P(0x0ab5c), P(0x0ab60), P(0x0ab64), P(0x0ab68), P(0x0ab6c),
+ P(0x0ab70), P(0x0ab74), P(0x0ab78), P(0x0ab7c), P(0x0ab80),
+ P(0x0ab84), P(0x0ab88), P(0x0ab8c), P(0x0ab90), P(0x0ab94),
+ P(0x0ab98), P(0x0ab9c), P(0x0aba0), P(0x0aba4), P(0x0aba8),
+ P(0x0abac), P(0x0abb0), P(0x0abb4), P(0x0abb8), P(0x0abbc),
+ P(0x0abc0), P(0x0abc4), P(0x0abc8), P(0x0abcc), P(0x0abd0),
+ P(0x0abd4), P(0x0abd8), P(0x0abdc), P(0x0abe0), P(0x0abe4),
+ P(0x0abe8), P(0x0abec), P(0x0abf0), P(0x0abf4), P(0x0abf8),
+ P(0x0abfc), P(0x09848), P(0x0a848)
+};
+
+static const uint32_t ar9287_1_0_rx_gain_vals_2g[] = {
+ 0x0000a120, 0x0000a124, 0x0000a128, 0x0000a12c, 0x0000a130,
+ 0x0000a194, 0x0000a198, 0x0000a20c, 0x0000a210, 0x0000a284,
+ 0x0000a288, 0x0000a28c, 0x0000a290, 0x0000a294, 0x0000a2a0,
+ 0x0000a2a4, 0x0000a2a8, 0x0000a2ac, 0x0000a2b0, 0x0000a2b4,
+ 0x0000a2b8, 0x0000a2c4, 0x0000a708, 0x0000a70c, 0x0000a710,
+ 0x0000ab04, 0x0000ab08, 0x0000ab0c, 0x0000ab10, 0x0000ab14,
+ 0x0000ab18, 0x0000ab8c, 0x0000ab90, 0x0000ab94, 0x0000ab98,
+ 0x0000aba4, 0x0000aba8, 0x0000cb04, 0x0000cb08, 0x0000cb0c,
+ 0x0000cb10, 0x0000cb14, 0x0000cb18, 0x0000cb8c, 0x0000cb90,
+ 0x0000cf18, 0x0000cf24, 0x0000cf28, 0x0000d314, 0x0000d318,
+ 0x0000d38c, 0x0000d390, 0x0000d394, 0x0000d398, 0x0000d3a4,
+ 0x0000d3a8, 0x0000d3ac, 0x0000d3b0, 0x0000f380, 0x0000f384,
+ 0x0000f388, 0x0000f710, 0x0000f714, 0x0000f718, 0x0000fb10,
+ 0x0000fb14, 0x0000fb18, 0x0000fb8c, 0x0000fb90, 0x0000fb94,
+ 0x0000ff8c, 0x0000ff90, 0x0000ff94, 0x0000ffa0, 0x0000ffa4,
+ 0x0000ffa8, 0x0000ffac, 0x0000ffb0, 0x0000ffb4, 0x0000ffa1,
+ 0x0000ffa5, 0x0000ffa9, 0x0000ffad, 0x0000ffb1, 0x0000ffb5,
+ 0x0000ffb9, 0x0000ffc5, 0x0000ffc9, 0x0000ffcd, 0x0000ffd1,
+ 0x0000ffd5, 0x0000ffc2, 0x0000ffc6, 0x0000ffca, 0x0000ffce,
+ 0x0000ffd2, 0x0000ffd6, 0x0000ffda, 0x0000ffc7, 0x0000ffcb,
+ 0x0000ffcf, 0x0000ffd3, 0x0000ffd7, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000a120, 0x0000a124,
+ 0x0000a128, 0x0000a12c, 0x0000a130, 0x0000a194, 0x0000a198,
+ 0x0000a20c, 0x0000a210, 0x0000a284, 0x0000a288, 0x0000a28c,
+ 0x0000a290, 0x0000a294, 0x0000a2a0, 0x0000a2a4, 0x0000a2a8,
+ 0x0000a2ac, 0x0000a2b0, 0x0000a2b4, 0x0000a2b8, 0x0000a2c4,
+ 0x0000a708, 0x0000a70c, 0x0000a710, 0x0000ab04, 0x0000ab08,
+ 0x0000ab0c, 0x0000ab10, 0x0000ab14, 0x0000ab18, 0x0000ab8c,
+ 0x0000ab90, 0x0000ab94, 0x0000ab98, 0x0000aba4, 0x0000aba8,
+ 0x0000cb04, 0x0000cb08, 0x0000cb0c, 0x0000cb10, 0x0000cb14,
+ 0x0000cb18, 0x0000cb8c, 0x0000cb90, 0x0000cf18, 0x0000cf24,
+ 0x0000cf28, 0x0000d314, 0x0000d318, 0x0000d38c, 0x0000d390,
+ 0x0000d394, 0x0000d398, 0x0000d3a4, 0x0000d3a8, 0x0000d3ac,
+ 0x0000d3b0, 0x0000f380, 0x0000f384, 0x0000f388, 0x0000f710,
+ 0x0000f714, 0x0000f718, 0x0000fb10, 0x0000fb14, 0x0000fb18,
+ 0x0000fb8c, 0x0000fb90, 0x0000fb94, 0x0000ff8c, 0x0000ff90,
+ 0x0000ff94, 0x0000ffa0, 0x0000ffa4, 0x0000ffa8, 0x0000ffac,
+ 0x0000ffb0, 0x0000ffb4, 0x0000ffa1, 0x0000ffa5, 0x0000ffa9,
+ 0x0000ffad, 0x0000ffb1, 0x0000ffb5, 0x0000ffb9, 0x0000ffc5,
+ 0x0000ffc9, 0x0000ffcd, 0x0000ffd1, 0x0000ffd5, 0x0000ffc2,
+ 0x0000ffc6, 0x0000ffca, 0x0000ffce, 0x0000ffd2, 0x0000ffd6,
+ 0x0000ffda, 0x0000ffc7, 0x0000ffcb, 0x0000ffcf, 0x0000ffd3,
+ 0x0000ffd7, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x00001067, 0x00001067
+};
+
+static const struct athn_gain ar9287_1_0_rx_gain = {
+ nitems(ar9287_1_0_rx_gain_regs),
+ ar9287_1_0_rx_gain_regs,
+ NULL, /* 2GHz only. */
+ ar9287_1_0_rx_gain_vals_2g
+};
+
+/*
+ * AR9287 1.1 Rx gains.
+ */
+static const uint16_t ar9287_1_1_rx_gain_regs[] = {
+ P(0x09a00), P(0x09a04), P(0x09a08), P(0x09a0c), P(0x09a10),
+ P(0x09a14), P(0x09a18), P(0x09a1c), P(0x09a20), P(0x09a24),
+ P(0x09a28), P(0x09a2c), P(0x09a30), P(0x09a34), P(0x09a38),
+ P(0x09a3c), P(0x09a40), P(0x09a44), P(0x09a48), P(0x09a4c),
+ P(0x09a50), P(0x09a54), P(0x09a58), P(0x09a5c), P(0x09a60),
+ P(0x09a64), P(0x09a68), P(0x09a6c), P(0x09a70), P(0x09a74),
+ P(0x09a78), P(0x09a7c), P(0x09a80), P(0x09a84), P(0x09a88),
+ P(0x09a8c), P(0x09a90), P(0x09a94), P(0x09a98), P(0x09a9c),
+ P(0x09aa0), P(0x09aa4), P(0x09aa8), P(0x09aac), P(0x09ab0),
+ P(0x09ab4), P(0x09ab8), P(0x09abc), P(0x09ac0), P(0x09ac4),
+ P(0x09ac8), P(0x09acc), P(0x09ad0), P(0x09ad4), P(0x09ad8),
+ P(0x09adc), P(0x09ae0), P(0x09ae4), P(0x09ae8), P(0x09aec),
+ P(0x09af0), P(0x09af4), P(0x09af8), P(0x09afc), P(0x09b00),
+ P(0x09b04), P(0x09b08), P(0x09b0c), P(0x09b10), P(0x09b14),
+ P(0x09b18), P(0x09b1c), P(0x09b20), P(0x09b24), P(0x09b28),
+ P(0x09b2c), P(0x09b30), P(0x09b34), P(0x09b38), P(0x09b3c),
+ P(0x09b40), P(0x09b44), P(0x09b48), P(0x09b4c), P(0x09b50),
+ P(0x09b54), P(0x09b58), P(0x09b5c), P(0x09b60), P(0x09b64),
+ P(0x09b68), P(0x09b6c), P(0x09b70), P(0x09b74), P(0x09b78),
+ P(0x09b7c), P(0x09b80), P(0x09b84), P(0x09b88), P(0x09b8c),
+ P(0x09b90), P(0x09b94), P(0x09b98), P(0x09b9c), P(0x09ba0),
+ P(0x09ba4), P(0x09ba8), P(0x09bac), P(0x09bb0), P(0x09bb4),
+ P(0x09bb8), P(0x09bbc), P(0x09bc0), P(0x09bc4), P(0x09bc8),
+ P(0x09bcc), P(0x09bd0), P(0x09bd4), P(0x09bd8), P(0x09bdc),
+ P(0x09be0), P(0x09be4), P(0x09be8), P(0x09bec), P(0x09bf0),
+ P(0x09bf4), P(0x09bf8), P(0x09bfc), P(0x0aa00), P(0x0aa04),
+ P(0x0aa08), P(0x0aa0c), P(0x0aa10), P(0x0aa14), P(0x0aa18),
+ P(0x0aa1c), P(0x0aa20), P(0x0aa24), P(0x0aa28), P(0x0aa2c),
+ P(0x0aa30), P(0x0aa34), P(0x0aa38), P(0x0aa3c), P(0x0aa40),
+ P(0x0aa44), P(0x0aa48), P(0x0aa4c), P(0x0aa50), P(0x0aa54),
+ P(0x0aa58), P(0x0aa5c), P(0x0aa60), P(0x0aa64), P(0x0aa68),
+ P(0x0aa6c), P(0x0aa70), P(0x0aa74), P(0x0aa78), P(0x0aa7c),
+ P(0x0aa80), P(0x0aa84), P(0x0aa88), P(0x0aa8c), P(0x0aa90),
+ P(0x0aa94), P(0x0aa98), P(0x0aa9c), P(0x0aaa0), P(0x0aaa4),
+ P(0x0aaa8), P(0x0aaac), P(0x0aab0), P(0x0aab4), P(0x0aab8),
+ P(0x0aabc), P(0x0aac0), P(0x0aac4), P(0x0aac8), P(0x0aacc),
+ P(0x0aad0), P(0x0aad4), P(0x0aad8), P(0x0aadc), P(0x0aae0),
+ P(0x0aae4), P(0x0aae8), P(0x0aaec), P(0x0aaf0), P(0x0aaf4),
+ P(0x0aaf8), P(0x0aafc), P(0x0ab00), P(0x0ab04), P(0x0ab08),
+ P(0x0ab0c), P(0x0ab10), P(0x0ab14), P(0x0ab18), P(0x0ab1c),
+ P(0x0ab20), P(0x0ab24), P(0x0ab28), P(0x0ab2c), P(0x0ab30),
+ P(0x0ab34), P(0x0ab38), P(0x0ab3c), P(0x0ab40), P(0x0ab44),
+ P(0x0ab48), P(0x0ab4c), P(0x0ab50), P(0x0ab54), P(0x0ab58),
+ P(0x0ab5c), P(0x0ab60), P(0x0ab64), P(0x0ab68), P(0x0ab6c),
+ P(0x0ab70), P(0x0ab74), P(0x0ab78), P(0x0ab7c), P(0x0ab80),
+ P(0x0ab84), P(0x0ab88), P(0x0ab8c), P(0x0ab90), P(0x0ab94),
+ P(0x0ab98), P(0x0ab9c), P(0x0aba0), P(0x0aba4), P(0x0aba8),
+ P(0x0abac), P(0x0abb0), P(0x0abb4), P(0x0abb8), P(0x0abbc),
+ P(0x0abc0), P(0x0abc4), P(0x0abc8), P(0x0abcc), P(0x0abd0),
+ P(0x0abd4), P(0x0abd8), P(0x0abdc), P(0x0abe0), P(0x0abe4),
+ P(0x0abe8), P(0x0abec), P(0x0abf0), P(0x0abf4), P(0x0abf8),
+ P(0x0abfc), P(0x09848), P(0x0a848)
+};
+
+static const uint32_t ar9287_1_1_rx_gain_vals_2g[] = {
+ 0x0000a120, 0x0000a124, 0x0000a128, 0x0000a12c, 0x0000a130,
+ 0x0000a194, 0x0000a198, 0x0000a20c, 0x0000a210, 0x0000a284,
+ 0x0000a288, 0x0000a28c, 0x0000a290, 0x0000a294, 0x0000a2a0,
+ 0x0000a2a4, 0x0000a2a8, 0x0000a2ac, 0x0000a2b0, 0x0000a2b4,
+ 0x0000a2b8, 0x0000a2c4, 0x0000a708, 0x0000a70c, 0x0000a710,
+ 0x0000ab04, 0x0000ab08, 0x0000ab0c, 0x0000ab10, 0x0000ab14,
+ 0x0000ab18, 0x0000ab8c, 0x0000ab90, 0x0000ab94, 0x0000ab98,
+ 0x0000aba4, 0x0000aba8, 0x0000cb04, 0x0000cb08, 0x0000cb0c,
+ 0x0000cb10, 0x0000cb14, 0x0000cb18, 0x0000cb8c, 0x0000cb90,
+ 0x0000cf18, 0x0000cf24, 0x0000cf28, 0x0000d314, 0x0000d318,
+ 0x0000d38c, 0x0000d390, 0x0000d394, 0x0000d398, 0x0000d3a4,
+ 0x0000d3a8, 0x0000d3ac, 0x0000d3b0, 0x0000f380, 0x0000f384,
+ 0x0000f388, 0x0000f710, 0x0000f714, 0x0000f718, 0x0000fb10,
+ 0x0000fb14, 0x0000fb18, 0x0000fb8c, 0x0000fb90, 0x0000fb94,
+ 0x0000ff8c, 0x0000ff90, 0x0000ff94, 0x0000ffa0, 0x0000ffa4,
+ 0x0000ffa8, 0x0000ffac, 0x0000ffb0, 0x0000ffb4, 0x0000ffa1,
+ 0x0000ffa5, 0x0000ffa9, 0x0000ffad, 0x0000ffb1, 0x0000ffb5,
+ 0x0000ffb9, 0x0000ffc5, 0x0000ffc9, 0x0000ffcd, 0x0000ffd1,
+ 0x0000ffd5, 0x0000ffc2, 0x0000ffc6, 0x0000ffca, 0x0000ffce,
+ 0x0000ffd2, 0x0000ffd6, 0x0000ffda, 0x0000ffc7, 0x0000ffcb,
+ 0x0000ffcf, 0x0000ffd3, 0x0000ffd7, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000a120, 0x0000a124,
+ 0x0000a128, 0x0000a12c, 0x0000a130, 0x0000a194, 0x0000a198,
+ 0x0000a20c, 0x0000a210, 0x0000a284, 0x0000a288, 0x0000a28c,
+ 0x0000a290, 0x0000a294, 0x0000a2a0, 0x0000a2a4, 0x0000a2a8,
+ 0x0000a2ac, 0x0000a2b0, 0x0000a2b4, 0x0000a2b8, 0x0000a2c4,
+ 0x0000a708, 0x0000a70c, 0x0000a710, 0x0000ab04, 0x0000ab08,
+ 0x0000ab0c, 0x0000ab10, 0x0000ab14, 0x0000ab18, 0x0000ab8c,
+ 0x0000ab90, 0x0000ab94, 0x0000ab98, 0x0000aba4, 0x0000aba8,
+ 0x0000cb04, 0x0000cb08, 0x0000cb0c, 0x0000cb10, 0x0000cb14,
+ 0x0000cb18, 0x0000cb8c, 0x0000cb90, 0x0000cf18, 0x0000cf24,
+ 0x0000cf28, 0x0000d314, 0x0000d318, 0x0000d38c, 0x0000d390,
+ 0x0000d394, 0x0000d398, 0x0000d3a4, 0x0000d3a8, 0x0000d3ac,
+ 0x0000d3b0, 0x0000f380, 0x0000f384, 0x0000f388, 0x0000f710,
+ 0x0000f714, 0x0000f718, 0x0000fb10, 0x0000fb14, 0x0000fb18,
+ 0x0000fb8c, 0x0000fb90, 0x0000fb94, 0x0000ff8c, 0x0000ff90,
+ 0x0000ff94, 0x0000ffa0, 0x0000ffa4, 0x0000ffa8, 0x0000ffac,
+ 0x0000ffb0, 0x0000ffb4, 0x0000ffa1, 0x0000ffa5, 0x0000ffa9,
+ 0x0000ffad, 0x0000ffb1, 0x0000ffb5, 0x0000ffb9, 0x0000ffc5,
+ 0x0000ffc9, 0x0000ffcd, 0x0000ffd1, 0x0000ffd5, 0x0000ffc2,
+ 0x0000ffc6, 0x0000ffca, 0x0000ffce, 0x0000ffd2, 0x0000ffd6,
+ 0x0000ffda, 0x0000ffc7, 0x0000ffcb, 0x0000ffcf, 0x0000ffd3,
+ 0x0000ffd7, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb,
+ 0x0000ffdb, 0x00001067, 0x00001067
+};
+
+static const struct athn_gain ar9287_1_1_rx_gain = {
+ nitems(ar9287_1_1_rx_gain_regs),
+ ar9287_1_1_rx_gain_regs,
+ NULL, /* 2GHz only. */
+ ar9287_1_1_rx_gain_vals_2g
+};
diff --git a/sys/dev/ic/athn.c b/sys/dev/ic/athn.c
new file mode 100644
index 00000000000..205e5d0e027
--- /dev/null
+++ b/sys/dev/ic/athn.c
@@ -0,0 +1,4663 @@
+/* $OpenBSD: athn.c,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Driver for Atheros 802.11a/g/n chipsets.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+#include <sys/timeout.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/stdint.h> /* uintptr_t */
+
+#include <machine/bus.h>
+#include <machine/endian.h>
+#include <machine/intr.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/ic/athnreg.h>
+#include <dev/ic/athnvar.h>
+
+#ifdef ATHN_DEBUG
+int athn_debug = 4;
+#endif
+
+void athn_radiotap_attach(struct athn_softc *);
+void athn_get_chanlist(struct athn_softc *);
+const char * athn_get_mac_name(struct athn_softc *);
+const char * athn_get_rf_name(struct athn_softc *);
+int athn_tx_alloc(struct athn_softc *);
+void athn_tx_free(struct athn_softc *);
+int athn_rx_alloc(struct athn_softc *);
+void athn_rx_free(struct athn_softc *);
+void athn_rx_start(struct athn_softc *);
+void athn_btcoex_init(struct athn_softc *);
+void athn_btcoex_enable(struct athn_softc *);
+void athn_btcoex_disable(struct athn_softc *);
+void athn_rfsilent_init(struct athn_softc *);
+void athn_set_rxfilter(struct athn_softc *, uint32_t);
+int athn_gpio_read(struct athn_softc *, int);
+void athn_gpio_write(struct athn_softc *, int, int);
+void athn_gpio_config_output(struct athn_softc *, int, int);
+void athn_gpio_config_input(struct athn_softc *, int);
+void athn_get_chipid(struct athn_softc *);
+int athn_reset_power_on(struct athn_softc *);
+int athn_reset(struct athn_softc *, int);
+void athn_init_pll(struct athn_softc *,
+ const struct ieee80211_channel *);
+int athn_set_power_awake(struct athn_softc *);
+void athn_set_power_sleep(struct athn_softc *);
+void athn_write_serdes(struct athn_softc *, const uint32_t [9]);
+void athn_config_pcie(struct athn_softc *);
+void athn_config_nonpcie(struct athn_softc *);
+uint8_t athn_get_rf_rev(struct athn_softc *);
+int athn_set_chan(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+int athn_switch_chan(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+void athn_get_delta_slope(uint32_t, uint32_t *, uint32_t *);
+void athn_set_delta_slope(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+void athn_set_phy(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+int athn_read_rom_word(struct athn_softc *, uint32_t, uint16_t *);
+int athn_read_rom(struct athn_softc *);
+void athn_swap_rom(struct athn_softc *);
+void athn_reset_key(struct athn_softc *, int);
+int athn_set_key(struct ieee80211com *, struct ieee80211_node *,
+ struct ieee80211_key *);
+void athn_delete_key(struct ieee80211com *, struct ieee80211_node *,
+ struct ieee80211_key *);
+void athn_iter_func(void *, struct ieee80211_node *);
+void athn_calib_to(void *);
+void athn_do_calib(struct athn_softc *);
+int athn_init_calib(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+void athn_init_chains(struct athn_softc *);
+uint8_t athn_get_vpd(uint8_t, const uint8_t *, const uint8_t *, int);
+int athn_interpolate(int, int, int, int, int);
+void athn_init_baseband(struct athn_softc *);
+void athn_init_dma(struct athn_softc *);
+void athn_inc_tx_trigger_level(struct athn_softc *);
+int athn_stop_rx_dma(struct athn_softc *);
+int athn_rx_abort(struct athn_softc *);
+int athn_tx_pending(struct athn_softc *, int);
+void athn_stop_tx_dma(struct athn_softc *, int);
+void athn_tx_reclaim(struct athn_softc *, int);
+void athn_rx_radiotap(struct athn_softc *, struct mbuf *,
+ struct ar_rx_desc *);
+void athn_rx_intr(struct athn_softc *);
+int athn_tx_process(struct athn_softc *, int);
+void athn_tx_intr(struct athn_softc *);
+int athn_txtime(struct athn_softc *, int, int, u_int);
+int athn_tx(struct athn_softc *, struct mbuf *,
+ struct ieee80211_node *);
+void athn_set_beacon_timers(struct athn_softc *);
+void athn_set_rf_mode(struct athn_softc *,
+ struct ieee80211_channel *);
+void athn_set_opmode(struct athn_softc *);
+void athn_set_bss(struct athn_softc *, struct ieee80211_node *);
+void athn_enable_interrupts(struct athn_softc *);
+void athn_disable_interrupts(struct athn_softc *);
+void athn_hw_init(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void athn_init_qos(struct athn_softc *);
+int athn_hw_reset(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+struct ieee80211_node *athn_node_alloc(struct ieee80211com *);
+void athn_newassoc(struct ieee80211com *, struct ieee80211_node *,
+ int);
+int athn_media_change(struct ifnet *);
+void athn_next_scan(void *);
+int athn_newstate(struct ieee80211com *, enum ieee80211_state,
+ int);
+void athn_updateedca(struct ieee80211com *);
+void athn_updateslot(struct ieee80211com *);
+void athn_start(struct ifnet *);
+void athn_watchdog(struct ifnet *);
+int athn_ioctl(struct ifnet *, u_long, caddr_t);
+int athn_init(struct ifnet *);
+void athn_stop(struct ifnet *, int);
+void athn_init_tx_queues(struct athn_softc *);
+void athn_calib_iq(struct athn_softc *);
+void athn_calib_adc_gain(struct athn_softc *);
+void athn_calib_adc_dc_off(struct athn_softc *);
+void athn_read_noisefloor(struct athn_softc *, int16_t *,
+ int16_t *);
+void athn_get_noisefloor(struct athn_softc *,
+ struct ieee80211_channel *);
+void athn_write_noisefloor(struct athn_softc *, int16_t *,
+ int16_t *);
+void athn_bb_load_noisefloor(struct athn_softc *);
+void athn_noisefloor_calib(struct athn_softc *);
+int32_t athn_ani_get_rssi(struct athn_softc *);
+void athn_ani_set_noise_immunity_level(struct athn_softc *, int);
+void athn_ani_ena_ofdm_weak_signal(struct athn_softc *);
+void athn_ani_dis_ofdm_weak_signal(struct athn_softc *);
+void athn_ani_set_cck_weak_signal(struct athn_softc *, int);
+void athn_ani_set_firstep_level(struct athn_softc *, int);
+void athn_ani_set_spur_immunity_level(struct athn_softc *, int);
+void athn_ani_ofdm_err_trigger(struct athn_softc *);
+void athn_ani_cck_err_trigger(struct athn_softc *);
+void athn_ani_lower_immunity(struct athn_softc *);
+void athn_ani_restart(struct athn_softc *);
+void athn_ani_monitor(struct athn_softc *);
+
+struct cfdriver athn_cd = {
+ NULL, "athn", DV_IFNET
+};
+
+int
+athn_attach(struct athn_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &ic->ic_if;
+ struct ar_base_eep_header *base;
+ uint8_t eep_ver, kc_entries_exp;
+ int i, error;
+
+ if ((error = athn_reset_power_on(sc)) != 0) {
+ printf(": could not reset chip\n");
+ return (error);
+ }
+
+ if (AR_SREV_5416(sc) || AR_SREV_9160(sc))
+ ar5416_attach(sc);
+ else if (AR_SREV_9280(sc))
+ ar9280_attach(sc);
+ else if (AR_SREV_9285(sc))
+ ar9285_attach(sc);
+ else if (AR_SREV_9287(sc))
+ ar9287_attach(sc);
+
+ if ((error = athn_set_power_awake(sc)) != 0) {
+ printf(": could not wakeup chip\n");
+ return (error);
+ }
+
+ /* Retrieve PHY Revision. */
+ sc->phy_rev = AR_READ(sc, AR_PHY_CHIP_ID);
+
+ if (!(sc->flags & ATHN_FLAG_PCIE))
+ athn_config_nonpcie(sc);
+ else
+ athn_config_pcie(sc);
+
+ /* Allow access to analog chips. */
+ AR_WRITE(sc, AR_PHY(0), 0x00000007);
+ /* Get RF revision. */
+ sc->rf_rev = athn_get_rf_rev(sc);
+
+ /* Read entire ROM content. */
+ if ((error = athn_read_rom(sc)) != 0) {
+ printf(": could not read ROM\n");
+ return (error);
+ }
+ base = sc->eep;
+
+ eep_ver = (base->version >> 12) & 0xf;
+ sc->eep_rev = (base->version & 0xfff);
+ if (eep_ver != AR_EEP_VER || sc->eep_rev == 0) {
+ printf(": unsupported ROM version %d.%d\n", eep_ver,
+ sc->eep_rev);
+ return (EINVAL);
+ }
+
+ sc->ops.setup(sc);
+
+ IEEE80211_ADDR_COPY(ic->ic_myaddr, base->macAddr);
+ printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
+
+ if (base->rfSilent & AR_EEP_RFSILENT_ENABLED)
+ sc->flags |= ATHN_FLAG_RFSILENT;
+
+ /* Get the number of HW key cache entries. */
+ kc_entries_exp = MS(base->deviceCap, AR_EEP_DEVCAP_KC_ENTRIES);
+ sc->kc_entries = (kc_entries_exp != 0) ?
+ 1 << kc_entries_exp : AR_KEYTABLE_SIZE;
+ DPRINTF(("%d key cache entries\n", sc->kc_entries));
+ /*
+ * In HostAP mode, the number of STAs that we can handle is
+ * limited by the number of entries in the HW key cache.
+ */
+ ic->ic_max_nnodes = sc->kc_entries; /* XXX MIC. */
+
+ DPRINTF(("using %s loop power control\n",
+ (sc->flags & ATHN_FLAG_OLPC) ? "open" : "closed"));
+
+ sc->txchainmask = base->txMask;
+ if (sc->mac_ver == AR_SREV_VERSION_5416_PCI &&
+ !(base->opCapFlags & AR_OPFLAGS_11A)) {
+ /* NB: Linux has a bug here. */
+ /* For single-band AR5416 PCI, use GPIO pin 0. */
+ sc->rxchainmask = athn_gpio_read(sc, 0) ? 0x5 : 0x7;
+ } else
+ sc->rxchainmask = base->rxMask;
+ DPRINTF(("txchainmask=0x%x rxchainmask=0x%x\n",
+ sc->txchainmask, sc->rxchainmask));
+ /* Count the number of bits set (in lowest 3 bits). */
+ sc->ntxchains =
+ ((sc->txchainmask >> 2) & 1) +
+ ((sc->txchainmask >> 1) & 1) +
+ ((sc->txchainmask >> 0) & 1);
+ sc->nrxchains =
+ ((sc->rxchainmask >> 2) & 1) +
+ ((sc->rxchainmask >> 1) & 1) +
+ ((sc->rxchainmask >> 0) & 1);
+
+ error = athn_tx_alloc(sc);
+ if (error != 0) {
+ printf("%s: could not allocate Tx DMA resources\n",
+ sc->sc_dev.dv_xname);
+ return (error);
+ }
+ error = athn_rx_alloc(sc);
+ if (error != 0) {
+ printf("%s: could not allocate Rx DMA resources\n",
+ sc->sc_dev.dv_xname);
+ return (error);
+ }
+
+ /* Reset HW key cache entries (XXX not here.) */
+ for (i = 0; i < sc->kc_entries; i++)
+ athn_reset_key(sc, i);
+
+ /* XXX not here. */
+ AR_SETBITS(sc, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
+
+#ifdef ATHN_BT_COEXISTENCE
+ /* Initialize bluetooth coexistence for combo chips. */
+ if (sc->flags & ATHN_FLAG_BTCOEX)
+ athn_btcoex_init(sc);
+#endif
+
+ athn_gpio_config_output(sc, AR_GPIO_LED_PIN,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ /* LED off, active low. */
+ athn_gpio_write(sc, AR_GPIO_LED_PIN, 1);
+
+ if (AR_SINGLE_CHIP(sc)) {
+ printf("%s: %s rev %d (%dT%dR), ROM rev %d\n",
+ sc->sc_dev.dv_xname, athn_get_mac_name(sc), sc->mac_rev,
+ sc->ntxchains, sc->nrxchains, sc->eep_rev);
+ } else {
+ printf("%s: MAC %s rev %d, RF %s (%dT%dR), ROM rev %d\n",
+ sc->sc_dev.dv_xname, athn_get_mac_name(sc), sc->mac_rev,
+ athn_get_rf_name(sc), sc->ntxchains, sc->nrxchains,
+ sc->eep_rev);
+ }
+
+ timeout_set(&sc->scan_to, athn_next_scan, sc);
+ timeout_set(&sc->calib_to, athn_calib_to, sc);
+
+ sc->amrr.amrr_min_success_threshold = 1;
+ sc->amrr.amrr_max_success_threshold = 15;
+
+ ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
+ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
+ ic->ic_state = IEEE80211_S_INIT;
+
+ /* Set device capabilities. */
+ ic->ic_caps =
+ IEEE80211_C_WEP | /* WEP */
+ IEEE80211_C_RSN | /* WPA/RSN */
+ IEEE80211_C_MONITOR | /* monitor mode supported */
+ IEEE80211_C_SHSLOT | /* short slot time supported */
+ IEEE80211_C_SHPREAMBLE | /* short preamble supported */
+ IEEE80211_C_PMGT; /* power saving supported */
+
+#ifndef IEEE80211_NO_HT
+ if (base->opCapFlags & AR_OPFLAGS_11N) {
+ /* Set HT capabilities. */
+ ic->ic_htcaps =
+ IEEE80211_HTCAP_SMPS_DIS |
+ IEEE80211_HTCAP_CBW20_40 |
+ IEEE80211_HTCAP_SGI40 |
+ IEEE80211_HTCAP_DSSSCCK40;
+ }
+#endif
+
+ /* Set supported rates. */
+ if (base->opCapFlags & AR_OPFLAGS_11G) {
+ ic->ic_sup_rates[IEEE80211_MODE_11B] =
+ ieee80211_std_rateset_11b;
+ ic->ic_sup_rates[IEEE80211_MODE_11G] =
+ ieee80211_std_rateset_11g;
+ }
+ if (base->opCapFlags & AR_OPFLAGS_11A) {
+ ic->ic_sup_rates[IEEE80211_MODE_11A] =
+ ieee80211_std_rateset_11a;
+ }
+#ifndef IEEE80211_NO_HT
+ if (base->opCapFlags & AR_OPFLAGS_11N) {
+ /* Set supported HT rates. */
+ ic->ic_sup_mcs[0] = 0xff;
+ if (sc->nrxchains > 1)
+ ic->ic_sup_mcs[1] = 0xff;
+ }
+#endif
+
+ /* Get the list of auhtorized/supported channels. */
+ athn_get_chanlist(sc);
+
+ /* IBSS channel undefined for now. */
+ ic->ic_ibss_chan = &ic->ic_channels[0];
+
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = athn_init;
+ ifp->if_ioctl = athn_ioctl;
+ ifp->if_start = athn_start;
+ ifp->if_watchdog = athn_watchdog;
+ IFQ_SET_READY(&ifp->if_snd);
+ memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
+
+ if_attach(ifp);
+ ieee80211_ifattach(ifp);
+ ic->ic_node_alloc = athn_node_alloc;
+ ic->ic_newassoc = athn_newassoc;
+ ic->ic_updateslot = athn_updateslot;
+ ic->ic_updateedca = athn_updateedca;
+#ifdef notyet
+ ic->ic_set_key = athn_set_key;
+ ic->ic_delete_key = athn_delete_key;
+#endif
+
+ /* Override 802.11 state transition machine. */
+ sc->sc_newstate = ic->ic_newstate;
+ ic->ic_newstate = athn_newstate;
+ ieee80211_media_init(ifp, athn_media_change, ieee80211_media_status);
+
+#if NBPFILTER > 0
+ athn_radiotap_attach(sc);
+#endif
+
+ return (0);
+}
+
+void
+athn_detach(struct athn_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_ic.ic_if;
+ int qid;
+
+ timeout_del(&sc->scan_to);
+ timeout_del(&sc->calib_to);
+
+ /* Free Tx/Rx DMA resources. */
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++)
+ athn_tx_reclaim(sc, qid);
+ athn_tx_free(sc);
+ athn_rx_free(sc);
+ /* Free ROM copy. */
+ if (sc->eep != NULL)
+ free(sc->eep, M_DEVBUF);
+
+ ieee80211_ifdetach(ifp);
+ if_detach(ifp);
+}
+
+#if NBPFILTER > 0
+/*
+ * Attach the interface to 802.11 radiotap.
+ */
+void
+athn_radiotap_attach(struct athn_softc *sc)
+{
+ bpfattach(&sc->sc_drvbpf, &sc->sc_ic.ic_if, DLT_IEEE802_11_RADIO,
+ sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
+
+ sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
+ sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
+ sc->sc_rxtap.wr_ihdr.it_present = htole32(ATHN_RX_RADIOTAP_PRESENT);
+
+ sc->sc_txtap_len = sizeof sc->sc_txtapu;
+ sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
+ sc->sc_txtap.wt_ihdr.it_present = htole32(ATHN_TX_RADIOTAP_PRESENT);
+}
+#endif
+
+void
+athn_get_chanlist(struct athn_softc *sc)
+{
+ struct ar_base_eep_header *base = sc->eep;
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint8_t chan;
+ int i;
+
+ /* XXX Regulatory domain. */
+ if (base->opCapFlags & AR_OPFLAGS_11G) {
+ for (i = 1; i <= 14; i++) {
+ chan = i;
+ ic->ic_channels[chan].ic_freq =
+ ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
+ ic->ic_channels[chan].ic_flags =
+ IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
+ }
+ }
+ if (base->opCapFlags & AR_OPFLAGS_11A) {
+ for (i = 0; i < nitems(athn_5ghz_chans); i++) {
+ chan = athn_5ghz_chans[i];
+ ic->ic_channels[chan].ic_freq =
+ ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
+ }
+ }
+}
+
+int
+athn_tx_alloc(struct athn_softc *sc)
+{
+ struct athn_tx_buf *bf;
+ bus_size_t size;
+ int error, nsegs, i;
+
+ /*
+ * Allocate a pool of Tx descriptors shared between all Tx queues.
+ */
+ size = ATHN_NTXBUFS * ATHN_MAX_SCATTER * sizeof (struct ar_tx_desc);
+
+ error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
+ BUS_DMA_NOWAIT, &sc->map);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamem_alloc(sc->sc_dmat, size, 4, 0, &sc->seg, 1,
+ &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamem_map(sc->sc_dmat, &sc->seg, 1, size,
+ (caddr_t *)&sc->descs, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamap_load_raw(sc->sc_dmat, sc->map, &sc->seg, 1, size,
+ BUS_DMA_NOWAIT);
+ if (error != 0)
+ goto fail;
+
+ SIMPLEQ_INIT(&sc->txbufs);
+ for (i = 0; i < ATHN_NTXBUFS; i++) {
+ bf = &sc->txpool[i];
+
+ error = bus_dmamap_create(sc->sc_dmat, ATHN_TXBUFSZ,
+ ATHN_MAX_SCATTER, ATHN_TXBUFSZ, 0, BUS_DMA_NOWAIT,
+ &bf->bf_map);
+ if (error != 0) {
+ printf("%s: could not create Tx buf DMA map\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+
+ bf->bf_descs = &sc->descs[i * ATHN_MAX_SCATTER];
+ bf->bf_daddr = sc->map->dm_segs[0].ds_addr +
+ i * ATHN_MAX_SCATTER * sizeof (struct ar_tx_desc);
+
+ SIMPLEQ_INSERT_TAIL(&sc->txbufs, bf, bf_list);
+ }
+ return (0);
+ fail:
+ athn_tx_free(sc);
+ return (error);
+}
+
+void
+athn_tx_free(struct athn_softc *sc)
+{
+ struct athn_tx_buf *bf;
+ int i;
+
+ for (i = 0; i < ATHN_NTXBUFS; i++) {
+ bf = &sc->txpool[i];
+
+ if (bf->bf_map != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, bf->bf_map);
+ }
+ /* Free Tx descriptors. */
+ if (sc->map != NULL) {
+ if (sc->descs != NULL) {
+ bus_dmamap_unload(sc->sc_dmat, sc->map);
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->descs,
+ ATHN_NTXBUFS * ATHN_MAX_SCATTER *
+ sizeof (struct ar_tx_desc));
+ bus_dmamem_free(sc->sc_dmat, &sc->seg, 1);
+ }
+ bus_dmamap_destroy(sc->sc_dmat, sc->map);
+ }
+}
+
+int
+athn_rx_alloc(struct athn_softc *sc)
+{
+ struct athn_rxq *rxq = &sc->rxq;
+ struct athn_rx_buf *bf;
+ struct ar_rx_desc *ds;
+ bus_size_t size;
+ int error, nsegs, i;
+
+ size = ATHN_NRXBUFS * sizeof (struct ar_rx_desc);
+
+ error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
+ BUS_DMA_NOWAIT, &rxq->map);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &rxq->seg, 1,
+ &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamem_map(sc->sc_dmat, &rxq->seg, 1, size,
+ (caddr_t *)&rxq->descs, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
+ if (error != 0)
+ goto fail;
+
+ error = bus_dmamap_load_raw(sc->sc_dmat, rxq->map, &rxq->seg, 1,
+ size, BUS_DMA_NOWAIT);
+ if (error != 0)
+ goto fail;
+
+ for (i = 0; i < ATHN_NRXBUFS; i++) {
+ bf = &rxq->bf[i];
+ ds = &rxq->descs[i];
+
+ error = bus_dmamap_create(sc->sc_dmat, ATHN_RXBUFSZ, 1,
+ ATHN_RXBUFSZ, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
+ &bf->bf_map);
+ if (error != 0) {
+ printf("%s: could not create Rx buf DMA map\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+ /*
+ * Assumes MCLGETI returns cache-line-size aligned buffers.
+ */
+ bf->bf_m = MCLGETI(NULL, M_DONTWAIT, NULL, ATHN_RXBUFSZ);
+ if (bf->bf_m == NULL) {
+ printf("%s: could not allocate Rx mbuf\n",
+ sc->sc_dev.dv_xname);
+ error = ENOBUFS;
+ goto fail;
+ }
+
+ error = bus_dmamap_load(sc->sc_dmat, bf->bf_map,
+ mtod(bf->bf_m, void *), ATHN_RXBUFSZ, NULL,
+ BUS_DMA_NOWAIT | BUS_DMA_READ);
+ if (error != 0) {
+ printf("%s: could not DMA map Rx buffer\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+
+ bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0,
+ bf->bf_map->dm_mapsize, BUS_DMASYNC_PREREAD);
+
+ bf->bf_desc = ds;
+ bf->bf_daddr = rxq->map->dm_segs[0].ds_addr +
+ i * sizeof (struct ar_rx_desc);
+ }
+ return (0);
+ fail:
+ athn_rx_free(sc);
+ return (error);
+}
+
+void
+athn_rx_free(struct athn_softc *sc)
+{
+ struct athn_rxq *rxq = &sc->rxq;
+ struct athn_rx_buf *bf;
+ int i;
+
+ for (i = 0; i < ATHN_NRXBUFS; i++) {
+ bf = &rxq->bf[i];
+
+ if (bf->bf_map != NULL)
+ bus_dmamap_destroy(sc->sc_dmat, bf->bf_map);
+ if (bf->bf_m != NULL)
+ m_freem(bf->bf_m);
+ }
+ /* Free Rx descriptors. */
+ if (rxq->descs != NULL) {
+ if (rxq->descs != NULL) {
+ bus_dmamap_unload(sc->sc_dmat, rxq->map);
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)rxq->descs,
+ ATHN_NRXBUFS * sizeof (struct ar_rx_desc));
+ bus_dmamem_free(sc->sc_dmat, &rxq->seg, 1);
+ }
+ bus_dmamap_destroy(sc->sc_dmat, rxq->map);
+ }
+}
+
+void
+athn_rx_start(struct athn_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct athn_rxq *rxq = &sc->rxq;
+ struct athn_rx_buf *bf;
+ struct ar_rx_desc *ds;
+ uint32_t rfilt;
+ int i;
+
+ /* Setup and link Rx descriptors. */
+ SIMPLEQ_INIT(&rxq->head);
+ rxq->lastds = NULL;
+ for (i = 0; i < ATHN_NRXBUFS; i++) {
+ bf = &rxq->bf[i];
+ ds = bf->bf_desc;
+
+ memset(ds, 0, sizeof (*ds));
+ ds->ds_data = bf->bf_map->dm_segs[0].ds_addr;
+ ds->ds_ctl1 = SM(AR_RXC1_BUF_LEN, ATHN_RXBUFSZ);
+
+ if (rxq->lastds != NULL)
+ rxq->lastds->ds_link = bf->bf_daddr;
+ SIMPLEQ_INSERT_TAIL(&rxq->head, bf, bf_list);
+ rxq->lastds = ds;
+ }
+ bus_dmamap_sync(sc->sc_dmat, rxq->map, 0, rxq->map->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
+
+ /* Enable Rx. */
+ AR_WRITE(sc, AR_RXDP, SIMPLEQ_FIRST(&rxq->head)->bf_daddr);
+ AR_WRITE(sc, AR_CR, AR_CR_RXE);
+
+ /* Set Rx filter. */
+ rfilt = AR_RX_FILTER_UCAST | AR_RX_FILTER_BCAST | AR_RX_FILTER_MCAST;
+#ifndef IEEE80211_NO_HT
+ /* Want Compressed Block Ack Requests. */
+ rfilt |= AR_RX_FILTER_COMPR_BAR;
+#endif
+ if (ic->ic_opmode != IEEE80211_M_STA) {
+ rfilt |= AR_RX_FILTER_PROBEREQ;
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ rfilt |= AR_RX_FILTER_PROM;
+#ifndef IEEE80211_STA_ONLY
+ if (AR_SREV_9280_10_OR_LATER(sc) &&
+ ic->ic_opmode == IEEE80211_M_HOSTAP)
+ rfilt |= AR_RX_FILTER_PSPOLL;
+#endif
+ rfilt |= AR_RX_FILTER_BEACON;
+ } else
+ rfilt |= AR_RX_FILTER_BEACON; /* XXX AR_RX_FILTER_MYBEACON */
+ athn_set_rxfilter(sc, rfilt);
+
+ /* Set BSSID mask. */
+ AR_WRITE(sc, AR_BSSMSKL, 0xffffffff);
+ AR_WRITE(sc, AR_BSSMSKU, 0xffff);
+
+ athn_set_opmode(sc);
+
+ /* Set multicast filter. */
+ AR_WRITE(sc, AR_MCAST_FIL0, 0xffffffff);
+ AR_WRITE(sc, AR_MCAST_FIL1, 0xffffffff);
+
+ AR_WRITE(sc, AR_FILT_OFDM, 0);
+ AR_WRITE(sc, AR_FILT_CCK, 0);
+ AR_WRITE(sc, AR_MIBC, 0);
+ AR_WRITE(sc, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ AR_WRITE(sc, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ /* XXX ANI. */
+ AR_WRITE(sc, AR_PHY_ERR_1, 0);
+ AR_WRITE(sc, AR_PHY_ERR_2, 0);
+
+ /* Disable HW crypto for now. */
+ AR_SETBITS(sc, AR_DIAG_SW, AR_DIAG_ENCRYPT_DIS | AR_DIAG_DECRYPT_DIS);
+
+ /* Start PCU Rx. */
+ AR_CLRBITS(sc, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
+}
+
+void
+athn_set_rxfilter(struct athn_softc *sc, uint32_t rfilt)
+{
+ AR_WRITE(sc, AR_RX_FILTER, rfilt);
+
+#ifdef notyet
+ reg = AR_READ(sc, AR_PHY_ERR);
+ reg &= (AR_PHY_ERR_RADAR | AR_PHY_ERR_OFDM_TIMING |
+ AR_PHY_ERR_CCK_TIMING);
+ AR_WRITE(sc, AR_PHY_ERR, reg);
+ if (reg != 0)
+ AR_SETBITS(sc, AR_RXCFG, AR_RXCFG_ZLFDMA);
+ else
+ AR_CLRBITS(sc, AR_RXCFG, AR_RXCFG_ZLFDMA);
+#else
+ AR_WRITE(sc, AR_PHY_ERR, 0);
+ AR_CLRBITS(sc, AR_RXCFG, AR_RXCFG_ZLFDMA);
+#endif
+}
+
+int
+athn_intr(void *xsc)
+{
+ struct athn_softc *sc = xsc;
+ struct ifnet *ifp = &sc->sc_ic.ic_if;
+ uint32_t intr, intr2, intr5, sync;
+
+ if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
+ (IFF_UP | IFF_RUNNING))
+ return (1);
+
+ /* Get pending interrupts. */
+ intr = AR_READ(sc, AR_INTR_ASYNC_CAUSE);
+ if ((intr & AR_INTR_MAC_IRQ) == 0 || intr == AR_INTR_SPURIOUS) {
+ intr = AR_READ(sc, AR_INTR_SYNC_CAUSE);
+ if (intr == AR_INTR_SPURIOUS ||
+ (intr & AR_INTR_SYNC_DEFAULT) == 0)
+ return (1); /* Not for us. */
+ }
+
+ if ((AR_READ(sc, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) != 0 &&
+ (AR_READ(sc, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON)
+ intr = AR_READ(sc, AR_ISR);
+ else
+ intr = 0;
+ sync = AR_READ(sc, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
+ if (intr == 0 && sync == 0)
+ return (1); /* Not for us. */
+
+ if (intr != 0) {
+ if (intr & AR_ISR_BCNMISC) {
+ intr2 = AR_READ(sc, AR_ISR_S2);
+ if (intr2 & AR_ISR_S2_TIM)
+ /* TBD */;
+ if (intr2 & AR_ISR_S2_TSFOOR)
+ /* TBD */;
+ }
+ intr = AR_READ(sc, AR_ISR_RAC);
+ if (intr == AR_INTR_SPURIOUS)
+ return (0);
+
+ if (intr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+ athn_rx_intr(sc);
+ if (intr & (AR_ISR_RXOK | AR_ISR_RXERR | AR_ISR_RXORN))
+ athn_rx_intr(sc);
+
+ if (intr & (AR_ISR_TXOK | AR_ISR_TXDESC |
+ AR_ISR_TXERR | AR_ISR_TXEOL))
+ athn_tx_intr(sc);
+
+ if (intr & AR_ISR_GENTMR) {
+ intr5 = AR_READ(sc, AR_ISR_S5_S);
+ if (intr5 & AR_ISR_GENTMR) {
+ DPRINTF(("GENTMR trigger=%d thresh=%d\n",
+ MS(intr5, AR_ISR_S5_GENTIMER_TRIG),
+ MS(intr5, AR_ISR_S5_GENTIMER_THRESH)));
+ }
+ }
+
+ intr5 = AR_READ(sc, AR_ISR_S5_S);
+ if (intr5 & AR_ISR_S5_TIM_TIMER)
+ /* TBD */;
+ }
+ if (sync != 0) {
+ if (sync & (AR_INTR_SYNC_HOST1_FATAL |
+ AR_INTR_SYNC_HOST1_PERR))
+ /* TBD */;
+
+ if (sync & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
+ AR_WRITE(sc, AR_RC, AR_RC_HOSTIF);
+ AR_WRITE(sc, AR_RC, 0);
+ }
+
+ AR_WRITE(sc, AR_INTR_SYNC_CAUSE, sync);
+ (void)AR_READ(sc, AR_INTR_SYNC_CAUSE);
+ }
+ return (0);
+}
+
+/*
+ * Access to General Purpose Input/Output ports.
+ */
+int
+athn_gpio_read(struct athn_softc *sc, int pin)
+{
+ KASSERT(pin < sc->ngpiopins);
+ return ((AR_READ(sc, AR_GPIO_IN_OUT) >> (sc->ngpiopins + pin)) & 1);
+}
+
+void
+athn_gpio_write(struct athn_softc *sc, int pin, int set)
+{
+ uint32_t reg;
+
+ KASSERT(pin < sc->ngpiopins);
+ reg = AR_READ(sc, AR_GPIO_IN_OUT);
+ if (set)
+ reg |= 1 << pin;
+ else
+ reg &= ~(1 << pin);
+ AR_WRITE(sc, AR_GPIO_IN_OUT, reg);
+}
+
+void
+athn_gpio_config_input(struct athn_softc *sc, int pin)
+{
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_GPIO_OE_OUT);
+ reg &= ~(AR_GPIO_OE_OUT_DRV_M << (pin * 2));
+ reg |= AR_GPIO_OE_OUT_DRV_NO << (pin * 2);
+ AR_WRITE(sc, AR_GPIO_OE_OUT, reg);
+}
+
+void
+athn_gpio_config_output(struct athn_softc *sc, int pin, int type)
+{
+ uint32_t reg;
+ int mux, off;
+
+ mux = pin / 6;
+ off = pin % 6;
+
+ reg = AR_READ(sc, AR_GPIO_OUTPUT_MUX(mux));
+ if (!AR_SREV_9280_20_OR_LATER(sc) && mux == 0)
+ reg = (reg & ~0x1f0) | (reg & 0x1f0) << 1;
+ reg &= ~(0x1f << (off * 5));
+ reg |= (type & 0x1f) << (off * 5);
+ AR_WRITE(sc, AR_GPIO_OUTPUT_MUX(mux), reg);
+
+ reg = AR_READ(sc, AR_GPIO_OE_OUT);
+ reg &= ~(AR_GPIO_OE_OUT_DRV_M << (pin * 2));
+ reg |= AR_GPIO_OE_OUT_DRV_ALL << (pin * 2);
+ AR_WRITE(sc, AR_GPIO_OE_OUT, reg);
+}
+
+void
+athn_get_chipid(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_SREV);
+ if (MS(reg, AR_SREV_ID) == 0xff) {
+ sc->mac_ver = MS(reg, AR_SREV_VERSION2);
+ sc->mac_rev = MS(reg, AR_SREV_REVISION2);
+ if (!(reg & AR_SREV_TYPE2_HOST_MODE))
+ sc->flags |= ATHN_FLAG_PCIE;
+ } else {
+ sc->mac_ver = MS(reg, AR_SREV_VERSION);
+ sc->mac_rev = MS(reg, AR_SREV_REVISION);
+ if (sc->mac_ver == AR_SREV_VERSION_5416_PCIE)
+ sc->flags |= ATHN_FLAG_PCIE;
+ }
+}
+
+const char *
+athn_get_mac_name(struct athn_softc *sc)
+{
+ switch (sc->mac_ver) {
+ case AR_SREV_VERSION_5416_PCI:
+ return ("AR5416");
+ case AR_SREV_VERSION_5416_PCIE:
+ return ("AR5418");
+ case AR_SREV_VERSION_9160:
+ return ("AR9160");
+ case AR_SREV_VERSION_9280:
+ return ("AR9280");
+ case AR_SREV_VERSION_9285:
+ return ("AR9285");
+ case AR_SREV_VERSION_9287:
+ return ("AR9287");
+ }
+ return ("unknown");
+}
+
+const char *
+athn_get_rf_name(struct athn_softc *sc)
+{
+ switch (sc->rf_rev) {
+ case AR_RAD5133_SREV_MAJOR: /* Dual-band 3T3R. */
+ return ("AR5133");
+ case AR_RAD2133_SREV_MAJOR: /* Single-band 3T3R. */
+ return ("AR2133");
+ case AR_RAD5122_SREV_MAJOR: /* Dual-band 2T2R. */
+ return ("AR5122");
+ case AR_RAD2122_SREV_MAJOR: /* Single-band 2T2R. */
+ return ("AR2122");
+ }
+ return ("unknown");
+}
+
+int
+athn_reset_power_on(struct athn_softc *sc)
+{
+ int ntries;
+
+ /* Set force wake. */
+ AR_WRITE(sc, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+ /* Make sure no DMA is active by doing an AHB reset. */
+ AR_WRITE(sc, AR_RC, AR_RC_AHB);
+
+ /* RTC reset and clear. */
+ AR_WRITE(sc, AR_RTC_RESET, 0);
+ DELAY(2);
+ AR_WRITE(sc, AR_RC, 0);
+ AR_WRITE(sc, AR_RTC_RESET, 1);
+
+ /* Poll until RTC is ON. */
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if ((AR_READ(sc, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
+ AR_RTC_STATUS_ON)
+ break;
+ DELAY(10);
+ }
+ if (ntries == 1000) {
+ DPRINTF(("RTC not waking up\n"));
+ return (ETIMEDOUT);
+ }
+
+ /* Read hardware revision. */
+ athn_get_chipid(sc);
+
+ return (athn_reset(sc, 0));
+}
+
+int
+athn_reset(struct athn_softc *sc, int cold)
+{
+ int ntries;
+
+ /* Set force wake. */
+ AR_WRITE(sc, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+ if (AR_READ(sc, AR_INTR_SYNC_CAUSE) &
+ (AR_INTR_SYNC_LOCAL_TIMEOUT | AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+ AR_WRITE(sc, AR_INTR_SYNC_ENABLE, 0);
+ AR_WRITE(sc, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+ } else
+ AR_WRITE(sc, AR_RC, AR_RC_AHB);
+
+ AR_WRITE(sc, AR_RTC_RC, AR_RTC_RC_MAC_WARM |
+ (cold ? AR_RTC_RC_MAC_COLD : 0));
+ DELAY(50);
+ AR_WRITE(sc, AR_RTC_RC, 0);
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if (!(AR_READ(sc, AR_RTC_RC) &
+ (AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD)))
+ break;
+ DELAY(10);
+ }
+ if (ntries == 1000) {
+ DPRINTF(("RTC stuck in MAC reset\n"));
+ return (ETIMEDOUT);
+ }
+ AR_WRITE(sc, AR_RC, 0);
+ return (0);
+}
+
+int
+athn_set_power_awake(struct athn_softc *sc)
+{
+ int ntries, error;
+
+ /* Do a Power-On-Reset if shutdown. */
+ if ((AR_READ(sc, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
+ AR_RTC_STATUS_SHUTDOWN) {
+ if ((error = athn_reset_power_on(sc)) != 0)
+ return (error);
+ athn_init_pll(sc, NULL);
+ }
+ AR_SETBITS(sc, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+ DELAY(50); /* Give chip the chance to awake. */
+
+ /* Poll until RTC is ON. */
+ for (ntries = 0; ntries < 4000; ntries++) {
+ if ((AR_READ(sc, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
+ AR_RTC_STATUS_ON)
+ break;
+ DELAY(50);
+ AR_SETBITS(sc, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+ }
+ if (ntries == 4000) {
+ DPRINTF(("RTC not waking up\n"));
+ return (ETIMEDOUT);
+ }
+
+ AR_CLRBITS(sc, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ return (0);
+}
+
+void
+athn_set_power_sleep(struct athn_softc *sc)
+{
+ AR_SETBITS(sc, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ AR_CLRBITS(sc, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
+ AR_WRITE(sc, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+ /*
+ * 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))
+ AR_CLRBITS(sc, AR_RTC_RESET, AR_RTC_RESET_EN);
+}
+
+void
+athn_init_pll(struct athn_softc *sc, const struct ieee80211_channel *c)
+{
+ uint32_t pll;
+
+ if (AR_SREV_9280_10_OR_LATER(sc)) {
+ pll = SM(AR_RTC_9160_PLL_REFDIV, 0x05);
+ if (c != NULL && IEEE80211_IS_CHAN_5GHZ(c)) {
+ if (AR_SREV_9280_20(sc)) {
+ /* Workaround for AR9280 2.0/5GHz. */
+ if ((c->ic_freq % 20) == 0 ||
+ (c->ic_freq % 10) == 0)
+ pll = 0x2850;
+ else
+ pll = 0x142c;
+ } else
+ pll |= SM(AR_RTC_9160_PLL_DIV, 0x28);
+ } else
+ pll |= SM(AR_RTC_9160_PLL_DIV, 0x2c);
+ } else if (AR_SREV_9160_10_OR_LATER(sc)) {
+ pll = SM(AR_RTC_9160_PLL_REFDIV, 0x05);
+ if (c != NULL && IEEE80211_IS_CHAN_5GHZ(c))
+ pll |= SM(AR_RTC_9160_PLL_DIV, 0x50);
+ else
+ pll |= SM(AR_RTC_9160_PLL_DIV, 0x58);
+ } else {
+ pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+ if (c != NULL && IEEE80211_IS_CHAN_5GHZ(c))
+ pll |= SM(AR_RTC_PLL_DIV, 0x0a);
+ else
+ pll |= SM(AR_RTC_PLL_DIV, 0x0b);
+ }
+ DPRINTFN(5, ("AR_RTC_PLL_CONTROL=0x%08x\n", pll));
+ AR_WRITE(sc, AR_RTC_PLL_CONTROL, pll);
+ DELAY(100);
+ AR_WRITE(sc, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+}
+
+void
+athn_write_serdes(struct athn_softc *sc, const uint32_t val[9])
+{
+ int i;
+
+ /* Write 288-bit value to Serializer/Deserializer. */
+ for (i = 0; i < 288 / 32; i++)
+ AR_WRITE(sc, AR_PCIE_SERDES, val[i]);
+ AR_WRITE(sc, AR_PCIE_SERDES2, 0);
+}
+
+void
+athn_config_pcie(struct athn_softc *sc)
+{
+ /* Disable PLL when in L0s as well as receiver clock when in L1. */
+ athn_write_serdes(sc, sc->serdes);
+
+ DELAY(1000);
+ /* Allow forcing of PCIe core into L1 state. */
+ AR_SETBITS(sc, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+
+#ifndef ATHN_PCIE_WAEN
+ AR_WRITE(sc, AR_WA, sc->workaround);
+#else
+ AR_WRITE(sc, AR_WA, ATHN_PCIE_WAEN);
+#endif
+}
+
+void
+athn_config_nonpcie(struct athn_softc *sc)
+{
+ athn_write_serdes(sc, ar_nonpcie_serdes);
+}
+
+uint8_t
+athn_reverse_bits(uint8_t v, int nbits)
+{
+ KASSERT(nbits <= 8);
+ v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
+ v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
+ v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
+ return (v >> (8 - nbits));
+}
+
+uint8_t
+athn_get_rf_rev(struct athn_softc *sc)
+{
+ uint8_t rev, reg;
+ int i;
+
+ AR_WRITE(sc, AR_PHY(0x36), 0x00007058);
+ for (i = 0; i < 8; i++)
+ AR_WRITE(sc, AR_PHY(0x20), 0x00010000);
+ reg = (AR_READ(sc, AR_PHY(256)) >> 24) & 0xff;
+ reg = (reg & 0xf0) >> 4 | (reg & 0x0f) << 4;
+
+ rev = athn_reverse_bits(reg, 8);
+ if ((rev & AR_RADIO_SREV_MAJOR) == 0)
+ rev = AR_RAD5133_SREV_MAJOR;
+ return (rev);
+}
+
+static __inline uint32_t
+athn_synth_delay(struct athn_softc *sc)
+{
+ uint32_t delay;
+
+ delay = MS(AR_READ(sc, AR_PHY_RX_DELAY), AR_PHY_RX_DELAY_DELAY);
+ if (sc->sc_ic.ic_curmode == IEEE80211_MODE_11B)
+ delay = (delay * 4) / 22;
+ else
+ delay = delay / 10; /* in 100ns steps */
+ return (delay);
+}
+
+int
+athn_set_chan(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ struct athn_ops *ops = &sc->ops;
+ int error, qid, ntries;
+
+ /* Check that Tx is stopped, otherwise RF Bus grant will not work. */
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++)
+ if (athn_tx_pending(sc, qid))
+ return (EBUSY);
+
+ /* Request RF Bus grant. */
+ AR_WRITE(sc, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+ for (ntries = 0; ntries < 10000; ntries++) {
+ if (AR_READ(sc, AR_PHY_RFBUS_GRANT) & AR_PHY_RFBUS_GRANT_EN)
+ break;
+ DELAY(10);
+ }
+ if (ntries == 10000) {
+ DPRINTF(("could not kill baseband Rx"));
+ return (ETIMEDOUT);
+ }
+
+ athn_set_phy(sc, c, extc);
+
+ /* Change the synthesizer. */
+ if ((error = ops->set_synth(sc, c, extc)) != 0)
+ return (error);
+
+ /* Set transmit power values for new channel. */
+ ops->set_txpower(sc, c, extc);
+
+ /* Wait for the synthesizer to settle. */
+ DELAY(AR_BASE_PHY_ACTIVE_DELAY + athn_synth_delay(sc));
+
+ /* Release the RF Bus grant. */
+ AR_WRITE(sc, AR_PHY_RFBUS_REQ, 0);
+
+ /* Write delta slope coeffs for modes where OFDM may be used. */
+ if (sc->sc_ic.ic_curmode != IEEE80211_MODE_11B)
+ athn_set_delta_slope(sc, c, extc);
+
+ ops->spur_mitigate(sc, c, extc);
+ /* XXX Load noisefloor values and start calibration. */
+
+ return (0);
+}
+
+int
+athn_switch_chan(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ int error, qid;
+
+ /* Disable interrupts. */
+ athn_disable_interrupts(sc);
+
+ /* Stop all Tx queues. */
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++)
+ athn_stop_tx_dma(sc, qid);
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++)
+ athn_tx_reclaim(sc, qid);
+
+ /* Stop Rx. */
+ AR_SETBITS(sc, AR_DIAG_SW, AR_DIAG_RX_DIS);
+ AR_WRITE(sc, AR_MIBC, AR_MIBC_FMC);
+ AR_WRITE(sc, AR_MIBC, AR_MIBC_CMC);
+ AR_WRITE(sc, AR_FILT_OFDM, 0);
+ AR_WRITE(sc, AR_FILT_CCK, 0);
+ athn_set_rxfilter(sc, 0);
+ error = athn_stop_rx_dma(sc);
+ if (error != 0)
+ goto reset;
+
+ /* AR9280 always needs a full reset. */
+ if (AR_SREV_9280(sc))
+ goto reset;
+
+ /* If band or bandwidth changes, we need to do a full reset. */
+ if (c->ic_flags != ic->ic_bss->ni_chan->ic_flags) {
+ DPRINTF(("channel band switch\n"));
+ goto reset;
+ }
+ error = athn_set_power_awake(sc);
+ if (error != 0)
+ goto reset;
+
+ error = athn_set_chan(sc, c, extc);
+ if (error != 0) {
+ reset: /* Error found, try a full reset. */
+ DPRINTF(("needs a full reset\n"));
+ error = athn_hw_reset(sc, c, extc);
+ if (error != 0) /* Hopeless case. */
+ return (error);
+ }
+ athn_rx_start(sc);
+
+ /* Re-enable interrupts. */
+ athn_enable_interrupts(sc);
+ return (0);
+}
+
+void
+athn_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
+{
+#define COEFF_SCALE_SHIFT 24
+ uint32_t exp, man;
+
+ /* exponent = 14 - floor(log2(coeff)) */
+ for (exp = 31; exp > 0; exp--)
+ if (coeff & (1 << exp))
+ break;
+ exp = 14 - (exp - COEFF_SCALE_SHIFT);
+
+ /* mantissa = floor(coeff * 2^exponent + 0.5) */
+ man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
+
+ *mantissa = man >> (COEFF_SCALE_SHIFT - exp);
+ *exponent = exp - 16;
+#undef COEFF_SCALE_SHIFT
+}
+
+void
+athn_set_delta_slope(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ uint32_t coeff, exp, man, reg;
+
+ /* Set Delta Slope (exponent and mantissa). */
+ coeff = (100 << 24) / c->ic_freq;
+ athn_get_delta_slope(coeff, &exp, &man);
+ DPRINTFN(5, ("delta slope coeff exp=%u man=%u\n", exp, man));
+
+ reg = AR_READ(sc, AR_PHY_TIMING3);
+ reg = RW(reg, AR_PHY_TIMING3_DSC_EXP, exp);
+ reg = RW(reg, AR_PHY_TIMING3_DSC_MAN, man);
+ AR_WRITE(sc, AR_PHY_TIMING3, reg);
+
+ /* For Short GI, coeff is 9/10 that of normal coeff. */
+ coeff = (9 * coeff) / 10;
+ athn_get_delta_slope(coeff, &exp, &man);
+ DPRINTFN(5, ("delta slope coeff exp=%u man=%u\n", exp, man));
+
+ reg = AR_READ(sc, AR_PHY_HALFGI);
+ reg = RW(reg, AR_PHY_HALFGI_DSC_EXP, exp);
+ reg = RW(reg, AR_PHY_HALFGI_DSC_MAN, man);
+ AR_WRITE(sc, AR_PHY_HALFGI, reg);
+}
+
+void
+athn_set_phy(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ uint32_t phy;
+
+ if (AR_SREV_9285_10_OR_LATER(sc))
+ phy = AR_READ(sc, AR_PHY_TURBO) & AR_PHY_FC_ENABLE_DAC_FIFO;
+ else
+ phy = 0;
+ phy |= AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 |
+ AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
+ if (extc != NULL) {
+ phy |= AR_PHY_FC_DYN2040_EN;
+ if (extc > c) /* XXX */
+ phy |= AR_PHY_FC_DYN2040_PRI_CH;
+ }
+ AR_WRITE(sc, AR_PHY_TURBO, phy);
+
+ AR_WRITE(sc, AR_2040_MODE,
+ (extc != NULL) ? AR_2040_JOINED_RX_CLEAR : 0);
+
+ AR_WRITE(sc, AR_GTXTO, SM(AR_GTXTO_TIMEOUT_LIMIT, 25));
+ AR_WRITE(sc, AR_CST, SM(AR_CST_TIMEOUT_LIMIT, 15));
+}
+
+int
+athn_read_rom_word(struct athn_softc *sc, uint32_t addr, uint16_t *val)
+{
+ uint32_t reg;
+ int ntries;
+
+ /* Read 16-bit value from ROM. */
+ reg = AR_READ(sc, AR_EEPROM_OFFSET(addr));
+ for (ntries = 0; ntries < 1000; ntries++) {
+ reg = AR_READ(sc, AR_EEPROM_STATUS_DATA);
+ if (!(reg & (AR_EEPROM_STATUS_DATA_BUSY |
+ AR_EEPROM_STATUS_DATA_PROT_ACCESS))) {
+ *val = MS(reg, AR_EEPROM_STATUS_DATA_VAL);
+ return (0);
+ }
+ DELAY(10);
+ }
+ *val = 0xffff;
+ return (ETIMEDOUT);
+}
+
+int
+athn_read_rom(struct athn_softc *sc)
+{
+ uint32_t addr, end;
+ uint16_t magic, sum, *eep;
+ int need_swap = 0;
+ int error;
+
+ /* Determine ROM endianness. */
+ error = athn_read_rom_word(sc, AR_EEPROM_MAGIC_OFFSET, &magic);
+ if (error != 0)
+ return (error);
+ if (magic != AR_EEPROM_MAGIC) {
+ if (magic != swap16(AR_EEPROM_MAGIC)) {
+ DPRINTF(("invalid ROM magic 0x%x != 0x%x\n",
+ magic, AR_EEPROM_MAGIC));
+ return (EIO);
+ }
+ DPRINTF(("non-native ROM endianness\n"));
+ need_swap = 1;
+ }
+
+ /* Allocate space to store ROM in host memory. */
+ sc->eep = malloc(sc->eep_size, M_DEVBUF, M_NOWAIT);
+ if (sc->eep == NULL)
+ return (ENOMEM);
+
+ /* Read entire ROM and compute checksum. */
+ sum = 0;
+ eep = sc->eep;
+ end = sc->eep_base + sc->eep_size / sizeof (uint16_t);
+ for (addr = sc->eep_base; addr < end; addr++, eep++) {
+ if ((error = athn_read_rom_word(sc, addr, eep)) != 0) {
+ DPRINTF(("could not read ROM at 0x%x\n", addr));
+ return (error);
+ }
+ if (need_swap)
+ *eep = swap16(*eep);
+ sum ^= *eep;
+ }
+ if (sum != 0xffff) {
+ printf("%s: bad ROM checksum 0x%04x\n",
+ sc->sc_dev.dv_xname, sum);
+ return (EIO);
+ }
+ if (need_swap)
+ athn_swap_rom(sc);
+
+ return (0);
+}
+
+void
+athn_swap_rom(struct athn_softc *sc)
+{
+ struct ar_base_eep_header *base = sc->eep;
+
+ /* Swap common fields first. */
+ base->length = swap16(base->length);
+ base->version = swap16(base->version);
+ base->regDmn[0] = swap16(base->regDmn[0]);
+ base->regDmn[1] = swap16(base->regDmn[1]);
+ base->rfSilent = swap16(base->rfSilent);
+ base->blueToothOptions = swap16(base->blueToothOptions);
+ base->deviceCap = swap16(base->deviceCap);
+
+ /* Swap device-dependent fields. */
+ sc->ops.swap_rom(sc);
+}
+
+void
+athn_reset_key(struct athn_softc *sc, int entry)
+{
+ /*
+ * NB: Key cache registers access special memory area that requires
+ * two 32-bit writes to actually update the values in the internal
+ * memory. Consequently, writes must be grouped by pair.
+ */
+ AR_WRITE(sc, AR_KEYTABLE_KEY0(entry), 0);
+ AR_WRITE(sc, AR_KEYTABLE_KEY1(entry), 0);
+
+ AR_WRITE(sc, AR_KEYTABLE_KEY2(entry), 0);
+ AR_WRITE(sc, AR_KEYTABLE_KEY3(entry), 0);
+
+ AR_WRITE(sc, AR_KEYTABLE_KEY4(entry), 0);
+ AR_WRITE(sc, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+
+ AR_WRITE(sc, AR_KEYTABLE_MAC0(entry), 0);
+ AR_WRITE(sc, AR_KEYTABLE_MAC1(entry), 0);
+}
+
+int
+athn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
+ struct ieee80211_key *k)
+{
+ struct athn_softc *sc = ic->ic_softc;
+ uint32_t type, lo, hi;
+ uint32_t keybuf[4], micbuf[4];
+ const uint8_t *addr;
+ uintptr_t entry, micentry;
+
+ switch (k->k_cipher) {
+ case IEEE80211_CIPHER_WEP40:
+ type = AR_KEYTABLE_TYPE_40;
+ break;
+ case IEEE80211_CIPHER_WEP104:
+ type = AR_KEYTABLE_TYPE_104;
+ break;
+ case IEEE80211_CIPHER_TKIP:
+ type = AR_KEYTABLE_TYPE_TKIP;
+ break;
+ case IEEE80211_CIPHER_CCMP:
+ type = AR_KEYTABLE_TYPE_CCM;
+ break;
+ default:
+ /* Fallback to software crypto for other ciphers. */
+ return (ieee80211_set_key(ic, ni, k));
+ }
+
+ memset(keybuf, 0, sizeof keybuf);
+ memcpy(keybuf, k->k_key, MIN(k->k_len, 16));
+
+ if (k->k_flags & IEEE80211_KEY_GROUP)
+ entry = k->k_id;
+ else
+ entry = IEEE80211_AID(ni->ni_associd); /* XXX +offset. */
+ k->k_priv = (void *)entry;
+
+ /* NB: See note about key cache registers access above. */
+ if (type == AR_KEYTABLE_TYPE_TKIP) {
+ micentry = entry + 64;
+
+ /* XXX Split MIC. */
+ AR_WRITE(sc, AR_KEYTABLE_KEY0(micentry), micbuf[0]);
+ AR_WRITE(sc, AR_KEYTABLE_KEY1(micentry), micbuf[1]);
+
+ AR_WRITE(sc, AR_KEYTABLE_KEY2(micentry), micbuf[2]);
+ AR_WRITE(sc, AR_KEYTABLE_KEY3(micentry), micbuf[3]);
+
+ AR_WRITE(sc, AR_KEYTABLE_KEY4(micentry), micbuf[4]);
+ AR_WRITE(sc, AR_KEYTABLE_TYPE(micentry), AR_KEYTABLE_TYPE_CLR);
+
+ /* MAC address registers are reserved for the MIC entry. */
+ AR_WRITE(sc, AR_KEYTABLE_MAC0(micentry), 0);
+ AR_WRITE(sc, AR_KEYTABLE_MAC1(micentry), 0);
+ } else {
+ AR_WRITE(sc, AR_KEYTABLE_KEY0(entry), keybuf[0]);
+ AR_WRITE(sc, AR_KEYTABLE_KEY1(entry), keybuf[1]);
+
+ AR_WRITE(sc, AR_KEYTABLE_KEY2(entry), keybuf[2]);
+ AR_WRITE(sc, AR_KEYTABLE_KEY3(entry), keybuf[3]);
+
+ AR_WRITE(sc, AR_KEYTABLE_KEY4(entry), keybuf[4]);
+ AR_WRITE(sc, AR_KEYTABLE_TYPE(entry), type);
+ }
+
+ /* Clear keys from the stack. */
+ memset(keybuf, 0, sizeof keybuf);
+ memset(micbuf, 0, sizeof micbuf);
+
+ /* XXX Group keys? */
+ addr = ni->ni_macaddr;
+ lo = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
+ hi = addr[4] | addr[5] << 8;
+ lo = lo >> 1 | hi << 31;
+ hi = hi >> 1;
+ AR_WRITE(sc, AR_KEYTABLE_MAC0(entry), lo);
+ AR_WRITE(sc, AR_KEYTABLE_MAC1(entry), hi | AR_KEYTABLE_VALID);
+ return (0);
+}
+
+void
+athn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
+ struct ieee80211_key *k)
+{
+ struct athn_softc *sc = ic->ic_softc;
+ uintptr_t entry;
+
+ switch (k->k_cipher) {
+ case IEEE80211_CIPHER_WEP40:
+ case IEEE80211_CIPHER_WEP104:
+ case IEEE80211_CIPHER_TKIP:
+ case IEEE80211_CIPHER_CCMP:
+ entry = (uintptr_t)k->k_priv;
+ athn_reset_key(sc, entry);
+ break;
+ default:
+ /* Fallback to software crypto for other ciphers. */
+ ieee80211_delete_key(ic, ni, k);
+ }
+}
+
+#ifdef ATHN_BT_COEXISTENCE
+void
+athn_btcoex_init(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ if (sc->flags & ATHN_FLAG_BTCOEX2WIRE) {
+ /* Connect bt_active to baseband. */
+ AR_CLRBITS(sc, AR_GPIO_INPUT_EN_VAL,
+ AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
+ AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF);
+ AR_SETBITS(sc, AR_GPIO_INPUT_EN_VAL,
+ AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
+
+ reg = AR_READ(sc, AR_GPIO_INPUT_MUX1);
+ reg = RW(reg, AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+ AR_GPIO_BTACTIVE_PIN);
+ AR_WRITE(sc, AR_GPIO_INPUT_MUX1, reg);
+
+ athn_gpio_config_input(sc, AR_GPIO_BTACTIVE_PIN);
+ } else { /* 3-wire. */
+ AR_SETBITS(sc, AR_GPIO_INPUT_EN_VAL,
+ AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
+ AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
+
+ reg = AR_READ(sc, AR_GPIO_INPUT_MUX1);
+ reg = RW(reg, AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+ AR_GPIO_BTACTIVE_PIN);
+ reg = RW(reg, AR_GPIO_INPUT_MUX1_BT_PRIORITY,
+ AR_GPIO_BTPRIORITY_PIN);
+ AR_WRITE(sc, AR_GPIO_INPUT_MUX1, reg);
+
+ athn_gpio_config_input(sc, AR_GPIO_BTACTIVE_PIN);
+ athn_gpio_config_input(sc, AR_GPIO_BTPRIORITY_PIN);
+ }
+}
+
+void
+athn_btcoex_enable(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ if (sc->flags & ATHN_FLAG_BTCOEX3WIRE) {
+ AR_WRITE(sc, AR_BT_COEX_MODE,
+ SM(AR_BT_MODE, AR_BT_MODE_SLOTTED) |
+ SM(AR_BT_PRIORITY_TIME, 2) |
+ SM(AR_BT_FIRST_SLOT_TIME, 5) |
+ SM(AR_BT_QCU_THRESH, ATHN_QID_AC_BE) |
+ AR_BT_TXSTATE_EXTEND | AR_BT_TX_FRAME_EXTEND |
+ AR_BT_QUIET | AR_BT_RX_CLEAR_POLARITY);
+ AR_WRITE(sc, AR_BT_COEX_WEIGHT,
+ SM(AR_BTCOEX_BT_WGHT, AR_STOMP_LOW_BT_WGHT) |
+ SM(AR_BTCOEX_WL_WGHT, AR_STOMP_LOW_WL_WGHT));
+ AR_WRITE(sc, AR_BT_COEX_MODE2,
+ SM(AR_BT_BCN_MISS_THRESH, 50) |
+ AR_BT_HOLD_RX_CLEAR | AR_BT_DISABLE_BT_ANT);
+
+ AR_SETBITS(sc, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE);
+ AR_CLRBITS(sc, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX);
+
+ athn_gpio_config_output(sc, AR_GPIO_WLANACTIVE_PIN,
+ AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
+
+ } else { /* 2-wire. */
+ athn_gpio_config_output(sc, AR_GPIO_WLANACTIVE_PIN,
+ AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
+ }
+ reg = AR_READ(sc, AR_GPIO_PDPU);
+ reg &= ~(0x3 << (AR_GPIO_WLANACTIVE_PIN * 2));
+ reg |= 0x2 << (AR_GPIO_WLANACTIVE_PIN * 2);
+ AR_WRITE(sc, AR_GPIO_PDPU, reg);
+
+ /* Disable PCIe Active State Power Management (ASPM). */
+ if (sc->sc_disable_aspm != NULL)
+ sc->sc_disable_aspm(sc);
+
+ /* XXX Start periodic timer. */
+}
+
+void
+athn_btcoex_disable(struct athn_softc *sc)
+{
+ athn_gpio_write(sc, AR_GPIO_WLANACTIVE_PIN, 0);
+
+ athn_gpio_config_output(sc, AR_GPIO_WLANACTIVE_PIN,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+
+ if (sc->flags & ATHN_FLAG_BTCOEX3WIRE) {
+ AR_WRITE(sc, AR_BT_COEX_MODE,
+ SM(AR_BT_MODE, AR_BT_MODE_DISABLED) | AR_BT_QUIET);
+ AR_WRITE(sc, AR_BT_COEX_WEIGHT, 0);
+ AR_WRITE(sc, AR_BT_COEX_MODE2, 0);
+ /* XXX Stop periodic timer. */
+ }
+ /* XXX Restore ASPM setting? */
+}
+#endif
+
+void
+athn_rfsilent_init(struct athn_softc *sc)
+{
+ struct ar_base_eep_header *base = sc->eep;
+ uint32_t reg;
+
+ /* Get GPIO pin used by hardware radio switch. */
+ sc->rfsilent_pin = MS(base->rfSilent, AR_EEP_RFSILENT_GPIO_SEL);
+ /* Get polarity of hardware radio switch. */
+ if (base->rfSilent & AR_EEP_RFSILENT_POLARITY)
+ sc->flags |= ATHN_FLAG_RFSILENT_REVERSED;
+ printf("%s: Found RF switch connected to GPIO pin %d\n",
+ sc->sc_dev.dv_xname, sc->rfsilent_pin);
+
+ /* Configure hardware radio switch. */
+ AR_SETBITS(sc, AR_GPIO_INPUT_EN_VAL, AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
+ reg = AR_READ(sc, AR_GPIO_INPUT_MUX2);
+ reg = RW(reg, AR_GPIO_INPUT_MUX2_RFSILENT, 0);
+ AR_WRITE(sc, AR_GPIO_INPUT_MUX2, reg);
+ athn_gpio_config_input(sc, sc->rfsilent_pin);
+ AR_SETBITS(sc, AR_PHY_TEST, AR_PHY_TEST_RFSILENT_BB);
+}
+
+void
+athn_iter_func(void *arg, struct ieee80211_node *ni)
+{
+ struct athn_softc *sc = arg;
+ struct athn_node *an = (struct athn_node *)ni;
+
+ ieee80211_amrr_choose(&sc->amrr, ni, &an->amn);
+}
+
+void
+athn_calib_to(void *arg)
+{
+ struct athn_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int s;
+
+ s = splnet();
+#ifdef notyet
+ /* XXX ANI. */
+ /* XXX OLPC temperature compensation. */
+
+ if (AR_READ(sc, AR_PHY_TIMING_CTRL4_0) & AR_PHY_TIMING_CTRL4_DO_CAL) {
+ /* Calibration in progress, come back later. */
+ timeout_add_msec(&sc->calib_to, 500);
+ splx(s);
+ return;
+ }
+ if (sc->calib_mask & ATHN_CAL_ADC_GAIN)
+ athn_calib_iq(sc);
+ else if (sc->calib_mask & ATHN_CAL_ADC_DC)
+ athn_calib_adc_gain(sc);
+ else if (sc->calib_mask & ATHN_CAL_IQ)
+ athn_calib_adc_dc_off(sc);
+#endif
+ if (ic->ic_fixed_rate == -1) {
+ if (ic->ic_opmode == IEEE80211_M_STA)
+ athn_iter_func(sc, ic->ic_bss);
+ else
+ ieee80211_iterate_nodes(ic, athn_iter_func, sc);
+ }
+ timeout_add_msec(&sc->calib_to, 500);
+ splx(s);
+}
+
+void
+athn_do_calib(struct athn_softc *sc)
+{
+ int log = AR_MAX_LOG_CAL; /* XXX */
+ uint32_t mode = 0, reg;
+
+ reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0);
+ 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)
+ mode = AR_PHY_CALMODE_ADC_GAIN;
+ else if (sc->calib_mask & ATHN_CAL_ADC_DC)
+ mode = AR_PHY_CALMODE_ADC_DC_PER;
+ else if (sc->calib_mask & ATHN_CAL_IQ)
+ mode = AR_PHY_CALMODE_IQ;
+ AR_WRITE(sc, AR_PHY_CALMODE, mode);
+
+ AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0, AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+void
+athn_calib_iq(struct athn_softc *sc)
+{
+ struct athn_iq_cal *cal;
+ uint32_t reg, i_coff_denom, q_coff_denom;
+ int32_t i_coff, q_coff;
+ int i, iq_corr_neg;
+
+ for (i = 0; i < AR_MAX_CHAINS; i++) {
+ cal = &sc->calib.iq[i];
+
+ /* Accumulate IQ calibration measures (clear on read). */
+ cal->pwr_meas_i += AR_READ(sc, AR_PHY_CAL_MEAS_0(i));
+ cal->pwr_meas_q += AR_READ(sc, AR_PHY_CAL_MEAS_1(i));
+ cal->iq_corr_meas +=
+ (int32_t)AR_READ(sc, AR_PHY_CAL_MEAS_2(i));
+ }
+ if (++sc->calib.nsamples < AR_CAL_SAMPLES) {
+ /* Not enough samples accumulated, continue. */
+ athn_do_calib(sc);
+ return;
+ }
+
+ for (i = 0; i < sc->nrxchains; i++) {
+ cal = &sc->calib.iq[i];
+
+ if (cal->pwr_meas_q == 0)
+ continue;
+
+ if ((iq_corr_neg = cal->iq_corr_meas < 0))
+ cal->iq_corr_meas = -cal->iq_corr_meas;
+
+ i_coff_denom =
+ (cal->pwr_meas_i / 2 + cal->pwr_meas_q / 2) / 128;
+ q_coff_denom = cal->pwr_meas_q / 64;
+
+ if (i_coff_denom == 0 || q_coff_denom == 0)
+ continue; /* Prevents division by zero. */
+
+ i_coff = cal->iq_corr_meas / i_coff_denom;
+ q_coff = (cal->pwr_meas_i / q_coff_denom) - 64;
+
+ /* Negate i_coff if iq_corr_meas is positive. */
+ if (!iq_corr_neg)
+ i_coff = 0x40 - (i_coff & 0x3f);
+ if (q_coff > 15)
+ q_coff = 15;
+ else if (q_coff <= -16)
+ q_coff = 16;
+
+ DPRINTF(("IQ calibration for chain %d\n", i));
+ reg = AR_READ(sc, AR_PHY_TIMING_CTRL4(i));
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, i_coff);
+ reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, q_coff);
+ AR_WRITE(sc, AR_PHY_TIMING_CTRL4(i), reg);
+ }
+
+ AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
+ AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
+
+void
+athn_calib_adc_gain(struct athn_softc *sc)
+{
+ struct athn_adc_cal *cal;
+ uint32_t reg, gain_mismatch_i, gain_mismatch_q;
+ int i;
+
+ for (i = 0; i < AR_MAX_CHAINS; i++) {
+ cal = &sc->calib.adc_gain[i];
+
+ /* Accumulate ADC gain measures (clear on read). */
+ cal->pwr_meas_odd_i += AR_READ(sc, AR_PHY_CAL_MEAS_0(i));
+ cal->pwr_meas_even_i += AR_READ(sc, AR_PHY_CAL_MEAS_1(i));
+ 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) {
+ /* Not enough samples accumulated, continue. */
+ athn_do_calib(sc);
+ return;
+ }
+
+ for (i = 0; i < sc->nrxchains; i++) {
+ cal = &sc->calib.adc_gain[i];
+
+ if (cal->pwr_meas_odd_i == 0 || cal->pwr_meas_even_q == 0)
+ continue; /* Prevents division by zero. */
+
+ gain_mismatch_i =
+ (cal->pwr_meas_even_i * 32) / cal->pwr_meas_odd_i;
+ gain_mismatch_q =
+ (cal->pwr_meas_odd_q * 32) / cal->pwr_meas_even_q;
+
+ DPRINTF(("ADC gain calibration for chain %d\n", i));
+ reg = AR_READ(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_IGAIN, gain_mismatch_i);
+ reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_QGAIN, gain_mismatch_q);
+ AR_WRITE(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), reg);
+ }
+
+ AR_SETBITS(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
+
+void
+athn_calib_adc_dc_off(struct athn_softc *sc)
+{
+ struct athn_adc_cal *cal;
+ int32_t dc_offset_mismatch_i, dc_offset_mismatch_q;
+ uint32_t reg;
+ int count, i;
+
+ for (i = 0; i < AR_MAX_CHAINS; i++) {
+ cal = &sc->calib.adc_dc_offset[i];
+
+ /* Accumulate ADC DC offset measures (clear on read). */
+ cal->pwr_meas_odd_i += AR_READ(sc, AR_PHY_CAL_MEAS_0(i));
+ cal->pwr_meas_even_i += AR_READ(sc, AR_PHY_CAL_MEAS_1(i));
+ 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) {
+ /* Not enough samples accumulated, continue. */
+ athn_do_calib(sc);
+ return;
+ }
+
+ count = (1 << (AR_MAX_LOG_CAL + 5)) * sc->calib.nsamples;
+
+ for (i = 0; i < sc->nrxchains; i++) {
+ cal = &sc->calib.adc_dc_offset[i];
+
+ dc_offset_mismatch_i =
+ (cal->pwr_meas_even_i - cal->pwr_meas_odd_i * 2) / count;
+ dc_offset_mismatch_q =
+ (cal->pwr_meas_odd_q - cal->pwr_meas_even_q * 2) / count;
+
+ DPRINTF(("ADC DC offset calibration for chain %d\n", i));
+ reg = AR_READ(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_QDC,
+ dc_offset_mismatch_q);
+ reg = RW(reg, AR_PHY_NEW_ADC_DC_GAIN_IDC,
+ dc_offset_mismatch_i);
+ AR_WRITE(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), reg);
+ }
+
+ AR_SETBITS(sc, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
+
+void
+athn_read_noisefloor(struct athn_softc *sc, int16_t *nf, int16_t *nf_ext)
+{
+/* Sign-extend 9-bit value to 16-bit. */
+#define SIGN_EXT(v) ((((int16_t)(v)) << 7) >> 7)
+ uint32_t reg;
+ int i;
+
+ for (i = 0; i < sc->nrxchains; i++) {
+ reg = AR_READ(sc, AR_PHY_CCA(i));
+ if (AR_SREV_9280_10_OR_LATER(sc))
+ nf[i] = MS(reg, AR9280_PHY_MINCCA_PWR);
+ else
+ nf[i] = MS(reg, AR_PHY_MINCCA_PWR);
+ nf[i] = SIGN_EXT(nf[i]);
+
+ reg = AR_READ(sc, AR_PHY_EXT_CCA(i));
+ if (AR_SREV_9280_10_OR_LATER(sc))
+ nf_ext[i] = MS(reg, AR9280_PHY_EXT_MINCCA_PWR);
+ else
+ nf_ext[i] = MS(reg, AR_PHY_EXT_MINCCA_PWR);
+ nf_ext[i] = SIGN_EXT(nf_ext[i]);
+ }
+#undef SIGN_EXT
+}
+
+void
+athn_write_noisefloor(struct athn_softc *sc, int16_t *nf, int16_t *nf_ext)
+{
+ uint32_t reg;
+ int i;
+
+ for (i = 0; i < sc->nrxchains; i++) {
+ reg = AR_READ(sc, AR_PHY_CCA(i));
+ reg = RW(reg, AR_PHY_MAXCCA_PWR, nf[i]);
+ AR_WRITE(sc, AR_PHY_CCA(i), reg);
+
+ reg = AR_READ(sc, AR_PHY_EXT_CCA(i));
+ reg = RW(reg, AR_PHY_EXT_MAXCCA_PWR, nf_ext[i]);
+ AR_WRITE(sc, AR_PHY_EXT_CCA(i), reg);
+ }
+}
+
+void
+athn_get_noisefloor(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ 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;
+ }
+ /* Noisefloor calibration is finished. */
+ athn_read_noisefloor(sc, nf, nf_ext);
+
+ /* Update noisefloor history. */
+ for (i = 0; i < sc->nrxchains; i++) {
+ sc->nf_hist[sc->nf_hist_cur].nf[i] = nf[i];
+ sc->nf_hist[sc->nf_hist_cur].nf_ext[i] = nf_ext[i];
+ }
+ if (++sc->nf_hist_cur >= ATHN_NF_CAL_HIST_MAX)
+ sc->nf_hist_cur = 0;
+}
+
+void
+athn_bb_load_noisefloor(struct athn_softc *sc)
+{
+ int16_t nf[AR_MAX_CHAINS], nf_ext[AR_MAX_CHAINS];
+ int i, ntries;
+
+ /* Write filtered noisefloor values. */
+ for (i = 0; i < sc->nrxchains; i++) {
+ nf[i] = sc->nf_priv[i] * 2;
+ nf_ext[i] = sc->nf_ext_priv[i] * 2;
+ }
+ athn_write_noisefloor(sc, nf, nf_ext);
+
+ /* Load filtered noisefloor values into baseband. */
+ AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
+ AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+ /* Wait for load to complete. */
+ for (ntries = 0; ntries < 5; ntries++) {
+ if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
+ break;
+ DELAY(50);
+ }
+#ifdef ATHN_DEBUG
+ if (ntries == 5 && athn_debug > 0)
+ printf("failed to load noisefloor values\n");
+#endif
+
+ /* Restore noisefloor values to initial (max) values. */
+ for (i = 0; i < AR_MAX_CHAINS; i++)
+ nf[i] = nf_ext[i] = -50 * 2;
+ athn_write_noisefloor(sc, nf, nf_ext);
+}
+
+void
+athn_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);
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+int
+athn_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ int error;
+
+ if (AR_SREV_9285_12_OR_LATER(sc))
+ error = ar9285_1_2_init_calib(sc, c, extc);
+ else
+ error = ar5416_init_calib(sc, c, extc);
+ if (error != 0)
+ return (error);
+
+ /* Do PA calibration. */
+ if (AR_SREV_9285_11_OR_LATER(sc))
+ ar9285_pa_calib(sc);
+
+ /* Do noisefloor calibration. */
+ AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+ if (AR_SREV_9160_10_OR_LATER(sc)) {
+ /* Enable IQ calibration. */
+ sc->calib_mask = ATHN_CAL_IQ;
+
+ /* Enable ADC gain and ADC DC offset calibrations. */
+ if (IEEE80211_IS_CHAN_5GHZ(c) || extc != NULL)
+ sc->calib_mask |= ATHN_CAL_ADC_GAIN | ATHN_CAL_ADC_DC;
+
+ athn_do_calib(sc);
+ }
+ return (0);
+}
+
+/*
+ * Anti-noise immunity.
+ */
+int32_t
+athn_ani_get_rssi(struct athn_softc *sc)
+{
+ return (0); /* XXX */
+}
+
+void
+athn_ani_set_noise_immunity_level(struct athn_softc *sc, int level)
+{
+ int high = level == 4;
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
+ reg = RW(reg, AR_PHY_DESIRED_SZ_TOT_DES, high ? -62 : -55);
+ AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
+
+ reg = AR_READ(sc, AR_PHY_AGC_CTL1);
+ reg = RW(reg, AR_PHY_AGC_CTL1_COARSE_LOW, high ? -70 : -64);
+ reg = RW(reg, AR_PHY_AGC_CTL1_COARSE_HIGH, high ? -12 : -14);
+ AR_WRITE(sc, AR_PHY_AGC_CTL1, reg);
+
+ reg = AR_READ(sc, AR_PHY_FIND_SIG);
+ reg = RW(reg, AR_PHY_FIND_SIG_FIRPWR, high ? -80 : -78);
+ AR_WRITE(sc, AR_PHY_FIND_SIG, reg);
+
+ sc->ani.noise_immunity_level = level;
+}
+
+void
+athn_ani_ena_ofdm_weak_signal(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_PHY_SFCORR_LOW);
+ reg = RW(reg, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, 50);
+ reg = RW(reg, AR_PHY_SFCORR_LOW_M2_THRESH_LOW, 40);
+ reg = RW(reg, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, 48);
+ AR_WRITE(sc, AR_PHY_SFCORR_LOW, reg);
+
+ reg = AR_READ(sc, AR_PHY_SFCORR);
+ reg = RW(reg, AR_PHY_SFCORR_M1_THRESH, 77);
+ reg = RW(reg, AR_PHY_SFCORR_M2_THRESH, 64);
+ reg = RW(reg, AR_PHY_SFCORR_M2COUNT_THR, 16);
+ AR_WRITE(sc, AR_PHY_SFCORR, reg);
+
+ reg = AR_READ(sc, AR_PHY_SFCORR_EXT);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, 50);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH_LOW, 40);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH, 77);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH, 64);
+ AR_WRITE(sc, AR_PHY_SFCORR_EXT, reg);
+
+ AR_SETBITS(sc, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+ sc->ani.ofdm_weak_signal = 1;
+}
+
+void
+athn_ani_dis_ofdm_weak_signal(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_PHY_SFCORR_LOW);
+ reg = RW(reg, AR_PHY_SFCORR_LOW_M1_THRESH_LOW, 127);
+ reg = RW(reg, AR_PHY_SFCORR_LOW_M2_THRESH_LOW, 127);
+ reg = RW(reg, AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, 63);
+ AR_WRITE(sc, AR_PHY_SFCORR_LOW, reg);
+
+ reg = AR_READ(sc, AR_PHY_SFCORR);
+ reg = RW(reg, AR_PHY_SFCORR_M1_THRESH, 127);
+ reg = RW(reg, AR_PHY_SFCORR_M2_THRESH, 127);
+ reg = RW(reg, AR_PHY_SFCORR_M2COUNT_THR, 31);
+ AR_WRITE(sc, AR_PHY_SFCORR, reg);
+
+ reg = AR_READ(sc, AR_PHY_SFCORR_EXT);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH_LOW, 127);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH_LOW, 127);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M1_THRESH, 127);
+ reg = RW(reg, AR_PHY_SFCORR_EXT_M2_THRESH, 127);
+ AR_WRITE(sc, AR_PHY_SFCORR_EXT, reg);
+
+ AR_CLRBITS(sc, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+ sc->ani.ofdm_weak_signal = 0;
+}
+
+void
+athn_ani_set_cck_weak_signal(struct athn_softc *sc, int high)
+{
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_PHY_CCK_DETECT);
+ reg = RW(reg, AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, high ? 6 : 8);
+ AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
+
+ sc->ani.cck_weak_signal = high;
+}
+
+void
+athn_ani_set_firstep_level(struct athn_softc *sc, int level)
+{
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_PHY_FIND_SIG);
+ reg = RW(reg, AR_PHY_FIND_SIG_FIRSTEP, level * 4);
+ AR_WRITE(sc, AR_PHY_FIND_SIG, reg);
+
+ sc->ani.firstep_level = level;
+}
+
+void
+athn_ani_set_spur_immunity_level(struct athn_softc *sc, int level)
+{
+ uint32_t reg;
+
+ reg = AR_READ(sc, AR_PHY_TIMING5);
+ reg = RW(reg, AR_PHY_TIMING5_CYCPWR_THR1, (level + 1) * 2);
+ AR_WRITE(sc, AR_PHY_TIMING5, reg);
+
+ sc->ani.spur_immunity_level = level;
+}
+
+void
+athn_ani_ofdm_err_trigger(struct athn_softc *sc)
+{
+ struct athn_ani *ani = &sc->ani;
+ int32_t rssi;
+
+ /* First, raise noise immunity level, up to max. */
+ if (ani->noise_immunity_level < 4) {
+ athn_ani_set_noise_immunity_level(sc,
+ ani->noise_immunity_level + 1);
+ return;
+ }
+
+ /* Then, raise our spur immunity level, up to max. */
+ if (ani->spur_immunity_level < 7) {
+ athn_ani_set_spur_immunity_level(sc,
+ ani->spur_immunity_level + 1);
+ return;
+ }
+
+#ifndef IEEE80211_STA_ONLY
+ if (sc->sc_ic.ic_opmode == IEEE80211_M_HOSTAP) {
+ if (ani->firstep_level < 2)
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level + 1);
+ return;
+ }
+#endif
+ rssi = athn_ani_get_rssi(sc);
+ if (rssi > ATHN_ANI_RSSI_THR_HIGH) {
+ /*
+ * Beacon RSSI is high, turn off OFDM weak signal detection
+ * or raise first step level as last resort.
+ */
+ if (ani->ofdm_weak_signal) {
+ athn_ani_dis_ofdm_weak_signal(sc);
+ athn_ani_set_spur_immunity_level(sc, 0);
+ } else if (ani->firstep_level < 2) {
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level + 1);
+ }
+ } else if (rssi > ATHN_ANI_RSSI_THR_LOW) {
+ /*
+ * Beacon RSSI is in mid range, we need OFDM weak signal
+ * detection but we can raise first step level.
+ */
+ if (!ani->ofdm_weak_signal)
+ athn_ani_ena_ofdm_weak_signal(sc);
+ if (ani->firstep_level < 2) {
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level + 1);
+ }
+ } else if (sc->sc_ic.ic_curmode != IEEE80211_MODE_11A) {
+ /*
+ * Beacon RSSI is low, if in b/g mode, turn off OFDM weak
+ * signal detection and zero first step level to maximize
+ * CCK sensitivity.
+ */
+ if (ani->ofdm_weak_signal)
+ athn_ani_dis_ofdm_weak_signal(sc);
+ if (ani->firstep_level > 0)
+ athn_ani_set_firstep_level(sc, 0);
+ }
+}
+
+void
+athn_ani_cck_err_trigger(struct athn_softc *sc)
+{
+ struct athn_ani *ani = &sc->ani;
+ int32_t rssi;
+
+ /* Raise noise immunity level, up to max. */
+ if (ani->noise_immunity_level < 4) {
+ athn_ani_set_noise_immunity_level(sc,
+ ani->noise_immunity_level + 1);
+ return;
+ }
+
+#ifndef IEEE80211_STA_ONLY
+ if (sc->sc_ic.ic_opmode == IEEE80211_M_HOSTAP) {
+ if (ani->firstep_level < 2)
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level + 1);
+ return;
+ }
+#endif
+ rssi = athn_ani_get_rssi(sc);
+ if (rssi > ATHN_ANI_RSSI_THR_LOW) {
+ /*
+ * Beacon RSSI is in mid or high range, raise first step
+ * level.
+ */
+ if (ani->firstep_level < 2)
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level + 1);
+ } else if (sc->sc_ic.ic_curmode != IEEE80211_MODE_11A) {
+ /*
+ * Beacon RSSI is low, zero first step level to maximize
+ * CCK sensitivity.
+ */
+ if (ani->firstep_level > 0)
+ athn_ani_set_firstep_level(sc, 0);
+ }
+}
+
+void
+athn_ani_lower_immunity(struct athn_softc *sc)
+{
+ struct athn_ani *ani = &sc->ani;
+ int32_t rssi;
+
+#ifndef IEEE80211_STA_ONLY
+ if (sc->sc_ic.ic_opmode == IEEE80211_M_HOSTAP) {
+ if (ani->firstep_level > 0)
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level - 1);
+ return;
+ }
+#endif
+ rssi = athn_ani_get_rssi(sc);
+ if (rssi > ATHN_ANI_RSSI_THR_HIGH) {
+ /*
+ * Beacon RSSI is high, leave OFDM weak signal detection
+ * off or it may oscillate.
+ */
+ } else if (rssi > ATHN_ANI_RSSI_THR_LOW) {
+ /*
+ * Beacon RSSI is in mid range, turn on OFDM weak signal
+ * detection or lower first step level.
+ */
+ if (!ani->ofdm_weak_signal) {
+ athn_ani_ena_ofdm_weak_signal(sc);
+ return;
+ }
+ if (ani->firstep_level > 0) {
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level - 1);
+ return;
+ }
+ } else {
+ /* Beacon RSSI is low, lower first step level. */
+ if (ani->firstep_level > 0) {
+ athn_ani_set_firstep_level(sc,
+ ani->firstep_level - 1);
+ return;
+ }
+ }
+ /*
+ * Lower spur immunity level down to zero, or if all else fails,
+ * lower noise immunity level down to zero.
+ */
+ if (ani->spur_immunity_level > 0)
+ athn_ani_set_spur_immunity_level(sc,
+ ani->spur_immunity_level - 1);
+ else if (ani->noise_immunity_level > 0)
+ athn_ani_set_noise_immunity_level(sc,
+ ani->noise_immunity_level - 1);
+}
+
+void
+athn_ani_restart(struct athn_softc *sc)
+{
+ struct athn_ani *ani = &sc->ani;
+
+ AR_WRITE(sc, AR_PHY_ERR_1, 0);
+ AR_WRITE(sc, AR_PHY_ERR_2, 0);
+ AR_WRITE(sc, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ AR_WRITE(sc, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ ani->listen_time = 0;
+ ani->ofdm_phy_err_count = 0;
+ ani->cck_phy_err_count = 0;
+}
+
+void
+athn_ani_monitor(struct athn_softc *sc)
+{
+ struct athn_ani *ani = &sc->ani;
+ uint32_t cyccnt, txfcnt, rxfcnt, phy1, phy2;
+ int32_t cycdelta, txfdelta, rxfdelta;
+ int32_t listen_time;
+
+ txfcnt = AR_READ(sc, AR_TFCNT); /* Tx frame count. */
+ rxfcnt = AR_READ(sc, AR_RFCNT); /* Rx frame count. */
+ cyccnt = AR_READ(sc, AR_CCCNT); /* Cycle count. */
+
+ if (ani->cyccnt != 0 && ani->cyccnt <= cyccnt) {
+ cycdelta = cyccnt - ani->cyccnt;
+ txfdelta = txfcnt - ani->txfcnt;
+ rxfdelta = rxfcnt - ani->rxfcnt;
+ listen_time = (cycdelta - txfdelta - rxfdelta) / 44000;
+ } else
+ listen_time = 0;
+
+ ani->cyccnt = cyccnt;
+ ani->txfcnt = txfcnt;
+ ani->rxfcnt = rxfcnt;
+
+ if (listen_time < 0) {
+ athn_ani_restart(sc);
+ return;
+ }
+ ani->listen_time += listen_time;
+
+ phy1 = AR_READ(sc, AR_PHY_ERR_1);
+ phy2 = AR_READ(sc, AR_PHY_ERR_2);
+
+ if (phy1 < ani->ofdm_phy_err_base) {
+ AR_WRITE(sc, AR_PHY_ERR_1, ani->ofdm_phy_err_base);
+ AR_WRITE(sc, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ }
+ if (phy2 < ani->cck_phy_err_base) {
+ AR_WRITE(sc, AR_PHY_ERR_2, ani->cck_phy_err_base);
+ AR_WRITE(sc, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+ }
+ if (phy1 < ani->ofdm_phy_err_base || phy2 < ani->cck_phy_err_base)
+ return;
+
+ ani->ofdm_phy_err_count = phy1 - ani->ofdm_phy_err_base;
+ ani->cck_phy_err_count = phy2 - ani->cck_phy_err_base;
+
+ if (ani->listen_time > 5 * ATHN_ANI_PERIOD) {
+ /* Check to see if we need to lower immunity. */
+ if (ani->ofdm_phy_err_count <=
+ ani->listen_time * ani->ofdm_trig_low / 1000 &&
+ ani->cck_phy_err_count <=
+ ani->listen_time * ani->cck_trig_low / 1000)
+ athn_ani_lower_immunity(sc);
+ athn_ani_restart(sc);
+
+ } else if (ani->listen_time > ATHN_ANI_PERIOD) {
+ /* Check to see if we need to raise immunity. */
+ if (ani->ofdm_phy_err_count >
+ ani->listen_time * ani->ofdm_trig_high / 1000) {
+ athn_ani_ofdm_err_trigger(sc);
+ athn_ani_restart(sc);
+ } else if (ani->cck_phy_err_count >
+ ani->listen_time * ani->cck_trig_high / 1000) {
+ athn_ani_cck_err_trigger(sc);
+ athn_ani_restart(sc);
+ }
+ }
+}
+
+uint8_t
+athn_chan2fbin(struct ieee80211_channel *c)
+{
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ return (c->ic_freq - 2300);
+ else
+ return ((c->ic_freq - 4800) / 5);
+}
+
+void
+athn_init_chains(struct athn_softc *sc)
+{
+ if (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5)
+ AR_SETBITS(sc, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN);
+
+ /* Setup chain masks. */
+ if (sc->mac_ver <= AR_SREV_VERSION_9160 &&
+ (sc->rxchainmask == 0x3 || sc->rxchainmask == 0x5)) {
+ AR_WRITE(sc, AR_PHY_RX_CHAINMASK, 0x7);
+ AR_WRITE(sc, AR_PHY_CAL_CHAINMASK, 0x7);
+ } else {
+ AR_WRITE(sc, AR_PHY_RX_CHAINMASK, sc->rxchainmask);
+ AR_WRITE(sc, AR_PHY_CAL_CHAINMASK, sc->rxchainmask);
+ }
+ AR_WRITE(sc, AR_SELFGEN_MASK, sc->txchainmask);
+}
+
+void
+athn_get_pier_ival(uint8_t fbin, const uint8_t *pierfreq, int npiers,
+ int *lo, int *hi)
+{
+ int i;
+
+ for (i = 0; i < npiers; i++)
+ if (pierfreq[i] == AR_BCHAN_UNUSED ||
+ pierfreq[i] > fbin)
+ break;
+ *hi = i;
+ *lo = *hi - 1;
+ if (*lo == -1)
+ *lo = *hi;
+ else if (*hi == npiers || pierfreq[*hi] == AR_BCHAN_UNUSED)
+ *hi = *lo;
+}
+
+uint8_t
+athn_get_vpd(uint8_t pwr, const uint8_t *pwrPdg, const uint8_t *vpdPdg,
+ int nicepts)
+{
+ uint8_t vpd;
+ int i, lo, hi;
+
+ for (i = 0; i < nicepts; i++)
+ if (pwrPdg[i] > pwr)
+ break;
+ hi = i;
+ lo = hi - 1;
+ if (lo == -1)
+ lo = hi;
+ else if (hi == nicepts)
+ hi = lo;
+
+ vpd = athn_interpolate(pwr, pwrPdg[lo], vpdPdg[lo],
+ pwrPdg[hi], vpdPdg[hi]);
+ return (vpd);
+}
+
+void
+athn_get_pdadcs(struct athn_softc *sc, uint8_t fbin, struct athn_pier *lopier,
+ struct athn_pier *hipier, int nxpdgains, int nicepts, uint8_t overlap,
+ uint8_t *boundaries, uint8_t *pdadcs)
+{
+#define DB(x) ((x) / 2) /* Convert half dB to dB. */
+ uint8_t minpwr[AR_PD_GAINS_IN_MASK], maxpwr[AR_PD_GAINS_IN_MASK];
+ uint8_t vpd[AR_MAX_PWR_RANGE_IN_HALF_DB], pwr;
+ uint8_t lovpd, hivpd, boundary;
+ int16_t ss, delta, vpdstep, val;
+ int i, j, npdadcs, nvpds, maxidx, tgtidx;
+
+ /* Compute min and max power in half dB for each pdGain. */
+ for (i = 0; i < nxpdgains; i++) {
+ minpwr[i] = MAX(lopier->pwr[i][0], hipier->pwr[i][0]);
+ maxpwr[i] = MIN(lopier->pwr[i][nicepts - 1],
+ hipier->pwr[i][nicepts - 1]);
+ }
+
+ npdadcs = 0;
+ for (i = 0; i < nxpdgains; i++) {
+ if (i != nxpdgains - 1)
+ boundaries[i] = DB(maxpwr[i] + minpwr[i + 1]) / 2;
+ else
+ boundaries[i] = DB(maxpwr[i]);
+ if (boundaries[i] > AR_MAX_RATE_POWER)
+ boundaries[i] = AR_MAX_RATE_POWER;
+
+ if (i == 0 && !AR_SREV_5416_20_OR_LATER(sc)) {
+ /* Fix the gain delta (AR5416 1.0 only.) */
+ delta = boundaries[0] - 23;
+ boundaries[0] = 23;
+ } else
+ delta = 0;
+
+ /* Find starting index for this pdGain. */
+ if (i != 0) {
+ ss = boundaries[i - 1] - DB(minpwr[i]) -
+ overlap + 1 + delta;
+ } else if (AR_SREV_9280_10_OR_LATER(sc)) {
+ ss = -DB(minpwr[i]);
+ } else
+ ss = 0;
+
+ /* Compute Vpd table for this pdGain. */
+ nvpds = DB(maxpwr[i] - minpwr[i]) + 1;
+ pwr = minpwr[i];
+ for (j = 0; j < nvpds; j++) {
+ /* Get lower and higher Vpd. */
+ lovpd = athn_get_vpd(pwr, lopier->pwr[i],
+ lopier->vpd[i], nicepts);
+ hivpd = athn_get_vpd(pwr, hipier->pwr[i],
+ hipier->vpd[i], nicepts);
+
+ /* Interpolate the final Vpd. */
+ vpd[j] = athn_interpolate(fbin,
+ lopier->fbin, lovpd, hipier->fbin, hivpd);
+
+ pwr += 2; /* In half dB. */
+ }
+
+ /* Extrapolate data for ss < 0. */
+ if (vpd[1] > vpd[0])
+ vpdstep = vpd[1] - vpd[0];
+ else
+ vpdstep = 1;
+ while (ss < 0 && npdadcs < AR_NUM_PDADC_VALUES - 1) {
+ val = vpd[0] + ss * vpdstep;
+ pdadcs[npdadcs++] = MAX(val, 0);
+ ss++;
+ }
+
+ tgtidx = boundaries[i] + overlap - DB(minpwr[i]);
+ maxidx = MIN(tgtidx, nvpds);
+ while (ss < maxidx && npdadcs < AR_NUM_PDADC_VALUES - 1)
+ pdadcs[npdadcs++] = vpd[ss++];
+
+ if (tgtidx <= maxidx)
+ continue;
+
+ /* Extrapolate data for maxidx <= ss <= tgtidx. */
+ if (vpd[nvpds - 1] > vpd[nvpds - 2])
+ vpdstep = vpd[nvpds - 1] - vpd[nvpds - 2];
+ else
+ vpdstep = 1;
+ while (ss <= tgtidx && npdadcs < AR_NUM_PDADC_VALUES - 1) {
+ val = vpd[nvpds - 1] + (ss - maxidx + 1) * vpdstep;
+ pdadcs[npdadcs++] = MIN(val, 255);
+ ss++;
+ }
+ }
+
+ /* Fill remaining PDADC and boundaries entries. */
+ if (AR_SREV_9285(sc))
+ boundary = AR9285_PD_GAIN_BOUNDARY_DEFAULT;
+ else /* Fill with latest. */
+ boundary = boundaries[nxpdgains - 1];
+
+ for (; nxpdgains < AR_PD_GAINS_IN_MASK; nxpdgains++)
+ boundaries[nxpdgains] = boundary;
+
+ for (; npdadcs < AR_NUM_PDADC_VALUES; npdadcs++)
+ pdadcs[npdadcs] = pdadcs[npdadcs - 1];
+#undef DB
+}
+
+int
+athn_interpolate(int x, int x1, int y1, int x2, int y2)
+{
+ if (x1 == x2) /* Prevents division by zero. */
+ return (y1);
+ /* Linear interpolation. */
+ return (y1 + ((x - x1) * (y2 - y1)) / (x2 - x1));
+}
+
+void
+athn_get_lg_tpow(struct athn_softc *sc, struct ieee80211_channel *c,
+ uint8_t ctl, const struct ar_cal_target_power_leg *tgt, int nchans,
+ uint8_t tpow[4])
+{
+ uint8_t fbin;
+ int i, lo, hi;
+
+ /* Find interval (lower and upper indices.) */
+ fbin = athn_chan2fbin(c);
+ for (i = 0; i < nchans; i++) {
+ if (tgt[i].bChannel == AR_BCHAN_UNUSED ||
+ tgt[i].bChannel > fbin)
+ break;
+ }
+ hi = i;
+ lo = hi - 1;
+ if (lo == -1)
+ lo = hi;
+ else if (hi == nchans || tgt[hi].bChannel == AR_BCHAN_UNUSED)
+ hi = lo;
+
+ /* Interpolate values. */
+ for (i = 0; i < 4; i++) {
+ tpow[i] = athn_interpolate(fbin,
+ tgt[lo].bChannel, tgt[lo].tPow2x[i],
+ tgt[hi].bChannel, tgt[hi].tPow2x[i]);
+ }
+ /* XXX Apply conformance test limit. */
+}
+
+#ifndef IEEE80211_NO_HT
+void
+athn_get_ht_tpow(struct athn_softc *sc, struct ieee80211_channel *c,
+ uint8_t ctl, const struct ar_cal_target_power_ht *tgt, int nchans,
+ uint8_t tpow[8])
+{
+ uint8_t fbin;
+ int i, lo, hi;
+
+ /* Find interval (lower and upper indices.) */
+ fbin = athn_chan2fbin(c);
+ for (i = 0; i < nchans; i++) {
+ if (tgt[i].bChannel == AR_BCHAN_UNUSED ||
+ tgt[i].bChannel > fbin)
+ break;
+ }
+ hi = i;
+ lo = hi - 1;
+ if (lo == -1)
+ lo = hi;
+ else if (hi == nchans || tgt[hi].bChannel == AR_BCHAN_UNUSED)
+ hi = lo;
+
+ /* Interpolate values. */
+ for (i = 0; i < 8; i++) {
+ tpow[i] = athn_interpolate(fbin,
+ tgt[lo].bChannel, tgt[lo].tPow2x[i],
+ tgt[hi].bChannel, tgt[hi].tPow2x[i]);
+ }
+ /* XXX Apply conformance test limit. */
+}
+#endif
+
+void
+athn_write_txpower(struct athn_softc *sc, int16_t power[ATHN_POWER_COUNT])
+{
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE1,
+ (power[ATHN_POWER_OFDM18 ] & 0x3f) << 24 |
+ (power[ATHN_POWER_OFDM12 ] & 0x3f) << 16 |
+ (power[ATHN_POWER_OFDM9 ] & 0x3f) << 8 |
+ (power[ATHN_POWER_OFDM6 ] & 0x3f));
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE2,
+ (power[ATHN_POWER_OFDM54 ] & 0x3f) << 24 |
+ (power[ATHN_POWER_OFDM48 ] & 0x3f) << 16 |
+ (power[ATHN_POWER_OFDM36 ] & 0x3f) << 8 |
+ (power[ATHN_POWER_OFDM24 ] & 0x3f));
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE3,
+ (power[ATHN_POWER_CCK2_SP ] & 0x3f) << 24 |
+ (power[ATHN_POWER_CCK2_LP ] & 0x3f) << 16 |
+ (power[ATHN_POWER_XR ] & 0x3f) << 8 |
+ (power[ATHN_POWER_CCK1_LP ] & 0x3f));
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE4,
+ (power[ATHN_POWER_CCK11_SP] & 0x3f) << 24 |
+ (power[ATHN_POWER_CCK11_LP] & 0x3f) << 16 |
+ (power[ATHN_POWER_CCK55_SP] & 0x3f) << 8 |
+ (power[ATHN_POWER_CCK55_LP] & 0x3f));
+#ifndef IEEE80211_NO_HT
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE5,
+ (power[ATHN_POWER_HT20(3) ] & 0x3f) << 24 |
+ (power[ATHN_POWER_HT20(2) ] & 0x3f) << 16 |
+ (power[ATHN_POWER_HT20(1) ] & 0x3f) << 8 |
+ (power[ATHN_POWER_HT20(0) ] & 0x3f));
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE6,
+ (power[ATHN_POWER_HT20(7) ] & 0x3f) << 24 |
+ (power[ATHN_POWER_HT20(6) ] & 0x3f) << 16 |
+ (power[ATHN_POWER_HT20(5) ] & 0x3f) << 8 |
+ (power[ATHN_POWER_HT20(4) ] & 0x3f));
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE7,
+ (power[ATHN_POWER_HT40(3) ] & 0x3f) << 24 |
+ (power[ATHN_POWER_HT40(2) ] & 0x3f) << 16 |
+ (power[ATHN_POWER_HT40(1) ] & 0x3f) << 8 |
+ (power[ATHN_POWER_HT40(0) ] & 0x3f));
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE8,
+ (power[ATHN_POWER_HT40(7) ] & 0x3f) << 24 |
+ (power[ATHN_POWER_HT40(6) ] & 0x3f) << 16 |
+ (power[ATHN_POWER_HT40(5) ] & 0x3f) << 8 |
+ (power[ATHN_POWER_HT40(4) ] & 0x3f));
+ AR_WRITE(sc, AR_PHY_POWER_TX_RATE9,
+ (power[ATHN_POWER_OFDM_EXT] & 0x3f) << 24 |
+ (power[ATHN_POWER_CCK_EXT ] & 0x3f) << 16 |
+ (power[ATHN_POWER_OFDM_DUP] & 0x3f) << 8 |
+ (power[ATHN_POWER_CCK_DUP ] & 0x3f));
+#endif
+}
+
+void
+athn_init_baseband(struct athn_softc *sc)
+{
+ uint32_t synth_delay;
+
+ synth_delay = athn_synth_delay(sc);
+ /* Activate the PHY (includes baseband activate and synthesizer on). */
+ AR_WRITE(sc, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+ DELAY(AR_BASE_PHY_ACTIVE_DELAY + synth_delay);
+}
+
+void
+athn_init_dma(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ /* Set AHB not to do cacheline prefetches. */
+ AR_SETBITS(sc, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN);
+
+ reg = AR_READ(sc, AR_TXCFG);
+ /* Let MAC DMA reads be in 128-byte chunks. */
+ reg = RW(reg, AR_TXCFG_DMASZ, AR_DMASZ_128B);
+
+ /* Set initial Tx trigger level. */
+ if (AR_SREV_9285(sc))
+ reg = RW(reg, AR_TXCFG_FTRIG, AR_TXCFG_FTRIG_256B);
+ else
+ reg = RW(reg, AR_TXCFG_FTRIG, AR_TXCFG_FTRIG_512B);
+ AR_WRITE(sc, AR_TXCFG, reg);
+
+ /* Let MAC DMA writes be in 128-byte chunks. */
+ reg = AR_READ(sc, AR_RXCFG);
+ reg = RW(reg, AR_RXCFG_DMASZ, AR_DMASZ_128B);
+ AR_WRITE(sc, AR_RXCFG, reg);
+
+ /* Setup Rx FIFO threshold to hold off Tx activities. */
+ 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);
+}
+
+void
+athn_inc_tx_trigger_level(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ /* XXX Disable interrupts? */
+ reg = AR_READ(sc, AR_TXCFG);
+ if ((reg & 0x3f0) == 0x3f0) /* Already at max. */
+ return;
+ reg += 0x10; /* Increment Tx trigger level by 1. */
+ AR_WRITE(sc, AR_TXCFG, reg);
+}
+
+int
+athn_stop_rx_dma(struct athn_softc *sc)
+{
+ int ntries;
+
+ AR_WRITE(sc, AR_CR, AR_CR_RXD);
+ /* Wait for Rx enable bit to go low. */
+ for (ntries = 0; ntries < 100; ntries++) {
+ if (!(AR_READ(sc, AR_CR) & AR_CR_RXE))
+ return (0);
+ DELAY(100);
+ }
+ DPRINTF(("Rx DMA failed to stop\n"));
+ return (ETIMEDOUT);
+}
+
+int
+athn_rx_abort(struct athn_softc *sc)
+{
+ int ntries;
+
+ AR_SETBITS(sc, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
+ for (ntries = 0; ntries < 1000; ntries++) {
+ if (MS(AR_READ(sc, AR_OBS_BUS_1), AR_OBS_BUS_1_RX_STATE) == 0)
+ return (0);
+ DELAY(10);
+ }
+ DPRINTF(("Rx failed to go idle in 10ms\n"));
+ AR_CLRBITS(sc, AR_DIAG_SW, AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT);
+ return (ETIMEDOUT);
+}
+
+int
+athn_tx_pending(struct athn_softc *sc, int qid)
+{
+ return (MS(AR_READ(sc, AR_QSTS(qid)), AR_Q_STS_PEND_FR_CNT) != 0 ||
+ (AR_READ(sc, AR_Q_TXE) & (1 << qid)) != 0);
+}
+
+void
+athn_stop_tx_dma(struct athn_softc *sc, int qid)
+{
+ uint32_t tsflo;
+ int ntries, i;
+
+ AR_WRITE(sc, AR_Q_TXD, 1 << qid);
+ for (ntries = 0; ntries < 40; ntries++) {
+ if (athn_tx_pending(sc, qid))
+ break;
+ DELAY(100);
+ }
+ if (ntries == 40) {
+ for (i = 0; i < 2; i++) {
+ tsflo = AR_READ(sc, AR_TSF_L32) / 1024;
+ AR_WRITE(sc, AR_QUIET2,
+ SM(AR_QUIET2_QUIET_DUR, 10));
+ AR_WRITE(sc, AR_QUIET_PERIOD, 100);
+ AR_WRITE(sc, AR_NEXT_QUIET_TIMER, tsflo);
+ AR_SETBITS(sc, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+ if (AR_READ(sc, AR_TSF_L32) / 1024 != tsflo)
+ break;
+ }
+ AR_SETBITS(sc, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+ DELAY(200);
+ AR_CLRBITS(sc, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+
+ for (ntries = 0; ntries < 40; ntries++) {
+ if (athn_tx_pending(sc, qid))
+ break;
+ DELAY(100);
+ }
+
+ AR_CLRBITS(sc, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+ }
+ AR_WRITE(sc, AR_Q_TXD, 0);
+}
+
+void
+athn_tx_reclaim(struct athn_softc *sc, int qid)
+{
+ struct athn_txq *txq = &sc->txq[qid];
+ struct athn_tx_buf *bf;
+
+ /* Reclaim all buffers queued in the specified Tx queue. */
+ /* NB: Tx DMA must be stopped. */
+ while ((bf = SIMPLEQ_FIRST(&txq->head)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&txq->head, bf_list);
+
+ bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0,
+ bf->bf_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, bf->bf_map);
+ m_freem(bf->bf_m);
+ bf->bf_m = NULL;
+ bf->bf_ni = NULL; /* Nodes already freed! */
+
+ /* Link Tx buffer back to global free list. */
+ SIMPLEQ_INSERT_TAIL(&sc->txbufs, bf, bf_list);
+ }
+}
+
+#if NBPFILTER > 0
+void
+athn_rx_radiotap(struct athn_softc *sc, struct mbuf *m, struct ar_rx_desc *ds)
+{
+#define IEEE80211_RADIOTAP_F_SHORTGI 0x80 /* XXX from FBSD */
+
+ struct athn_rx_radiotap_header *tap = &sc->sc_rxtap;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct mbuf mb;
+ uint64_t tsf;
+ uint32_t tstamp;
+ uint8_t rate;
+
+ /* Extend the 15-bit timestamp from Rx descriptor to 64-bit TSF. */
+ tstamp = ds->ds_status2;
+ tsf = AR_READ(sc, AR_TSF_U32);
+ tsf = tsf << 32 | AR_READ(sc, AR_TSF_L32);
+ if ((tsf & 0x7fff) < tstamp)
+ tsf -= 0x8000;
+ tsf = (tsf & ~0x7fff) | tstamp;
+
+ tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
+ tap->wr_tsft = htole64(tsf);
+ tap->wr_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
+ tap->wr_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
+ tap->wr_dbm_antsignal = MS(ds->ds_status4, AR_RXS4_RSSI_COMBINED);
+ /* XXX noise. */
+ tap->wr_antenna = MS(ds->ds_status3, AR_RXS3_ANTENNA);
+ tap->wr_rate = 0; /* In case it can't be found below. */
+ if (AR_SREV_5416_20_OR_LATER(sc))
+ rate = MS(ds->ds_status0, AR_RXS0_RATE);
+ else
+ rate = MS(ds->ds_status3, AR_RXS3_RATE);
+ if (rate & 0x80) { /* HT. */
+ /* Bit 7 set means HT MCS instead of rate. */
+ tap->wr_rate = rate;
+ if (!(ds->ds_status3 & AR_RXS3_GI))
+ tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
+
+ } else if (rate & 0x10) { /* CCK. */
+ if (rate & 0x04)
+ tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ switch (rate & ~0x14) {
+ case 0xb: tap->wr_rate = 2; break;
+ case 0xa: tap->wr_rate = 4; break;
+ case 0x9: tap->wr_rate = 11; break;
+ case 0x8: tap->wr_rate = 22; break;
+ }
+ } else { /* OFDM. */
+ switch (rate) {
+ case 0xb: tap->wr_rate = 12; break;
+ case 0xf: tap->wr_rate = 18; break;
+ case 0xa: tap->wr_rate = 24; break;
+ case 0xe: tap->wr_rate = 36; break;
+ case 0x9: tap->wr_rate = 48; break;
+ case 0xd: tap->wr_rate = 72; break;
+ case 0x8: tap->wr_rate = 96; break;
+ case 0xc: tap->wr_rate = 108; break;
+ }
+ }
+ mb.m_data = (caddr_t)tap;
+ mb.m_len = sc->sc_rxtap_len;
+ mb.m_next = m;
+ mb.m_nextpkt = NULL;
+ mb.m_type = 0;
+ mb.m_flags = 0;
+ bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
+}
+#endif
+
+static __inline int
+athn_rx_process(struct athn_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &ic->ic_if;
+ struct athn_rxq *rxq = &sc->rxq;
+ struct athn_rx_buf *bf, *nbf;
+ struct ar_rx_desc *ds;
+ struct ieee80211_frame *wh;
+ struct ieee80211_rxinfo rxi;
+ struct ieee80211_node *ni;
+ struct mbuf *m, *m1;
+ int error, len;
+
+ bf = SIMPLEQ_FIRST(&rxq->head);
+ if (__predict_false(bf == NULL)) { /* Should not happen. */
+ printf("%s: Rx queue is empty!\n", sc->sc_dev.dv_xname);
+ return (ENOENT);
+ }
+ ds = bf->bf_desc;
+
+ if (!(ds->ds_status8 & AR_RXS8_DONE)) {
+ /*
+ * On some parts, the status words can get corrupted
+ * (including the "done" bit), so we check the next
+ * descriptor "done" bit. If it is set, it is a good
+ * indication that the status words are corrupted, so
+ * we skip this descriptor and drop the frame.
+ */
+ nbf = SIMPLEQ_NEXT(bf, bf_list);
+ if (nbf != NULL &&
+ (nbf->bf_desc->ds_status8 & AR_RXS8_DONE)) {
+ DPRINTF(("corrupted descriptor status=0x%x\n",
+ ds->ds_status8));
+ /* HW will not "move" RXDP in this case, so do it. */
+ AR_WRITE(sc, AR_RXDP, nbf->bf_daddr);
+ ifp->if_ierrors++;
+ goto skip;
+ }
+ return (EBUSY);
+ }
+
+ if (__predict_false(ds->ds_status1 & AR_RXS1_MORE)) {
+ /* Drop frames that span multiple Rx descriptors. */
+ DPRINTF(("dropping split frame\n"));
+ ifp->if_ierrors++;
+ goto skip;
+ }
+ if (!(ds->ds_status8 & AR_RXS8_FRAME_OK)) {
+ if (ds->ds_status8 & AR_RXS8_CRC_ERR)
+ DPRINTFN(6, ("CRC error\n"));
+ else if (ds->ds_status8 & AR_RXS8_PHY_ERR)
+ DPRINTFN(6, ("PHY error=0x%x\n",
+ MS(ds->ds_status8, AR_RXS8_PHY_ERR_CODE)));
+ else if (ds->ds_status8 & AR_RXS8_DECRYPT_CRC_ERR)
+ DPRINTFN(6, ("Decryption CRC error\n"));
+ else if (ds->ds_status8 & AR_RXS8_MICHAEL_ERR) {
+ DPRINTFN(2, ("Michael MIC failure\n"));
+ /* Report Michael MIC failures to net80211. */
+ ic->ic_stats.is_rx_locmicfail++;
+ ieee80211_michael_mic_failure(ic, 0);
+ /*
+ * XXX Check that it is not a control frame
+ * (invalid MIC failures on valid ctl frames.)
+ */
+ }
+ ifp->if_ierrors++;
+ goto skip;
+ }
+
+ len = MS(ds->ds_status1, AR_RXS1_DATA_LEN);
+ if (__predict_false(len == 0 || len > ATHN_RXBUFSZ)) {
+ DPRINTF(("corrupted descriptor length=%d\n", len));
+ ifp->if_ierrors++;
+ goto skip;
+ }
+
+ /* Allocate a new Rx buffer. */
+ m1 = MCLGETI(NULL, M_DONTWAIT, NULL, ATHN_RXBUFSZ);
+ if (__predict_false(m1 == NULL)) {
+ ic->ic_stats.is_rx_nombuf++;
+ ifp->if_ierrors++;
+ goto skip;
+ }
+
+ /* Sync and unmap the old Rx buffer. */
+ bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, ATHN_RXBUFSZ,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmat, bf->bf_map);
+
+ /* Map the new Rx buffer. */
+ error = bus_dmamap_load(sc->sc_dmat, bf->bf_map, mtod(m1, void *),
+ ATHN_RXBUFSZ, NULL, BUS_DMA_NOWAIT | BUS_DMA_READ);
+ if (__predict_false(error != 0)) {
+ m_freem(m1);
+
+ /* Remap the old Rx buffer or panic. */
+ error = bus_dmamap_load(sc->sc_dmat, bf->bf_map,
+ mtod(bf->bf_m, void *), ATHN_RXBUFSZ, NULL,
+ BUS_DMA_NOWAIT | BUS_DMA_READ);
+ KASSERT(error != 0);
+ ifp->if_ierrors++;
+ goto skip;
+ }
+
+ bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, bf->bf_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
+
+ /* Write physical address of new Rx buffer. */
+ ds->ds_data = bf->bf_map->dm_segs[0].ds_addr;
+
+ m = bf->bf_m;
+ bf->bf_m = m1;
+
+ /* Finalize mbuf. */
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = len;
+
+ /* Grab a reference to the source node. */
+ wh = mtod(m, struct ieee80211_frame *);
+ ni = ieee80211_find_rxnode(ic, wh);
+
+ /* Remove any HW padding after the 802.11 header. */
+ if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL)) {
+ u_int hdrlen = ieee80211_get_hdrlen(wh);
+ if (hdrlen & 3) {
+ ovbcopy(wh, (caddr_t)wh + 2, hdrlen);
+ m_adj(m, 2); /* XXX sure? */
+ }
+ }
+#if NBPFILTER > 0
+ if (__predict_false(sc->sc_drvbpf != NULL))
+ athn_rx_radiotap(sc, m, ds);
+#endif
+ /* Trim 802.11 FCS after radiotap. */
+ m_adj(m, -IEEE80211_CRC_LEN);
+
+ /* Send the frame to the 802.11 layer. */
+ rxi.rxi_flags = 0; /* XXX */
+ rxi.rxi_rssi = MS(ds->ds_status4, AR_RXS4_RSSI_COMBINED);
+ rxi.rxi_tstamp = ds->ds_status2;
+ ieee80211_input(ifp, m, ni, &rxi);
+
+ /* Node is no longer needed. */
+ ieee80211_release_node(ic, ni);
+
+ skip:
+ /* Unlink this descriptor from head. */
+ SIMPLEQ_REMOVE_HEAD(&rxq->head, bf_list);
+ memset(&ds->ds_status0, 0, 36); /* XXX Really needed? */
+ ds->ds_status8 &= ~AR_RXS8_DONE;
+ ds->ds_link = 0;
+
+ /* Re-use this descriptor and link it to tail. */
+ if (__predict_true(!SIMPLEQ_EMPTY(&rxq->head)))
+ rxq->lastds->ds_link = bf->bf_daddr;
+ else
+ AR_WRITE(sc, AR_RXDP, bf->bf_daddr);
+ SIMPLEQ_INSERT_TAIL(&rxq->head, bf, bf_list);
+ rxq->lastds = ds;
+
+ /* Re-enable Rx. */
+ AR_WRITE(sc, AR_CR, AR_CR_RXE);
+ return (0);
+}
+
+void
+athn_rx_intr(struct athn_softc *sc)
+{
+ while (athn_rx_process(sc) == 0);
+}
+
+int
+athn_tx_process(struct athn_softc *sc, int qid)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &ic->ic_if;
+ struct athn_txq *txq = &sc->txq[qid];
+ struct athn_node *an;
+ struct athn_tx_buf *bf;
+ struct ar_tx_desc *ds;
+ uint8_t failcnt;
+
+ bf = SIMPLEQ_FIRST(&txq->head);
+ if (__predict_false(bf == NULL))
+ return (ENOENT);
+ /* Get descriptor of last DMA segment. */
+ ds = &bf->bf_descs[bf->bf_map->dm_nsegs - 1];
+
+ if (!(ds->ds_status9 & AR_TXS9_DONE))
+ return (EBUSY);
+
+ SIMPLEQ_REMOVE_HEAD(&txq->head, bf_list);
+ ifp->if_opackets++;
+
+ sc->sc_tx_timer = 0;
+
+ if (ds->ds_status1 & AR_TXS1_EXCESSIVE_RETRIES)
+ ifp->if_oerrors++;
+
+ if (ds->ds_status1 & AR_TXS1_UNDERRUN)
+ athn_inc_tx_trigger_level(sc);
+
+ an = (struct athn_node *)bf->bf_ni;
+ /*
+ * NB: the data fail count contains the number of un-acked tries
+ * for the final series used. We must add the number of tries for
+ * each series that was fully processed.
+ */
+ failcnt = MS(ds->ds_status1, AR_TXS1_DATA_FAIL_CNT);
+ /* XXX Assume one single try per series. */
+ failcnt += MS(ds->ds_status9, AR_TXS9_FINAL_IDX);
+
+ /* Update rate control statistics. */
+ an->amn.amn_txcnt++;
+ if (failcnt > 0)
+ an->amn.amn_retrycnt++;
+
+ DPRINTFN(6, ("Tx done qid=%d status1=%d fail count=%d\n",
+ qid, ds->ds_status1, failcnt));
+
+ bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, bf->bf_map->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, bf->bf_map);
+
+ m_freem(bf->bf_m);
+ bf->bf_m = NULL;
+ ieee80211_release_node(ic, bf->bf_ni);
+ bf->bf_ni = NULL;
+
+ /* Link Tx buffer back to global free list. */
+ SIMPLEQ_INSERT_TAIL(&sc->txbufs, bf, bf_list);
+ return (0);
+}
+
+void
+athn_tx_intr(struct athn_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &ic->ic_if;
+ uint16_t mask = 0;
+ uint32_t reg;
+ int qid;
+
+ reg = AR_READ(sc, AR_ISR_S0_S);
+ mask |= MS(reg, AR_ISR_S0_QCU_TXOK);
+ mask |= MS(reg, AR_ISR_S0_QCU_TXDESC);
+
+ reg = AR_READ(sc, AR_ISR_S1_S);
+ mask |= MS(reg, AR_ISR_S1_QCU_TXERR);
+ mask |= MS(reg, AR_ISR_S1_QCU_TXEOL);
+
+ DPRINTFN(5, ("Tx interrupt mask=0x%x\n", mask));
+ for (qid = 0; mask != 0; mask >>= 1, qid++) {
+ if (mask & 1)
+ while (athn_tx_process(sc, qid) == 0);
+ }
+ if (!SIMPLEQ_EMPTY(&sc->txbufs)) {
+ ifp->if_flags &= ~IFF_OACTIVE;
+ athn_start(ifp);
+ }
+}
+
+int
+athn_txtime(struct athn_softc *sc, int len, int ridx, u_int flags)
+{
+#define divround(a, b) (((a) + (b) - 1) / (b))
+ int txtime;
+
+ /* XXX HT. */
+ if (athn_rates[ridx].phy == IEEE80211_T_OFDM) {
+ txtime = divround(8 + 4 * len + 3, athn_rates[ridx].rate);
+ txtime = 16 + 4 + 4 * txtime + 6;
+ } else {
+ txtime = divround(16 * len, athn_rates[ridx].rate);
+ if (ridx != ATHN_RIDX_CCK1 && (flags & IEEE80211_F_SHPREAMBLE))
+ txtime += 72 + 24;
+ else
+ txtime += 144 + 48;
+ }
+ return (txtime);
+#undef divround
+}
+
+int
+athn_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_key *k = NULL;
+ struct ieee80211_frame *wh;
+ struct athn_series series[4];
+ struct ar_tx_desc *ds, *lastds;
+ struct athn_txq *txq;
+ struct athn_tx_buf *bf;
+ struct athn_node *an = (void *)ni;
+ struct mbuf *m1;
+ uintptr_t entry;
+ uint16_t qos;
+ uint8_t txpower, type, encrtype, tid, ridx[4];
+ int i, error, totlen, hasqos, qid;
+
+ /* Grab a Tx buffer from our global free list. */
+ bf = SIMPLEQ_FIRST(&sc->txbufs);
+ KASSERT(bf != NULL);
+ SIMPLEQ_REMOVE_HEAD(&sc->txbufs, bf_list);
+
+ /* Map 802.11 frame type to hardware frame type. */
+ wh = mtod(m, struct ieee80211_frame *);
+ if ((wh->i_fc[0] &
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
+ (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON))
+ type = AR_FRAME_TYPE_BEACON;
+ else if ((wh->i_fc[0] &
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
+ (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
+ type = AR_FRAME_TYPE_PROBE_RESP;
+ else if ((wh->i_fc[0] &
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
+ (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ATIM))
+ type = AR_FRAME_TYPE_ATIM;
+ else if ((wh->i_fc[0] &
+ (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
+ (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL))
+ type = AR_FRAME_TYPE_PSPOLL;
+ else
+ type = AR_FRAME_TYPE_NORMAL;
+
+ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ k = ieee80211_get_txkey(ic, wh, ni);
+ if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
+ return (ENOBUFS);
+ wh = mtod(m, struct ieee80211_frame *);
+ }
+
+ /* XXX 2-byte padding for QoS and 4-addr headers. */
+
+ /* Select the HW Tx queue to use for this frame. */
+ if ((hasqos = ieee80211_has_qos(wh))) {
+ qos = ieee80211_get_qos(wh);
+ tid = qos & IEEE80211_QOS_TID;
+ qid = athn_ac2qid[ieee80211_up_to_ac(ic, tid)];
+ } else if (type == AR_FRAME_TYPE_BEACON) {
+ qid = ATHN_QID_BEACON;
+ } else if (type == AR_FRAME_TYPE_PSPOLL) {
+ qid = ATHN_QID_PSPOLL;
+ } else
+ qid = ATHN_QID_AC_BE;
+ txq = &sc->txq[qid];
+
+ /* Select the transmit rates to use for this frame. */
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
+ (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
+ IEEE80211_FC0_TYPE_DATA) {
+ /* Use lowest rate for all tries. */
+ ridx[0] = ridx[1] = ridx[2] = ridx[3] =
+ (ic->ic_curmode == IEEE80211_MODE_11A) ?
+ ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK1;
+ } else if (ic->ic_fixed_rate != -1) {
+ /* Use same fixed rate for all tries. */
+ ridx[0] = ridx[1] = ridx[2] = ridx[3] =
+ sc->fixed_ridx;
+ } else {
+ int txrate = ni->ni_txrate;
+ /* Use fallback table of the node. */
+ for (i = 0; i < 4; i++) {
+ ridx[i] = an->ridx[txrate];
+ txrate = an->fallback[txrate];
+ }
+ }
+
+#if NBPFILTER > 0
+ if (__predict_false(sc->sc_drvbpf != NULL)) {
+ struct athn_tx_radiotap_header *tap = &sc->sc_txtap;
+ struct mbuf mb;
+
+ tap->wt_flags = 0;
+ /* Use initial transmit rate. */
+ tap->wt_rate = athn_rates[ridx[0]].rate;
+ tap->wt_chan_freq = htole16(ic->ic_bss->ni_chan->ic_freq);
+ tap->wt_chan_flags = htole16(ic->ic_bss->ni_chan->ic_flags);
+ tap->wt_hwqueue = qid;
+ if (ridx[0] != ATHN_RIDX_CCK1 &&
+ (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
+ tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+ mb.m_data = (caddr_t)tap;
+ mb.m_len = sc->sc_txtap_len;
+ mb.m_next = m;
+ mb.m_nextpkt = NULL;
+ mb.m_type = 0;
+ mb.m_flags = 0;
+ bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
+ }
+#endif
+
+ /* DMA map mbuf. */
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_map, m,
+ BUS_DMA_NOWAIT | BUS_DMA_WRITE);
+ if (__predict_false(error != 0)) {
+ if (error != EFBIG) {
+ printf("%s: can't map mbuf (error %d)\n",
+ sc->sc_dev.dv_xname, error);
+ m_freem(m);
+ return (error);
+ }
+ /*
+ * DMA mapping requires too many DMA segments; linearize
+ * mbuf in kernel virtual address space and retry.
+ */
+ MGETHDR(m1, M_DONTWAIT, MT_DATA);
+ if (m1 == NULL) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ if (m->m_pkthdr.len > MHLEN) {
+ MCLGET(m1, M_DONTWAIT);
+ if (!(m1->m_flags & M_EXT)) {
+ m_freem(m);
+ m_freem(m1);
+ return (ENOBUFS);
+ }
+ }
+ m_copydata(m, 0, m->m_pkthdr.len, mtod(m1, caddr_t));
+ m1->m_pkthdr.len = m1->m_len = m->m_pkthdr.len;
+ m_freem(m);
+ m = m1;
+
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_map, m,
+ BUS_DMA_NOWAIT | BUS_DMA_WRITE);
+ if (error != 0) {
+ printf("%s: can't map mbuf (error %d)\n",
+ sc->sc_dev.dv_xname, error);
+ m_freem(m);
+ return (error);
+ }
+ }
+ bf->bf_m = m;
+ bf->bf_ni = ni;
+
+ wh = mtod(m, struct ieee80211_frame *);
+
+ totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
+
+ /* Clear all Tx descriptors that we will use. */
+ memset(bf->bf_descs, 0, bf->bf_map->dm_nsegs * sizeof (*ds));
+
+ /* Setup first Tx descriptor. */
+ ds = &bf->bf_descs[0];
+
+ ds->ds_ctl0 = AR_TXC0_INTR_REQ | AR_TXC0_CLR_DEST_MASK;
+ txpower = AR_MAX_RATE_POWER; /* Get from per-rate registers. */
+ ds->ds_ctl0 |= SM(AR_TXC0_XMIT_POWER, txpower);
+
+ ds->ds_ctl1 = SM(AR_TXC1_FRAME_TYPE, type);
+
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
+ (hasqos && (qos & IEEE80211_QOS_ACK_POLICY_MASK) ==
+ IEEE80211_QOS_ACK_POLICY_NOACK))
+ ds->ds_ctl1 |= AR_TXC1_NO_ACK;
+
+ if (0 && wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ /* Retrieve key for encryption. */
+ k = ieee80211_get_txkey(ic, wh, ni);
+ /*
+ * Map 802.11 cipher to hardware encryption type and
+ * compute crypto overhead.
+ */
+ switch (k->k_cipher) {
+ case IEEE80211_CIPHER_WEP40:
+ case IEEE80211_CIPHER_WEP104:
+ encrtype = AR_ENCR_TYPE_WEP;
+ totlen += 8;
+ break;
+ case IEEE80211_CIPHER_TKIP:
+ encrtype = AR_ENCR_TYPE_TKIP;
+ totlen += 20;
+ break;
+ case IEEE80211_CIPHER_CCMP:
+ encrtype = AR_ENCR_TYPE_AES;
+ totlen += 16;
+ break;
+ default:
+ panic("unsupported cipher"); /* XXX BIP? */
+ }
+ /*
+ * NB: The key cache entry index is stored in the key
+ * private field when the key is installed.
+ */
+ entry = (uintptr_t)k->k_priv;
+ ds->ds_ctl1 |= SM(AR_TXC1_DEST_IDX, entry);
+ ds->ds_ctl0 |= AR_TXC0_DEST_IDX_VALID;
+ } else
+ encrtype = AR_ENCR_TYPE_CLEAR;
+ ds->ds_ctl6 = SM(AR_TXC6_ENCR_TYPE, encrtype);
+
+ /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
+ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+ /* NB: Group frames are sent using CCK in 802.11b/g. */
+ if (totlen > ic->ic_rtsthreshold) {
+ ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE;
+ } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
+ ATHN_IS_OFDM_RIDX(ridx[0])) {
+ if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
+ ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE;
+ else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
+ ds->ds_ctl0 |= AR_TXC0_CTS_ENABLE;
+ }
+ }
+
+ /* Setup multi-rate retries. */
+ for (i = 0; i < 4; i++) {
+ series[i].tries = 1; /* XXX more for last. */
+ series[i].hwrate = athn_rates[ridx[i]].hwrate;
+ if (athn_rates[ridx[i]].phy == IEEE80211_T_DS &&
+ ridx[i] != ATHN_RIDX_CCK1 &&
+ (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
+ series[i].hwrate |= 0x04;
+ series[i].dur = 0;
+ }
+ if (!(ds->ds_ctl1 & AR_TXC1_NO_ACK)) {
+ /* Compute duration for each series. */
+ for (i = 0; i < 4; i++) {
+ series[i].dur = athn_txtime(sc, IEEE80211_ACK_LEN,
+ ridx[i], ic->ic_flags);
+ }
+ }
+
+ /* Write number of tries for each series. */
+ ds->ds_ctl2 =
+ SM(AR_TXC2_XMIT_DATA_TRIES0, series[0].tries) |
+ SM(AR_TXC2_XMIT_DATA_TRIES1, series[1].tries) |
+ SM(AR_TXC2_XMIT_DATA_TRIES2, series[2].tries) |
+ SM(AR_TXC2_XMIT_DATA_TRIES3, series[3].tries);
+
+ /* Tell HW to update duration field in 802.11 header. */
+ if (type != AR_FRAME_TYPE_PSPOLL)
+ ds->ds_ctl2 |= AR_TXC2_DUR_UPDATE_ENA;
+
+ /* Write Tx rate for each series. */
+ ds->ds_ctl3 =
+ SM(AR_TXC3_XMIT_RATE0, series[0].hwrate) |
+ SM(AR_TXC3_XMIT_RATE1, series[1].hwrate) |
+ SM(AR_TXC3_XMIT_RATE2, series[2].hwrate) |
+ SM(AR_TXC3_XMIT_RATE3, series[3].hwrate);
+
+ /* Write duration for each series. */
+ ds->ds_ctl4 =
+ SM(AR_TXC4_PACKET_DUR0, series[0].dur) |
+ SM(AR_TXC4_PACKET_DUR1, series[1].dur);
+ ds->ds_ctl5 =
+ SM(AR_TXC5_PACKET_DUR2, series[2].dur) |
+ SM(AR_TXC5_PACKET_DUR3, series[3].dur);
+
+ /* Use the same Tx chains for all tries. */
+ ds->ds_ctl7 =
+ SM(AR_TXC7_CHAIN_SEL0, sc->txchainmask) |
+ SM(AR_TXC7_CHAIN_SEL1, sc->txchainmask) |
+ SM(AR_TXC7_CHAIN_SEL2, sc->txchainmask) |
+ SM(AR_TXC7_CHAIN_SEL3, sc->txchainmask);
+#ifdef notyet
+#ifndef IEEE80211_NO_HT
+ /* Use the same short GI setting for all tries. */
+ if (ic->ic_flags & IEEE80211_F_SHGI)
+ ds->ds_ctl7 |= AR_TXC7_GI0123;
+ /* Use the same channel width for all tries. */
+ if (ic->ic_flags & IEEE80211_F_CBW40)
+ ds->ds_ctl7 |= AR_TXC7_2040_0123;
+#endif
+#endif
+
+ if (ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE)) {
+ /* Use the same protection mode for all tries. */
+ if (ds->ds_ctl0 & AR_TXC0_RTS_ENABLE) {
+ ds->ds_ctl4 |= AR_TXC4_RTSCTS_QUAL01;
+ ds->ds_ctl5 |= AR_TXC5_RTSCTS_QUAL23;
+ }
+ /* Write protection frame duration and rate. */
+ ds->ds_ctl2 |= SM(AR_TXC2_BURST_DUR, 0 /* XXX */);
+ ds->ds_ctl7 |= SM(AR_TXC7_RTSCTS_RATE,
+ athn_rates[0].hwrate /* XXX */);
+ /* XXX short preamble. */
+ }
+
+ /* 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++) {
+ ds->ds_data = bf->bf_map->dm_segs[i].ds_addr;
+ ds->ds_ctl1 |= SM(AR_TXC1_BUF_LEN,
+ bf->bf_map->dm_segs[i].ds_len);
+
+ if (i != bf->bf_map->dm_nsegs - 1)
+ ds->ds_ctl1 |= AR_TXC1_MORE;
+ ds->ds_link = 0;
+
+ /* Chain Tx descriptor. */
+ if (i != 0)
+ lastds->ds_link = bf->bf_daddr + i * sizeof (*ds);
+ lastds = ds;
+ }
+ if (txq->lastds != NULL)
+ txq->lastds->ds_link = bf->bf_daddr;
+ else
+ AR_WRITE(sc, AR_QTXDP(qid), bf->bf_daddr);
+ txq->lastds = lastds;
+ SIMPLEQ_INSERT_TAIL(&txq->head, bf, bf_list);
+
+ DPRINTFN(4, ("Tx qid=%d nsegs=%d ctl0=0x%x ctl1=0x%x ctl3=0x%x\n",
+ qid, bf->bf_map->dm_nsegs, bf->bf_descs[0].ds_ctl0,
+ bf->bf_descs[0].ds_ctl1, bf->bf_descs[0].ds_ctl3));
+
+ bus_dmamap_sync(sc->sc_dmat, bf->bf_map, 0, bf->bf_map->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
+
+ /* Kick Tx. */
+ AR_WRITE(sc, AR_Q_TXE, 1 << qid);
+ return (0);
+}
+
+void
+athn_init_tx_queues(struct athn_softc *sc)
+{
+ int qid;
+
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++) {
+ SIMPLEQ_INIT(&sc->txq[qid].head);
+ sc->txq[qid].lastds = NULL;
+
+ AR_WRITE(sc, AR_DRETRY_LIMIT(qid),
+ SM(AR_D_RETRY_LIMIT_STA_SH, 32) |
+ SM(AR_D_RETRY_LIMIT_STA_LG, 32) |
+ SM(AR_D_RETRY_LIMIT_FR_SH, 10));
+ AR_WRITE(sc, AR_QMISC(qid),
+ AR_Q_MISC_DCU_EARLY_TERM_REQ);
+ AR_WRITE(sc, AR_DMISC(qid),
+ SM(AR_D_MISC_BKOFF_THRESH, 2) |
+ AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN);
+ }
+
+ /* Init beacon queue. */
+ AR_SETBITS(sc, AR_QMISC(ATHN_QID_BEACON),
+ AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_BEACON_USE |
+ AR_Q_MISC_CBR_INCR_DIS1);
+ AR_SETBITS(sc, AR_DMISC(ATHN_QID_BEACON),
+ SM(AR_D_MISC_ARB_LOCKOUT_CNTRL,
+ AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL) |
+ AR_D_MISC_BEACON_USE |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+
+ /* Init CAB queue. */
+ AR_SETBITS(sc, AR_QMISC(ATHN_QID_CAB),
+ AR_Q_MISC_FSP_DBA_GATED | AR_Q_MISC_CBR_INCR_DIS1 |
+ AR_Q_MISC_CBR_INCR_DIS0);
+ AR_SETBITS(sc, AR_DMISC(ATHN_QID_CAB),
+ SM(AR_D_MISC_ARB_LOCKOUT_CNTRL,
+ AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL));
+
+ /* Init PS-Poll queue. */
+ AR_SETBITS(sc, AR_QMISC(ATHN_QID_PSPOLL),
+ AR_Q_MISC_CBR_INCR_DIS1);
+
+ /* Init UAPSD queue. */
+ AR_SETBITS(sc, AR_DMISC(ATHN_QID_UAPSD),
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+
+ /* Enable DESC interrupts for all Tx queues. */
+ AR_WRITE(sc, AR_IMR_S0, 0x00ff0000);
+ /* Enable EOL interrupts for all Tx queues except UAPSD. */
+ AR_WRITE(sc, AR_IMR_S1, 0x00df0000);
+}
+
+void
+athn_set_viterbi_mask(struct athn_softc *sc, int bin)
+{
+ uint32_t mask[4], reg;
+ uint8_t m[62], p[62]; /* XXX use bit arrays? */
+ int i, bit, cur;
+
+ /* Compute pilot mask. */
+ cur = -6000;
+ for (i = 0; i < 4; i++) {
+ mask[i] = 0;
+ for (bit = 0; bit < 30; bit++) {
+ if (abs(cur - bin) < 100)
+ mask[i] |= 1 << bit;
+ cur += 100;
+ }
+ if (cur == 0) /* Skip entry "0". */
+ cur = 100;
+ }
+ /* Write entries from -6000 to -3100. */
+ AR_WRITE(sc, AR_PHY_TIMING7, mask[0]);
+ AR_WRITE(sc, AR_PHY_TIMING9, mask[0]);
+ /* Write entries from -3000 to -100. */
+ AR_WRITE(sc, AR_PHY_TIMING8, mask[1]);
+ AR_WRITE(sc, AR_PHY_TIMING10, mask[1]);
+ /* Write entries from 100 to 3000. */
+ AR_WRITE(sc, AR_PHY_PILOT_MASK_01_30, mask[2]);
+ AR_WRITE(sc, AR_PHY_CHANNEL_MASK_01_30, mask[2]);
+ /* Write entries from 3100 to 6000. */
+ AR_WRITE(sc, AR_PHY_PILOT_MASK_31_60, mask[3]);
+ AR_WRITE(sc, AR_PHY_CHANNEL_MASK_31_60, mask[3]);
+
+ /* Compute viterbi mask. */
+ for (cur = 6100; cur >= 0; cur -= 100)
+ p[+cur / 100] = abs(cur - bin) < 75;
+ for (cur = -100; cur >= -6100; cur -= 100)
+ m[-cur / 100] = abs(cur - bin) < 75;
+
+ /* 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 |
+ m[54] << 14 | m[55] << 12 | m[56] << 10 | m[57] << 8 |
+ m[58] << 6 | m[59] << 4 | m[60] << 2 | m[61] << 0;
+ AR_WRITE(sc, AR_PHY_BIN_MASK_1, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_M_46_61, reg);
+
+ /* XXX m[48] should be m[38] ? */
+ reg = m[31] << 28 | m[32] << 26 | m[33] << 24 |
+ m[34] << 22 | m[35] << 20 | m[36] << 18 | m[37] << 16 |
+ m[48] << 14 | m[39] << 12 | m[40] << 10 | m[41] << 8 |
+ m[42] << 6 | m[43] << 4 | m[44] << 2 | m[45] << 0;
+ AR_WRITE(sc, AR_PHY_BIN_MASK_2, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_M_31_45, reg);
+
+ /* XXX This one is weird too. */
+ reg =
+ m[16] << 30 | m[16] << 28 | m[18] << 26 | m[18] << 24 |
+ m[20] << 22 | m[20] << 20 | m[22] << 18 | m[22] << 16 |
+ m[24] << 14 | m[24] << 12 | m[25] << 10 | m[26] << 8 |
+ m[27] << 6 | m[28] << 4 | m[29] << 2 | m[30] << 0;
+ AR_WRITE(sc, AR_PHY_BIN_MASK_3, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_M_16_30, reg);
+
+ reg =
+ m[ 0] << 30 | m[ 1] << 28 | m[ 2] << 26 | m[ 3] << 24 |
+ m[ 4] << 22 | m[ 5] << 20 | m[ 6] << 18 | m[ 7] << 16 |
+ m[ 8] << 14 | m[ 9] << 12 | m[10] << 10 | m[11] << 8 |
+ m[12] << 6 | m[13] << 4 | m[14] << 2 | m[15] << 0;
+ AR_WRITE(sc, AR_PHY_MASK_CTL, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_M_00_15, reg);
+
+ reg = p[15] << 28 | p[14] << 26 | p[13] << 24 |
+ p[12] << 22 | p[11] << 20 | p[10] << 18 | p[ 9] << 16 |
+ p[ 8] << 14 | p[ 7] << 12 | p[ 6] << 10 | p[ 5] << 8 |
+ p[ 4] << 6 | p[ 3] << 4 | p[ 2] << 2 | p[ 1] << 0;
+ AR_WRITE(sc, AR_PHY_BIN_MASK2_1, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_P_15_01, reg);
+
+ reg = p[30] << 28 | p[29] << 26 | p[28] << 24 |
+ p[27] << 22 | p[26] << 20 | p[25] << 18 | p[24] << 16 |
+ p[23] << 14 | p[22] << 12 | p[21] << 10 | p[20] << 8 |
+ p[19] << 6 | p[18] << 4 | p[17] << 2 | p[16] << 0;
+ AR_WRITE(sc, AR_PHY_BIN_MASK2_2, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_P_30_16, reg);
+
+ reg = p[45] << 28 | p[44] << 26 | p[43] << 24 |
+ p[42] << 22 | p[41] << 20 | p[40] << 18 | p[39] << 16 |
+ p[38] << 14 | p[37] << 12 | p[36] << 10 | p[35] << 8 |
+ p[34] << 6 | p[33] << 4 | p[32] << 2 | p[31] << 0;
+ AR_WRITE(sc, AR_PHY_BIN_MASK2_3, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_P_45_31, reg);
+
+ reg =
+ p[61] << 30 | p[60] << 28 | p[59] << 26 | p[58] << 24 |
+ p[57] << 22 | p[56] << 20 | p[55] << 18 | p[54] << 16 |
+ p[53] << 14 | p[52] << 12 | p[51] << 10 | p[50] << 8 |
+ p[49] << 6 | p[48] << 4 | p[47] << 2 | p[46] << 0;
+ AR_WRITE(sc, AR_PHY_BIN_MASK2_4, reg);
+ AR_WRITE(sc, AR_PHY_VIT_MASK2_P_61_46, reg);
+}
+
+void
+athn_set_beacon_timers(struct athn_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni = ic->ic_bss;
+ uint32_t tsfhi, tsflo, tsftu, reg;
+ uint32_t intval, next_tbtt, next_dtim;
+ int dtim_period, dtim_count, rem_dtim_count;
+
+ tsfhi = AR_READ(sc, AR_TSF_U32);
+ tsflo = AR_READ(sc, AR_TSF_L32);
+ tsftu = AR_TSF_TO_TU(tsfhi, tsflo) + AR_FUDGE;
+
+ /* Beacon interval in TU. */
+ intval = ni->ni_intval;
+
+ next_tbtt = roundup(tsftu, intval);
+#ifdef notyet
+ dtim_period = ic->ic_dtim_period;
+ if (dtim_period <= 0)
+#endif
+ dtim_period = 1; /* Assume all TIMs are DTIMs. */
+
+#ifdef notyet
+ dtim_count = ic->ic_dtim_count;
+ if (dtim_count >= dtim_period) /* Should not happen. */
+#endif
+ dtim_count = 0; /* Assume last TIM was a DTIM. */
+
+ /* Compute number of remaining TIMs until next DTIM. */
+ rem_dtim_count = 0; /* XXX */
+ next_dtim = next_tbtt + rem_dtim_count * intval;
+
+ AR_WRITE(sc, AR_NEXT_TBTT_TIMER, next_tbtt * IEEE80211_DUR_TU);
+ AR_WRITE(sc, AR_BEACON_PERIOD, intval * IEEE80211_DUR_TU);
+ AR_WRITE(sc, AR_DMA_BEACON_PERIOD, intval * IEEE80211_DUR_TU);
+
+ /*
+ * Set the number of consecutive beacons to miss before raising
+ * a BMISS interrupt to 10.
+ */
+ reg = AR_READ(sc, AR_RSSI_THR);
+ reg = RW(reg, AR_RSSI_THR_BM_THR, 10);
+ AR_WRITE(sc, AR_RSSI_THR, reg);
+
+ AR_WRITE(sc, AR_NEXT_DTIM,
+ (next_dtim - AR_SLEEP_SLOP) * IEEE80211_DUR_TU);
+ AR_WRITE(sc, AR_NEXT_TIM,
+ (next_tbtt - AR_SLEEP_SLOP) * IEEE80211_DUR_TU);
+
+ /* CAB timeout is in 1/8 TU. */
+ AR_WRITE(sc, AR_SLEEP1,
+ SM(AR_SLEEP1_CAB_TIMEOUT, AR_CAB_TIMEOUT_VAL * 8) |
+ AR_SLEEP1_ASSUME_DTIM);
+ AR_WRITE(sc, AR_SLEEP2,
+ SM(AR_SLEEP2_BEACON_TIMEOUT, AR_MIN_BEACON_TIMEOUT_VAL));
+
+ AR_WRITE(sc, AR_TIM_PERIOD, intval * IEEE80211_DUR_TU);
+ AR_WRITE(sc, AR_DTIM_PERIOD, dtim_period * IEEE80211_DUR_TU);
+
+ AR_SETBITS(sc, AR_TIMER_MODE,
+ AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | AR_DTIM_TIMER_EN);
+
+ /* Set TSF out-of-range threshold (fixed at 16k us). */
+ AR_WRITE(sc, AR_TSFOOR_THRESHOLD, 0x4240);
+}
+
+void
+athn_set_rf_mode(struct athn_softc *sc, struct ieee80211_channel *c)
+{
+ uint32_t reg;
+
+ reg = IEEE80211_IS_CHAN_2GHZ(c) ?
+ AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+ if (!AR_SREV_9280_10_OR_LATER(sc)) {
+ reg |= IEEE80211_IS_CHAN_2GHZ(c) ?
+ AR_PHY_MODE_RF2GHZ : AR_PHY_MODE_RF5GHZ;
+ } else if (AR_SREV_9280_20(sc) && 0 /* XXX */) {
+ reg |= AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE;
+ }
+ AR_WRITE(sc, AR_PHY_MODE, reg);
+}
+
+void
+athn_set_opmode(struct athn_softc *sc)
+{
+ uint32_t reg;
+
+ switch (sc->sc_ic.ic_opmode) {
+#ifndef IEEE80211_STA_ONLY
+ case IEEE80211_M_HOSTAP:
+ reg = AR_READ(sc, AR_STA_ID1);
+ reg &= ~AR_STA_ID1_ADHOC;
+ reg |= AR_STA_ID1_STA_AP | AR_STA_ID1_KSRCH_MODE;
+ AR_WRITE(sc, AR_STA_ID1, reg);
+
+ AR_CLRBITS(sc, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ break;
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
+ reg = AR_READ(sc, AR_STA_ID1);
+ reg &= ~AR_STA_ID1_STA_AP;
+ reg |= AR_STA_ID1_ADHOC | AR_STA_ID1_KSRCH_MODE;
+ AR_WRITE(sc, AR_STA_ID1, reg);
+
+ AR_SETBITS(sc, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ break;
+#endif
+ default:
+ reg = AR_READ(sc, AR_STA_ID1);
+ reg &= ~(AR_STA_ID1_ADHOC | AR_STA_ID1_STA_AP);
+ reg |= AR_STA_ID1_KSRCH_MODE;
+ AR_WRITE(sc, AR_STA_ID1, reg);
+ break;
+ }
+}
+
+void
+athn_set_bss(struct athn_softc *sc, struct ieee80211_node *ni)
+{
+ const uint8_t *bssid = ni->ni_bssid;
+
+ AR_WRITE(sc, AR_BSS_ID0, bssid[0] | bssid[1] << 8 |
+ bssid[2] << 16 | bssid[3] << 24);
+ AR_WRITE(sc, AR_BSS_ID1, bssid[4] | bssid[5] << 8 |
+ SM(AR_BSS_ID1_AID, IEEE80211_AID(ni->ni_associd)));
+}
+
+void
+athn_enable_interrupts(struct athn_softc *sc)
+{
+ uint32_t mask, mask2;
+
+ athn_disable_interrupts(sc); /* XXX */
+
+ mask = AR_IMR_TXDESC | AR_IMR_TXEOL | AR_IMR_RXERR | AR_IMR_RXEOL |
+ AR_IMR_RXORN | AR_IMR_GENTMR | AR_IMR_BCNMISC;
+#ifndef ATHN_INTR_MITIGATION
+ mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
+#else
+ mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
+#endif
+ AR_WRITE(sc, AR_IMR, mask);
+
+ mask2 = AR_READ(sc, AR_IMR_S2);
+ mask2 &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
+ AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | AR_IMR_S2_TSFOOR |
+ AR_IMR_S2_GTT | AR_IMR_S2_CST);
+ mask2 |= AR_IMR_S2_GTT | AR_IMR_S2_CST;
+ AR_WRITE(sc, AR_IMR_S2, mask2);
+
+ AR_CLRBITS(sc, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+
+ AR_WRITE(sc, AR_IER, AR_IER_ENABLE);
+
+ AR_WRITE(sc, AR_INTR_ASYNC_ENABLE, AR_INTR_MAC_IRQ);
+ AR_WRITE(sc, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+ AR_WRITE(sc, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+ AR_WRITE(sc, AR_INTR_SYNC_MASK, AR_INTR_SYNC_DEFAULT);
+}
+
+void
+athn_disable_interrupts(struct athn_softc *sc)
+{
+ AR_WRITE(sc, AR_IER, 0);
+ (void)AR_READ(sc, AR_IER);
+
+ AR_WRITE(sc, AR_INTR_ASYNC_ENABLE, 0);
+ (void)AR_READ(sc, AR_INTR_ASYNC_ENABLE);
+
+ AR_WRITE(sc, AR_INTR_SYNC_ENABLE, 0);
+ (void)AR_READ(sc, AR_INTR_SYNC_ENABLE);
+
+ AR_WRITE(sc, AR_IMR, 0);
+
+ AR_CLRBITS(sc, AR_IMR_S2, AR_IMR_S2_TIM | AR_IMR_S2_DTIM |
+ AR_IMR_S2_DTIMSYNC | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
+ AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
+
+ AR_CLRBITS(sc, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+}
+
+void
+athn_hw_init(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ struct athn_ops *ops = &sc->ops;
+ const struct athn_ini *ini = sc->ini;
+ const uint32_t *pvals;
+ int i;
+
+ AR_WRITE(sc, AR_PHY(0), 0x00000007);
+ AR_WRITE(sc, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+
+ if (!AR_SINGLE_CHIP(sc))
+ ar5416_reset_addac(sc, c);
+
+ AR_WRITE(sc, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+ /* First initialization step (depends on channel band/bandwidth). */
+#ifndef IEEE80211_NO_HT
+ if (extc != NULL) {
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ pvals = ini->vals_2g40;
+ else
+ pvals = ini->vals_5g40;
+ } else
+#endif
+ {
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ pvals = ini->vals_2g20;
+ else
+ pvals = ini->vals_5g20;
+ }
+ DPRINTF(("writing per-mode init vals\n"));
+ for (i = 0; i < ini->nregs; i++) {
+ AR_WRITE(sc, ini->regs[i], pvals[i]);
+ if (AR_IS_ANALOG_REG(ini->regs[i]))
+ DELAY(100);
+ if ((i & 0x1f) == 0)
+ DELAY(1);
+ }
+
+ if (AR_SREV_9280_20(sc) || AR_SREV_9287_10_OR_LATER(sc))
+ ar9280_reset_rx_gain(sc, c);
+ if (AR_SREV_9280_20(sc) || AR_SREV_9285_12(sc) ||
+ AR_SREV_9287_10_OR_LATER(sc))
+ ar9280_reset_tx_gain(sc, c);
+
+ /* Second initialization step (common to all channels). */
+ DPRINTF(("writing common init vals\n"));
+ for (i = 0; i < ini->ncmregs; i++) {
+ AR_WRITE(sc, ini->cmregs[i], ini->cmvals[i]);
+ if (AR_IS_ANALOG_REG(ini->cmregs[i]))
+ DELAY(100);
+ if ((i & 0x1f) == 0)
+ DELAY(1);
+ }
+
+ if (!AR_SINGLE_CHIP(sc))
+ ar5416_reset_bb_gain(sc, c);
+
+ /*
+ * Set the RX_ABORT and RX_DIS bits to prevent frames with corrupted
+ * descriptor status.
+ */
+ 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)) {
+ /* Disable baseband clock gating. */
+ AR_WRITE(sc, AR_PHY(651), 0x11);
+ }
+
+ athn_set_phy(sc, c, extc);
+ athn_init_chains(sc);
+
+ if (sc->flags & ATHN_FLAG_OLPC)
+ sc->ops.olpc_init(sc);
+
+ ops->set_txpower(sc, c, extc);
+
+ if (!AR_SINGLE_CHIP(sc))
+ ar5416_rf_reset(sc, c);
+}
+
+void
+athn_init_qos(struct athn_softc *sc)
+{
+ /* Initialize QoS settings. */
+ AR_WRITE(sc, AR_MIC_QOS_CONTROL, 0x100aa);
+ AR_WRITE(sc, AR_MIC_QOS_SELECT, 0x3210);
+ AR_WRITE(sc, AR_QOS_NO_ACK,
+ SM(AR_QOS_NO_ACK_TWO_BIT, 2) |
+ SM(AR_QOS_NO_ACK_BIT_OFF, 5) |
+ SM(AR_QOS_NO_ACK_BYTE_OFF, 0));
+ AR_WRITE(sc, AR_TXOP_X, AR_TXOP_X_VAL);
+ /* Initialize TXOP for all TIDs. */
+ AR_WRITE(sc, AR_TXOP_0_3, 0xffffffff);
+ AR_WRITE(sc, AR_TXOP_4_7, 0xffffffff);
+ AR_WRITE(sc, AR_TXOP_8_11, 0xffffffff);
+ AR_WRITE(sc, AR_TXOP_12_15, 0xffffffff);
+}
+
+int
+athn_hw_reset(struct athn_softc *sc, struct ieee80211_channel *c,
+ struct ieee80211_channel *extc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct athn_ops *ops = &sc->ops;
+ uint32_t reg, def_ant, sta_id1, cfg_led, tsflo, tsfhi;
+ int i, error;
+
+ /* XXX not if already awake */
+ if ((error = athn_set_power_awake(sc)) != 0) {
+ printf("%s: could not wakeup chip\n", sc->sc_dev.dv_xname);
+ return (error);
+ }
+
+ /* Preserve the antenna on a channel switch. */
+ if ((def_ant = AR_READ(sc, AR_DEF_ANTENNA)) == 0)
+ def_ant = 1;
+ /* Preserve other registers. */
+ sta_id1 = AR_READ(sc, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
+ cfg_led = AR_READ(sc, AR_CFG_LED) & (AR_CFG_LED_ASSOC_CTL_M |
+ AR_CFG_LED_MODE_SEL_M | AR_CFG_LED_BLINK_THRESH_SEL_M |
+ AR_CFG_LED_BLINK_SLOW);
+
+ /* Mark PHY as inactive. */
+ AR_WRITE(sc, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+
+ if (AR_SREV_9280(sc) && (sc->flags & ATHN_FLAG_OLPC)) {
+ /* Save TSF before it gets cleared. */
+ tsfhi = AR_READ(sc, AR_TSF_U32);
+ tsflo = AR_READ(sc, AR_TSF_L32);
+
+ /* NB: RTC reset clears TSF. */
+ error = athn_reset_power_on(sc);
+ } else
+ error = athn_reset(sc, 0);
+ if (error != 0) {
+ printf("%s: could not reset chip (error=%d)\n",
+ sc->sc_dev.dv_xname);
+ return (error);
+ }
+
+ /* XXX not if already awake */
+ if ((error = athn_set_power_awake(sc)) != 0) {
+ printf("%s: could not wakeup chip\n", sc->sc_dev.dv_xname);
+ return (error);
+ }
+
+ athn_init_pll(sc, c);
+ athn_set_rf_mode(sc, c);
+
+ /* XXX move to attach? */
+ if (sc->flags & ATHN_FLAG_RFSILENT)
+ athn_rfsilent_init(sc);
+
+ if (sc->flags & ATHN_FLAG_RFSILENT) {
+ /* Check that the radio is not disabled by hardware switch. */
+ reg = athn_gpio_read(sc, sc->rfsilent_pin);
+ if (sc->flags & ATHN_FLAG_RFSILENT_REVERSED)
+ reg = !reg;
+ if (!reg) {
+ printf("%s: radio is disabled by hardware switch\n",
+ sc->sc_dev.dv_xname);
+ return (EPERM);
+ }
+ }
+ if (AR_SREV_9280(sc) && (sc->flags & ATHN_FLAG_OLPC)) {
+ /* Restore TSF if it got cleared. */
+ AR_WRITE(sc, AR_TSF_L32, tsflo);
+ AR_WRITE(sc, AR_TSF_U32, tsfhi);
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(sc))
+ AR_SETBITS(sc, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
+
+ if (AR_SREV_9287_12_OR_LATER(sc))
+ ar9287_1_2_enable_async_fifo(sc);
+
+ /* Write init values to hardware. */
+ athn_hw_init(sc, c, extc);
+
+ /*
+ * Only >=AR9280 2.0 parts are capable of encrypting unicast
+ * management frames using CCMP.
+ */
+ if (AR_SREV_9280_20_OR_LATER(sc)) {
+ reg = AR_READ(sc, AR_AES_MUTE_MASK1);
+ /* Do not mask the subtype field in management frames. */
+ reg = RW(reg, AR_AES_MUTE_MASK1_FC0_MGMT, 0xff);
+ reg = RW(reg, AR_AES_MUTE_MASK1_FC1_MGMT,
+ ~(IEEE80211_FC1_RETRY | IEEE80211_FC1_PWR_MGT |
+ IEEE80211_FC1_MORE_DATA));
+ AR_WRITE(sc, AR_AES_MUTE_MASK1, reg);
+ } else if (AR_SREV_9160_10_OR_LATER(sc)) {
+ /* Disable hardware crypto for management frames. */
+ AR_CLRBITS(sc, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
+ AR_SETBITS(sc, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
+ }
+
+ if (ic->ic_curmode != IEEE80211_MODE_11B)
+ athn_set_delta_slope(sc, c, extc);
+
+ ops->spur_mitigate(sc, c, extc);
+ ops->init_from_rom(sc, c, extc);
+
+ AR_WRITE(sc, AR_STA_ID0,
+ ic->ic_myaddr[0] << 0 | ic->ic_myaddr[1] << 8 |
+ ic->ic_myaddr[2] << 16 | ic->ic_myaddr[3] << 24);
+ /* XXX */
+ AR_WRITE(sc, AR_STA_ID1,
+ ic->ic_myaddr[4] << 0 | ic->ic_myaddr[5] << 8 |
+ sta_id1 | AR_STA_ID1_RTS_USE_DEF | AR_STA_ID1_CRPT_MIC_ENABLE);
+
+ athn_set_opmode(sc);
+
+ AR_WRITE(sc, AR_BSSMSKL, 0xffffffff);
+ AR_WRITE(sc, AR_BSSMSKU, 0xffff);
+
+ /* Restore previous antenna. */
+ AR_WRITE(sc, AR_DEF_ANTENNA, def_ant);
+
+ AR_WRITE(sc, AR_BSS_ID0, 0);
+ AR_WRITE(sc, AR_BSS_ID1, 0);
+
+ AR_WRITE(sc, AR_ISR, 0xffffffff);
+
+ AR_WRITE(sc, AR_RSSI_THR, SM(AR_RSSI_THR_BM_THR, 7));
+
+ error = ops->set_synth(sc, c, extc);
+ if (error != 0) {
+ printf("%s: could not set channel\n", sc->sc_dev.dv_xname);
+ return (error);
+ }
+
+ for (i = 0; i < AR_NUM_DCU; i++)
+ AR_WRITE(sc, AR_DQCUMASK(i), 1 << i);
+
+ athn_init_tx_queues(sc);
+
+ /* Initialize interrupt mask. */
+#ifndef IEEE80211_STA_ONLY
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ AR_WRITE(sc, AR_IMR, AR_IMR_HOSTAP);
+ else
+#endif
+ AR_WRITE(sc, AR_IMR, AR_IMR_DEFAULT);
+ AR_SETBITS(sc, AR_IMR_S2, AR_IMR_S2_GTT);
+ AR_WRITE(sc, AR_INTR_SYNC_CAUSE, 0xffffffff);
+ AR_WRITE(sc, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+ AR_WRITE(sc, AR_INTR_SYNC_MASK, 0);
+
+ athn_init_qos(sc);
+
+ if (!AR_SREV_9280_10(sc))
+ AR_SETBITS(sc, AR_PCU_MISC, AR_PCU_MIC_NEW_LOC_ENA);
+
+ if (AR_SREV_9287_12_OR_LATER(sc))
+ ar9287_1_2_setup_async_fifo(sc);
+
+ /* Disable sequence number generation in hardware. */
+ AR_SETBITS(sc, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
+
+ athn_init_dma(sc);
+
+ /* Program OBS bus to see MAC interrupts. */
+ AR_WRITE(sc, AR_OBS, 8);
+
+#ifdef ATHN_INTR_MITIGATION
+ /* Setup interrupt mitigation. */
+ AR_WRITE(sc, AR_RIMT, SM(AR_RIMT_FIRST, 2000) | SM(AR_RIMT_LAST, 500));
+#endif
+
+ athn_init_baseband(sc);
+
+ if ((error = athn_init_calib(sc, c, extc)) != 0) {
+ printf("%s: could not initialize calibration\n",
+ sc->sc_dev.dv_xname);
+ return (error);
+ }
+
+ if (sc->rxchainmask == 0x3 || sc->rxchainmask == 0x5) {
+ /* XXX why again? */
+ AR_WRITE(sc, AR_PHY_RX_CHAINMASK, sc->rxchainmask);
+ AR_WRITE(sc, AR_PHY_CAL_CHAINMASK, sc->rxchainmask);
+ }
+
+ AR_WRITE(sc, AR_CFG_LED, cfg_led | AR_CFG_SCLK_32KHZ);
+
+#if BYTE_ORDER == BIG_ENDIAN
+ /* Default is little-endian, turn on swapping for big-endian. */
+ AR_WRITE(sc, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+#endif
+ return (0);
+}
+
+struct ieee80211_node *
+athn_node_alloc(struct ieee80211com *ic)
+{
+ return (malloc(sizeof (struct athn_node), M_DEVBUF,
+ M_NOWAIT | M_ZERO));
+}
+
+void
+athn_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
+{
+ struct athn_softc *sc = ic->ic_softc;
+ struct athn_node *an = (void *)ni;
+ struct ieee80211_rateset *rs = &ni->ni_rates;
+ uint8_t rate;
+ int ridx, i, j;
+
+ ieee80211_amrr_node_init(&sc->amrr, &an->amn);
+ /* Start at lowest available bit-rate, AMRR will raise. */
+ ni->ni_txrate = 0;
+
+ for (i = 0; i < rs->rs_nrates; i++) {
+ rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
+
+ /* Map 802.11 rate to HW rate index. */
+ for (ridx = 0; ridx <= ATHN_RIDX_MAX; ridx++)
+ if (athn_rates[ridx].rate == rate)
+ break;
+ an->ridx[i] = ridx;
+
+ /* Compute fallback rate for retries. */
+ an->fallback[i] = i;
+ for (j = i - 1; j >= 0; j--) {
+ if (athn_rates[an->ridx[j]].phy ==
+ athn_rates[an->ridx[i]].phy) {
+ an->fallback[i] = j;
+ break;
+ }
+ }
+#if 0
+ /* Compute rate for protection frames. */
+ an->ctlridx[i] = athn_rates[ridx].ctlridx;
+ for (j = i; j >= 0; j--) {
+ if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) &&
+ athn_rates[an->ridx[j]].phy ==
+ athn_rates[an->ridx[i]].phy) {
+ an->ctlridx[i] = an->ridx[j];
+ break;
+ }
+ }
+#endif
+ }
+}
+
+int
+athn_media_change(struct ifnet *ifp)
+{
+ struct athn_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ uint8_t rate, ridx;
+ int error;
+
+ error = ieee80211_media_change(ifp);
+ if (error != ENETRESET)
+ return (error);
+
+ if (ic->ic_fixed_rate != -1) {
+ rate = ic->ic_sup_rates[ic->ic_curmode].
+ rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
+ /* Map 802.11 rate to HW rate index. */
+ for (ridx = 0; ridx <= ATHN_RIDX_MAX; ridx++)
+ if (athn_rates[ridx].rate == rate)
+ break;
+ sc->fixed_ridx = ridx;
+ }
+ if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
+ (IFF_UP | IFF_RUNNING)) {
+ athn_stop(ifp, 0);
+ error = athn_init(ifp);
+ }
+ return (error);
+}
+
+void
+athn_next_scan(void *arg)
+{
+ struct athn_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int s;
+
+ s = splnet();
+ if (ic->ic_state == IEEE80211_S_SCAN)
+ ieee80211_next_scan(&ic->ic_if);
+ splx(s);
+}
+
+int
+athn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
+{
+ struct ifnet *ifp = &ic->ic_if;
+ struct athn_softc *sc = ifp->if_softc;
+ int error;
+
+ timeout_del(&sc->calib_to);
+
+ switch (nstate) {
+ case IEEE80211_S_INIT:
+ break;
+ case IEEE80211_S_SCAN:
+ error = athn_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
+ if (error != 0)
+ return (error);
+ timeout_add_msec(&sc->scan_to, 200);
+ break;
+ case IEEE80211_S_AUTH:
+ error = athn_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
+ if (error != 0)
+ return (error);
+ break;
+ case IEEE80211_S_ASSOC:
+ break;
+ case IEEE80211_S_RUN:
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ break;
+
+ /* Fake a join to initialize the Tx rate. */
+ athn_newassoc(ic, ic->ic_bss, 1);
+
+ athn_set_bss(sc, ic->ic_bss);
+ athn_disable_interrupts(sc);
+ athn_set_beacon_timers(sc);
+ /* XXX Enable BMISS interrupts. */
+ athn_enable_interrupts(sc);
+ /* XXX Start ANI. */
+
+ timeout_add_msec(&sc->calib_to, 500);
+ break;
+ }
+
+ return (sc->sc_newstate(ic, nstate, arg));
+}
+
+void
+athn_updateedca(struct ieee80211com *ic)
+{
+#define ATHN_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
+ struct athn_softc *sc = ic->ic_softc;
+ const struct ieee80211_edca_ac_params *ac;
+ int aci, qid;
+
+ for (aci = 0; aci < EDCA_NUM_AC; aci++) {
+ ac = &ic->ic_edca_ac[aci];
+ qid = athn_ac2qid[aci];
+
+ AR_WRITE(sc, AR_DLCL_IFS(qid),
+ SM(AR_D_LCL_IFS_CWMIN, ATHN_EXP2(ac->ac_ecwmin)) |
+ SM(AR_D_LCL_IFS_CWMAX, ATHN_EXP2(ac->ac_ecwmax)) |
+ SM(AR_D_LCL_IFS_AIFS, ac->ac_aifsn));
+ if (ac->ac_txoplimit != 0) {
+ AR_WRITE(sc, AR_DCHNTIME(qid),
+ SM(AR_D_CHNTIME_DUR,
+ IEEE80211_TXOP_TO_US(ac->ac_txoplimit)) |
+ AR_D_CHNTIME_EN);
+ } else
+ AR_WRITE(sc, AR_DCHNTIME(qid), 0);
+ }
+#undef ATHN_EXP2
+}
+
+void
+athn_updateslot(struct ieee80211com *ic)
+{
+ struct athn_softc *sc = ic->ic_softc;
+ uint32_t clks;
+
+ if (ic->ic_opmode == IEEE80211_MODE_11B)
+ clks = AR_CLOCK_RATE_CCK;
+ else if (ic->ic_opmode == IEEE80211_MODE_11A)
+ clks = AR_CLOCK_RATE_5GHZ_OFDM;
+ else
+ clks = AR_CLOCK_RATE_2GHZ_OFDM;
+ clks *= (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
+
+ /* XXX 40MHz. */
+
+ AR_WRITE(sc, AR_D_GBL_IFS_SLOT, clks);
+}
+
+void
+athn_start(struct ifnet *ifp)
+{
+ struct athn_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni;
+ struct mbuf *m;
+
+ if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
+ return;
+
+ for (;;) {
+ if (SIMPLEQ_EMPTY(&sc->txbufs)) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
+ /* Send pending management frames first. */
+ IF_DEQUEUE(&ic->ic_mgtq, m);
+ if (m != NULL) {
+ ni = (void *)m->m_pkthdr.rcvif;
+ goto sendit;
+ }
+ if (ic->ic_state != IEEE80211_S_RUN)
+ break;
+
+ /* Encapsulate and send data frames. */
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+#if NBPFILTER > 0
+ if (ifp->if_bpf != NULL)
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+ if ((m = ieee80211_encap(ifp, m, &ni)) == NULL)
+ continue;
+ sendit:
+#if NBPFILTER > 0
+ if (ic->ic_rawbpf != NULL)
+ bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT);
+#endif
+ if (athn_tx(sc, m, ni) != 0) {
+ ieee80211_release_node(ic, ni);
+ ifp->if_oerrors++;
+ continue;
+ }
+
+ sc->sc_tx_timer = 5;
+ ifp->if_timer = 1;
+ }
+}
+
+void
+athn_watchdog(struct ifnet *ifp)
+{
+ struct athn_softc *sc = ifp->if_softc;
+
+ ifp->if_timer = 0;
+
+ if (sc->sc_tx_timer > 0) {
+ if (--sc->sc_tx_timer == 0) {
+ printf("%s: device timeout\n", sc->sc_dev.dv_xname);
+ athn_stop(ifp, 1);
+ (void)athn_init(ifp);
+ ifp->if_oerrors++;
+ return;
+ }
+ ifp->if_timer = 1;
+ }
+
+ ieee80211_watchdog(ifp);
+}
+
+int
+athn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct athn_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifaddr *ifa;
+ struct ifreq *ifr;
+ int s, error = 0;
+
+ s = splnet();
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ ifa = (struct ifaddr *)data;
+ ifp->if_flags |= IFF_UP;
+#ifdef INET
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ arp_ifinit(&ic->ic_ac, ifa);
+#endif
+ /* FALLTHROUGH */
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (!(ifp->if_flags & IFF_RUNNING))
+ error = athn_init(ifp);
+ } else {
+ if (ifp->if_flags & IFF_RUNNING)
+ athn_stop(ifp, 1);
+ }
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ /* XXX Update hardware multicast filter. */
+ ifr = (struct ifreq *)data;
+ error = (cmd == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &ic->ic_ac) :
+ ether_delmulti(ifr, &ic->ic_ac);
+ if (error == ENETRESET)
+ error = 0;
+ break;
+
+ default:
+ error = ieee80211_ioctl(ifp, cmd, data);
+ }
+
+ if (error == ENETRESET) {
+ error = 0;
+ if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
+ (IFF_UP | IFF_RUNNING)) {
+ athn_stop(ifp, 0);
+ error = athn_init(ifp);
+ }
+ }
+
+ splx(s);
+ return (error);
+}
+
+int
+athn_init(struct ifnet *ifp)
+{
+ struct athn_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_channel *c, *extc;
+ int i, error;
+
+ c = ic->ic_bss->ni_chan = ic->ic_ibss_chan;
+ extc = NULL;
+
+ /* In case a new MAC address has been configured. */
+ IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
+
+#ifdef notyet
+ /* For CardBus, power on the socket. */
+ if (sc->sc_enable != NULL) {
+ if ((error = sc->sc_enable(sc)) != 0) {
+ printf("%s: could not enable device\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+ if ((error = athn_reset_power_on(sc)) != 0) {
+ printf("%s: could not power on device\n",
+ sc->sc_dev.dv_xname);
+ goto fail;
+ }
+ }
+#endif
+
+ if (sc->flags & ATHN_FLAG_PCIE)
+ athn_config_pcie(sc);
+
+ if ((error = athn_hw_reset(sc, c, extc)) != 0) {
+ printf("%s: unable to reset hardware; reset status %d\n",
+ sc->sc_dev.dv_xname, error);
+ goto fail;
+ }
+
+ /* Enable Rx. */
+ athn_rx_start(sc);
+
+ /* Enable interrupts. */
+ athn_enable_interrupts(sc);
+
+#ifdef ATHN_BT_COEXISTENCE
+ /* Enable bluetooth coexistence for combo chips. */
+ if (sc->flags & ATHN_FLAG_BTCOEX)
+ athn_btcoex_enable(sc);
+#endif
+
+ ifp->if_flags &= ~IFF_OACTIVE;
+ ifp->if_flags |= IFF_RUNNING;
+
+ if (ic->ic_flags & IEEE80211_F_WEPON) {
+ /* Configure WEP keys. */
+ for (i = 0; i < IEEE80211_WEP_NKID; i++)
+ (void)athn_set_key(ic, NULL, &ic->ic_nw_keys[i]);
+ }
+
+ if (ic->ic_opmode == IEEE80211_M_MONITOR)
+ ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+ else
+ ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+
+ return (0);
+ fail:
+ athn_stop(ifp, 1);
+ return (error);
+}
+
+void
+athn_stop(struct ifnet *ifp, int disable)
+{
+ struct athn_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int qid;
+
+ ifp->if_timer = sc->sc_tx_timer = 0;
+ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+
+ timeout_del(&sc->scan_to);
+ /* In case we were scanning, release the scan "lock". */
+ ic->ic_scan_lock = IEEE80211_SCAN_UNLOCKED;
+
+ ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+
+#ifdef ATHN_BT_COEXISTENCE
+ /* Disable bluetooth coexistence for combo chips. */
+ if (sc->flags & ATHN_FLAG_BTCOEX)
+ athn_btcoex_disable(sc);
+#endif
+
+ /* Disable interrupts. */
+ athn_disable_interrupts(sc);
+
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++)
+ athn_stop_tx_dma(sc, qid);
+ /* XXX call athn_hw_reset if Tx still pending? */
+ for (qid = 0; qid < ATHN_QID_COUNT; qid++)
+ athn_tx_reclaim(sc, qid);
+
+ /* Stop Rx. */
+ AR_SETBITS(sc, AR_DIAG_SW, AR_DIAG_RX_DIS);
+ AR_WRITE(sc, AR_MIBC, AR_MIBC_FMC);
+ AR_WRITE(sc, AR_MIBC, AR_MIBC_CMC);
+ AR_WRITE(sc, AR_FILT_OFDM, 0);
+ AR_WRITE(sc, AR_FILT_CCK, 0);
+ athn_set_rxfilter(sc, 0);
+ athn_stop_rx_dma(sc);
+
+ athn_reset(sc, 0);
+ athn_init_pll(sc, NULL);
+ athn_set_power_awake(sc);
+ athn_reset(sc, 1);
+ athn_init_pll(sc, NULL);
+
+ athn_set_power_sleep(sc);
+
+#ifdef notyet
+ /* For CardBus, power down the socket. */
+ if (disable && sc->sc_disable != NULL)
+ sc->sc_disable(sc);
+#endif
+}
diff --git a/sys/dev/ic/athnreg.h b/sys/dev/ic/athnreg.h
new file mode 100644
index 00000000000..61fc6973b1c
--- /dev/null
+++ b/sys/dev/ic/athnreg.h
@@ -0,0 +1,2410 @@
+/* $OpenBSD: athnreg.h,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2008-2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define AR_CR 0x0008
+#define AR_RXDP 0x000c
+#define AR_CFG 0x0014
+#define AR_MIRT 0x0020
+#define AR_IER 0x0024
+#define AR_TIMT 0x0028
+#define AR_RIMT 0x002c
+#define AR_TXCFG 0x0030
+#define AR_RXCFG 0x0034
+#define AR_MIBC 0x0040
+#define AR_TOPS 0x0044
+#define AR_RXNPTO 0x0048
+#define AR_TXNPTO 0x004c
+#define AR_RPGTO 0x0050
+#define AR_RPCNT 0x0054
+#define AR_MACMISC 0x0058
+#define AR_GTXTO 0x0064
+#define AR_GTTM 0x0068
+#define AR_CST 0x006c
+#define AR_ISR 0x0080
+#define AR_ISR_S0 0x0084
+#define AR_ISR_S1 0x0088
+#define AR_ISR_S2 0x008c
+#define AR_ISR_S3 0x0090
+#define AR_ISR_S4 0x0094
+#define AR_ISR_S5 0x0098
+#define AR_IMR 0x00a0
+#define AR_IMR_S0 0x00a4
+#define AR_IMR_S1 0x00a8
+#define AR_IMR_S2 0x00ac
+#define AR_IMR_S3 0x00b0
+#define AR_IMR_S4 0x00b4
+#define AR_IMR_S5 0x00b8
+#define AR_ISR_RAC 0x00c0
+#define AR_ISR_S0_S 0x00c4
+#define AR_ISR_S1_S 0x00c8
+#define AR_ISR_S2_S 0x00cc
+#define AR_ISR_S3_S 0x00d0
+#define AR_ISR_S4_S 0x00d4
+#define AR_ISR_S5_S 0x00d8
+#define AR_DMADBG(i) (0x00e0 + (i) * 4)
+#define AR_QTXDP(i) (0x0800 + (i) * 4)
+#define AR_Q_TXE 0x0840
+#define AR_Q_TXD 0x0880
+#define AR_QCBRCFG(i) (0x08c0 + (i) * 4)
+#define AR_QRDYTIMECFG(i) (0x0900 + (i) * 4)
+#define AR_Q_ONESHOTARM_SC 0x0940
+#define AR_Q_ONESHOTARM_CC 0x0980
+#define AR_QMISC(i) (0x09c0 + (i) * 4)
+#define AR_QSTS(i) (0x0a00 + (i) * 4)
+#define AR_Q_RDYTIMESHDN 0x0a40
+#define AR_DQCUMASK(i) (0x1000 + (i) * 4)
+#define AR_D_GBL_IFS_SIFS 0x1030
+#define AR_D_TXBLK_CMD 0x1038
+#define AR_DLCL_IFS(i) (0x1040 + (i) * 4)
+#define AR_D_GBL_IFS_SLOT 0x1070
+#define AR_DRETRY_LIMIT(i) (0x1080 + (i) * 4)
+#define AR_D_GBL_IFS_EIFS 0x10b0
+#define AR_DCHNTIME(i) (0x10c0 + (i) * 4)
+#define AR_D_GBL_IFS_MISC 0x10f0
+#define AR_DMISC(i) (0x1100 + (i) * 4)
+#define AR_D_SEQNUM 0x1140
+#define AR_D_FPCTL 0x1230
+#define AR_D_TXPSE 0x1270
+#define AR_D_TXSLOTMASK 0x12f0
+#define AR_MAC_SLEEP 0x1f00
+#define AR_CFG_LED 0x1f04
+#define AR_EEPROM_OFFSET(i) (0x2000 + (i) * 4)
+#define AR_RC 0x4000
+#define AR_WA 0x4004
+#define AR_PM_STATE 0x4008
+#define AR_PCIE_PM_CTRL 0x4014
+#define AR_HOST_TIMEOUT 0x4018
+#define AR_EEPROM 0x401c
+#define AR_SREV 0x4020
+#define AR_AHB_MODE 0x4024
+#define AR_INTR_SYNC_CAUSE 0x4028
+#define AR_INTR_SYNC_ENABLE 0x402c
+#define AR_INTR_ASYNC_MASK 0x4030
+#define AR_INTR_SYNC_MASK 0x4034
+#define AR_INTR_ASYNC_CAUSE 0x4038
+#define AR_INTR_ASYNC_ENABLE 0x403c
+#define AR_PCIE_SERDES 0x4040
+#define AR_PCIE_SERDES2 0x4044
+#define AR_GPIO_IN_OUT 0x4048
+#define AR_GPIO_OE_OUT 0x404c
+#define AR_GPIO_INTR_POL 0x4050
+#define AR_GPIO_INPUT_EN_VAL 0x4054
+#define AR_GPIO_INPUT_MUX1 0x4058
+#define AR_GPIO_INPUT_MUX2 0x405c
+#define AR_GPIO_OUTPUT_MUX(i) (0x4060 + (i) * 4)
+#define AR_INPUT_STATE 0x406c
+#define AR_EEPROM_STATUS_DATA 0x407c
+#define AR_OBS 0x4080
+#define AR_GPIO_PDPU 0x4088
+#define AR_PCIE_MSI 0x4094
+#define AR_RTC_RC 0x7000
+#define AR_RTC_PLL_CONTROL 0x7014
+#define AR_RTC_RESET 0x7040
+#define AR_RTC_STATUS 0x7044
+#define AR_RTC_SLEEP_CLK 0x7048
+#define AR_RTC_FORCE_WAKE 0x704c
+#define AR_RTC_INTR_CAUSE 0x7050
+#define AR_RTC_INTR_ENABLE 0x7054
+#define AR_RTC_INTR_MASK 0x7058
+#define AR_IS_ANALOG_REG(reg) ((reg) >= 0x7800 && (reg) <= 0x78b4)
+#define AR_AN_RF2G1_CH0 0x7810
+#define AR_AN_RF5G1_CH0 0x7818
+#define AR_AN_RF2G1_CH1 0x7834
+#define AR_AN_RF5G1_CH1 0x783c
+#define AR_AN_SYNTH9 0x7868
+#define AR_AN_TOP1 0x7890
+#define AR_AN_TOP2 0x7894
+#define AR_STA_ID0 0x8000
+#define AR_STA_ID1 0x8004
+#define AR_BSS_ID0 0x8008
+#define AR_BSS_ID1 0x800c
+#define AR_BCN_RSSI_AVE 0x8010
+#define AR_TIME_OUT 0x8014
+#define AR_RSSI_THR 0x8018
+#define AR_USEC 0x801c
+#define AR_RESET_TSF 0x8020
+#define AR_MAX_CFP_DUR 0x8038
+#define AR_RX_FILTER 0x803c
+#define AR_MCAST_FIL0 0x8040
+#define AR_MCAST_FIL1 0x8044
+#define AR_DIAG_SW 0x8048
+#define AR_TSF_L32 0x804c
+#define AR_TSF_U32 0x8050
+#define AR_TST_ADDAC 0x8054
+#define AR_DEF_ANTENNA 0x8058
+#define AR_AES_MUTE_MASK0 0x805c
+#define AR_AES_MUTE_MASK1 0x8060
+#define AR_GATED_CLKS 0x8064
+#define AR_OBS_BUS_CTRL 0x8068
+#define AR_OBS_BUS_1 0x806c
+#define AR_LAST_TSTP 0x8080
+#define AR_NAV 0x8084
+#define AR_RTS_OK 0x8088
+#define AR_RTS_FAIL 0x808c
+#define AR_ACK_FAIL 0x8090
+#define AR_FCS_FAIL 0x8094
+#define AR_BEACON_CNT 0x8098
+#define AR_SLEEP1 0x80d4
+#define AR_SLEEP2 0x80d8
+#define AR_BSSMSKL 0x80e0
+#define AR_BSSMSKU 0x80e4
+#define AR_TPC 0x80e8
+#define AR_TFCNT 0x80ec
+#define AR_RFCNT 0x80f0
+#define AR_RCCNT 0x80f4
+#define AR_CCCNT 0x80f8
+#define AR_QUIET1 0x80fc
+#define AR_QUIET2 0x8100
+#define AR_TSF_PARM 0x8104
+#define AR_QOS_NO_ACK 0x8108
+#define AR_PHY_ERR 0x810c
+#define AR_RXFIFO_CFG 0x8114
+#define AR_MIC_QOS_CONTROL 0x8118
+#define AR_MIC_QOS_SELECT 0x811c
+#define AR_PCU_MISC 0x8120
+#define AR_FILT_OFDM 0x8124
+#define AR_FILT_CCK 0x8128
+#define AR_PHY_ERR_1 0x812c
+#define AR_PHY_ERR_MASK_1 0x8130
+#define AR_PHY_ERR_2 0x8134
+#define AR_PHY_ERR_MASK_2 0x8138
+#define AR_TSFOOR_THRESHOLD 0x813c
+#define AR_PHY_ERR_3 0x8168
+#define AR_PHY_ERR_MASK_3 0x816c
+#define AR_BT_COEX_MODE 0x8170
+#define AR_BT_COEX_WEIGHT 0x8174
+#define AR_BT_COEX_MODE2 0x817c
+#define AR_NEXT_NDP2_TIMER(i) (0x8180 + (i) * 4)
+#define AR_NDP2_PERIOD(i) (0x81a0 + (i) * 4)
+#define AR_NDP2_TIMER_MODE 0x81c0
+#define AR_TXSIFS 0x81d0
+#define AR_TXOP_X 0x81ec
+#define AR_TXOP_0_3 0x81f0
+#define AR_TXOP_4_7 0x81f4
+#define AR_TXOP_8_11 0x81f8
+#define AR_TXOP_12_15 0x81fc
+#define AR_NEXT_TBTT_TIMER 0x8200
+#define AR_NEXT_DMA_BEACON_ALERT 0x8204
+#define AR_NEXT_CFP 0x8208
+#define AR_NEXT_HCF 0x820c
+#define AR_NEXT_TIM 0x8210
+#define AR_NEXT_DTIM 0x8214
+#define AR_NEXT_QUIET_TIMER 0x8218
+#define AR_NEXT_NDP_TIMER 0x821c
+#define AR_BEACON_PERIOD 0x8220
+#define AR_DMA_BEACON_PERIOD 0x8224
+#define AR_SWBA_PERIOD 0x8228
+#define AR_HCF_PERIOD 0x822c
+#define AR_TIM_PERIOD 0x8230
+#define AR_DTIM_PERIOD 0x8234
+#define AR_QUIET_PERIOD 0x8238
+#define AR_NDP_PERIOD 0x823c
+#define AR_TIMER_MODE 0x8240
+#define AR_SLP32_MODE 0x8244
+#define AR_SLP32_WAKE 0x8248
+#define AR_SLP32_INC 0x824c
+#define AR_SLP_CNT 0x8250
+#define AR_SLP_CYCLE_CNT 0x8254
+#define AR_SLP_MIB_CTRL 0x8258
+#define AR_WOW_PATTERN_REG 0x825c
+#define AR_WOW_COUNT_REG 0x8260
+#define AR_MAC_PCU_LOGIC_ANALYZER 0x8264
+#define AR_WOW_BCN_EN_REG 0x8270
+#define AR_WOW_BCN_TIMO_REG 0x8274
+#define AR_WOW_KEEP_ALIVE_TIMO_REG 0x8278
+#define AR_WOW_KEEP_ALIVE_REG 0x827c
+#define AR_WOW_US_SCALAR_REG 0x8284
+#define AR_WOW_KEEP_ALIVE_DELAY_REG 0x8288
+#define AR_WOW_PATTERN_MATCH_REG 0x828c
+#define AR_WOW_PATTERN_OFF1_REG 0x8290
+#define AR_WOW_PATTERN_OFF2_REG 0x8294
+#define AR_WOW_EXACT_REG 0x829c
+#define AR_2040_MODE 0x8318
+#define AR_EXTRCCNT 0x8328
+#define AR_SELFGEN_MASK 0x832c
+#define AR_PCU_TXBUF_CTRL 0x8340
+#define AR_PCU_MISC_MODE2 0x8344
+#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
+#define AR_WOW_LENGTH1_REG 0x8360
+#define AR_WOW_LENGTH2_REG 0x8364
+#define AR_WOW_PATTERN_MATCH_LT_256B 0x8368
+#define AR_RATE_DURATION(i) (0x8700 + (i) * 4)
+#define AR_KEYTABLE(i) (0x8800 + (i) * 32)
+#define AR_KEYTABLE_KEY0(i) (AR_KEYTABLE(i) + 0)
+#define AR_KEYTABLE_KEY1(i) (AR_KEYTABLE(i) + 4)
+#define AR_KEYTABLE_KEY2(i) (AR_KEYTABLE(i) + 8)
+#define AR_KEYTABLE_KEY3(i) (AR_KEYTABLE(i) + 12)
+#define AR_KEYTABLE_KEY4(i) (AR_KEYTABLE(i) + 16)
+#define AR_KEYTABLE_TYPE(i) (AR_KEYTABLE(i) + 20)
+#define AR_KEYTABLE_MAC0(i) (AR_KEYTABLE(i) + 24)
+#define AR_KEYTABLE_MAC1(i) (AR_KEYTABLE(i) + 28)
+
+/*
+ * PHY registers.
+ */
+#define AR_PHY_BASE 0x9800
+#define AR_PHY(i) (AR_PHY_BASE + (i) * 4)
+#define AR_PHY_TEST 0x9800
+#define AR_PHY_TURBO 0x9804
+#define AR_PHY_TEST2 0x9808
+#define AR_PHY_TIMING2 0x9810
+#define AR_PHY_TIMING3 0x9814
+#define AR_PHY_CHIP_ID 0x9818
+#define AR_PHY_ACTIVE 0x981c
+#define AR_PHY_RF_CTL2 0x9824
+#define AR_PHY_RF_CTL3 0x9828
+#define AR_PHY_ADC_CTL 0x982c
+#define AR_PHY_ADC_SERIAL_CTL 0x9830
+#define AR_PHY_RF_CTL4 0x9834
+#define AR_PHY_TSTDAC_CONST 0x983c
+#define AR_PHY_SETTLING 0x9844
+#define AR_PHY_RXGAIN 0x9848
+#define AR_PHY_DESIRED_SZ 0x9850
+#define AR_PHY_FIND_SIG 0x9858
+#define AR_PHY_AGC_CTL1 0x985c
+#define AR_PHY_AGC_CONTROL 0x9860
+#define AR_PHY_CCA(i) (0x9864 + (i) * 0x1000)
+#define AR_PHY_SFCORR 0x9868
+#define AR_PHY_SFCORR_LOW 0x986c
+#define AR_PHY_SLEEP_CTR_CONTROL 0x9870
+#define AR_PHY_SLEEP_CTR_LIMIT 0x9874
+#define AR_PHY_SLEEP_SCAL 0x9878
+#define AR_PHY_PLL_CTL 0x987c
+#define AR_PHY_BIN_MASK_1 0x9900
+#define AR_PHY_BIN_MASK_2 0x9904
+#define AR_PHY_BIN_MASK_3 0x9908
+#define AR_PHY_MASK_CTL 0x990c
+#define AR_PHY_RX_DELAY 0x9914
+#define AR_PHY_SEARCH_START_DELAY 0x9918
+#define AR_PHY_TIMING_CTRL4_0 0x9920
+#define AR_PHY_TIMING_CTRL4(i) (0x9920 + (i) * 0x1000)
+#define AR_PHY_TIMING5 0x9924
+#define AR_PHY_POWER_TX_RATE1 0x9934
+#define AR_PHY_POWER_TX_RATE2 0x9938
+#define AR_PHY_POWER_TX_RATE_MAX 0x993c
+#define AR_PHY_RADAR_EXT 0x9940
+#define AR_PHY_FRAME_CTL 0x9944
+#define AR_PHY_SPUR_REG 0x994c
+#define AR_PHY_RADAR_0 0x9954
+#define AR_PHY_RADAR_1 0x9958
+#define AR_PHY_SWITCH_CHAIN_0 0x9960
+#define AR_PHY_SWITCH_COM 0x9964
+#define AR_PHY_SIGMA_DELTA 0x996c
+#define AR_PHY_RESTART 0x9970
+#define AR_PHY_RFBUS_REQ 0x997c
+#define AR_PHY_TIMING7 0x9980
+#define AR_PHY_TIMING8 0x9984
+#define AR_PHY_BIN_MASK2_1 0x9988
+#define AR_PHY_BIN_MASK2_2 0x998c
+#define AR_PHY_BIN_MASK2_3 0x9990
+#define AR_PHY_BIN_MASK2_4 0x9994
+#define AR_PHY_TIMING9 0x9998
+#define AR_PHY_TIMING10 0x999c
+#define AR_PHY_TIMING11 0x99a0
+#define AR_PHY_RX_CHAINMASK 0x99a4
+#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
+#define AR_PHY_NEW_ADC_DC_GAIN_CORR(i) (0x99b4 + (i) * 0x1000)
+#define AR_PHY_EXT_CCA0 0x99b8
+#define AR_PHY_EXT_CCA(i) (0x99bc + (i) * 0x1000)
+#define AR_PHY_SFCORR_EXT 0x99c0
+#define AR_PHY_HALFGI 0x99d0
+#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
+#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
+#define AR_PHY_CHAN_INFO_MEMORY 0x99dc
+#define AR_PHY_HEAVY_CLIP_ENABLE 0x99e0
+#define AR_PHY_CALMODE 0x99f0
+#define AR_PHY_REFCLKDLY 0x99f4
+#define AR_PHY_REFCLKPD 0x99f8
+#define AR_PHY_BB_RFGAIN(i) (0x9a00 + (i) * 4)
+#define AR_PHY_CAL_MEAS_0(i) (0x9c10 + (i) * 0x1000)
+#define AR_PHY_CAL_MEAS_1(i) (0x9c14 + (i) * 0x1000)
+#define AR_PHY_CAL_MEAS_2(i) (0x9c18 + (i) * 0x1000)
+#define AR_PHY_CAL_MEAS_3(i) (0x9c1c + (i) * 0x1000)
+#define AR_PHY_CURRENT_RSSI 0x9c1c
+#define AR_PHY_RFBUS_GRANT 0x9c20
+#define AR9280_PHY_CURRENT_RSSI 0x9c3c
+#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9cf4
+#define AR_PHY_CHAN_INFO_GAIN 0x9cfc
+#define AR_PHY_MODE 0xa200
+#define AR_PHY_CCK_TX_CTRL 0xa204
+#define AR_PHY_CCK_DETECT 0xa208
+#define AR_PHY_GAIN_2GHZ 0xa20c
+#define AR_PHY_CCK_RXCTRL4 0xa21c
+#define AR_PHY_DAG_CTRLCCK 0xa228
+#define AR_PHY_FORCE_CLKEN_CCK 0xa22c
+#define AR_PHY_POWER_TX_RATE3 0xa234
+#define AR_PHY_POWER_TX_RATE4 0xa238
+#define AR_PHY_SCRM_SEQ_XR 0xa23c
+#define AR_PHY_HEADER_DETECT_XR 0xa240
+#define AR_PHY_CHIRP_DETECTED_XR 0xa244
+#define AR_PHY_BLUETOOTH 0xa254
+#define AR_PHY_TPCRG1 0xa258
+#define AR_PHY_TX_PWRCTRL4 0xa264
+#define AR_PHY_ANALOG_SWAP 0xa268
+#define AR_PHY_TPCRG5 0xa26c
+#define AR_PHY_TX_PWRCTRL6_0 0xa270
+#define AR_PHY_TX_PWRCTRL7 0xa274
+#define AR_PHY_TX_PWRCTRL9 0xa27c
+#define AR_PHY_PDADC_TBL_BASE 0xa280
+#define AR_PHY_TX_GAIN_TBL(i) (0xa300 + (i) * 4)
+#define AR_PHY_CL_CAL_CTL 0xa358
+#define AR_PHY_POWER_TX_RATE5 0xa38c
+#define AR_PHY_POWER_TX_RATE6 0xa390
+#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
+#define AR_PHY_CAL_CHAINMASK 0xa39c
+#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
+#define AR_PHY_VIT_MASK2_M_31_45 0xa3a4
+#define AR_PHY_VIT_MASK2_M_16_30 0xa3a8
+#define AR_PHY_VIT_MASK2_M_00_15 0xa3ac
+#define AR_PHY_PILOT_MASK_01_30 0xa3b0
+#define AR_PHY_PILOT_MASK_31_60 0xa3b4
+#define AR_PHY_VIT_MASK2_P_15_01 0xa3b8
+#define AR_PHY_VIT_MASK2_P_30_16 0xa3bc
+#define AR_PHY_VIT_MASK2_P_45_31 0xa3c0
+#define AR_PHY_VIT_MASK2_P_61_46 0xa3c4
+#define AR_PHY_POWER_TX_SUB 0xa3c8
+#define AR_PHY_POWER_TX_RATE7 0xa3cc
+#define AR_PHY_POWER_TX_RATE8 0xa3d0
+#define AR_PHY_POWER_TX_RATE9 0xa3d4
+#define AR_PHY_XPA_CFG 0xa3d8
+#define AR_PHY_TX_PWRCTRL6_1 0xb270
+#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
+
+/* Bits for AR_CR. */
+#define AR_CR_RXE 0x00000004
+#define AR_CR_RXD 0x00000020
+#define AR_CR_SWI 0x00000040
+
+/* Bits for AR_CFG. */
+#define AR_CFG_SWTD 0x00000001
+#define AR_CFG_SWTB 0x00000002
+#define AR_CFG_SWRD 0x00000004
+#define AR_CFG_SWRB 0x00000008
+#define AR_CFG_SWRG 0x00000010
+#define AR_CFG_AP_ADHOC_INDICATION 0x00000020
+#define AR_CFG_PHOK 0x00000100
+#define AR_CFG_EEBS 0x00000200
+#define AR_CFG_CLK_GATE_DIS 0x00000400
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_M 0x00060000
+#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17
+
+/* Bits for AR_IER. */
+#define AR_IER_ENABLE 0x00000001
+
+/* Bits for AR_TIMT. */
+#define AR_TIMT_LAST_M 0x0000ffff
+#define AR_TIMT_LAST_S 0
+#define AR_TIMT_FIRST_M 0xffff0000
+#define AR_TIMT_FIRST_S 16
+
+/* Bits for AR_RIMT. */
+#define AR_RIMT_LAST_M 0x0000ffff
+#define AR_RIMT_LAST_S 0
+#define AR_RIMT_FIRST_M 0xffff0000
+#define AR_RIMT_FIRST_S 16
+
+/* Bits for AR_[TR]XCFG_DMASZ fields. */
+#define AR_DMASZ_4B 0
+#define AR_DMASZ_8B 1
+#define AR_DMASZ_16B 2
+#define AR_DMASZ_32B 3
+#define AR_DMASZ_64B 4
+#define AR_DMASZ_128B 5
+#define AR_DMASZ_256B 6
+#define AR_DMASZ_512B 7
+
+/* Bits for AR_TXCFG. */
+#define AR_TXCFG_DMASZ_M 0x00000007
+#define AR_TXCFG_DMASZ_S 0
+#define AR_TXCFG_FTRIG_M 0x000003f0
+#define AR_TXCFG_FTRIG_S 4
+#define AR_TXCFG_FTRIG_IMMED ( 0 / 64)
+#define AR_TXCFG_FTRIG_64B ( 64 / 64)
+#define AR_TXCFG_FTRIG_128B (128 / 64)
+#define AR_TXCFG_FTRIG_192B (192 / 64)
+#define AR_TXCFG_FTRIG_256B (256 / 64)
+#define AR_TXCFG_FTRIG_512B (512 / 64)
+#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800
+
+/* Bits for AR_RXCFG. */
+#define AR_RXCFG_DMASZ_M 0x00000007
+#define AR_RXCFG_DMASZ_S 0
+#define AR_RXCFG_CHIRP 0x00000008
+#define AR_RXCFG_ZLFDMA 0x00000010
+
+/* Bits for AR_MIBC. */
+#define AR_MIBC_COW 0x00000001
+#define AR_MIBC_FMC 0x00000002
+#define AR_MIBC_CMC 0x00000004
+#define AR_MIBC_MCS 0x00000008
+
+/* Bits for AR_TOPS. */
+#define AR_TOPS_MASK 0x0000ffff
+
+/* Bits for AR_RXNPTO. */
+#define AR_RXNPTO_MASK 0x000003ff
+
+/* Bits for AR_TXNPTO. */
+#define AR_TXNPTO_MASK 0x000003ff
+#define AR_TXNPTO_QCU_MASK 0x000ffc00
+
+/* Bits for AR_RPGTO. */
+#define AR_RPGTO_MASK 0x000003ff
+
+/* Bits for AR_RPCNT. */
+#define AR_RPCNT_MASK 0x0000001f
+
+/* Bits for AR_MACMISC. */
+#define AR_MACMISC_PCI_EXT_FORCE 0x00000010
+#define AR_MACMISC_DMA_OBS_M 0x000001e0
+#define AR_MACMISC_DMA_OBS_S 5
+#define AR_MACMISC_MISC_OBS_M 0x00000e00
+#define AR_MACMISC_MISC_OBS_S 9
+#define AR_MACMISC_MISC_OBS_BUS_LSB_M 0x00007000
+#define AR_MACMISC_MISC_OBS_BUS_LSB_S 12
+#define AR_MACMISC_MISC_OBS_BUS_MSB_M 0x00038000
+#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15
+
+/* Bits for AR_GTXTO. */
+#define AR_GTXTO_TIMEOUT_COUNTER_M 0x0000ffff
+#define AR_GTXTO_TIMEOUT_COUNTER_S 0
+#define AR_GTXTO_TIMEOUT_LIMIT_M 0xffff0000
+#define AR_GTXTO_TIMEOUT_LIMIT_S 16
+
+/* Bits for AR_GTTM. */
+#define AR_GTTM_USEC 0x00000001
+#define AR_GTTM_IGNORE_IDLE 0x00000002
+#define AR_GTTM_RESET_IDLE 0x00000004
+#define AR_GTTM_CST_USEC 0x00000008
+
+/* Bits for AR_CST. */
+#define AR_CST_TIMEOUT_COUNTER_M 0x0000ffff
+#define AR_CST_TIMEOUT_COUNTER_S 0
+#define AR_CST_TIMEOUT_LIMIT_M 0xffff0000
+#define AR_CST_TIMEOUT_LIMIT_S 16
+
+/* Bits for AR_ISR. */
+#define AR_ISR_RXOK 0x00000001
+#define AR_ISR_RXDESC 0x00000002
+#define AR_ISR_RXERR 0x00000004
+#define AR_ISR_RXNOPKT 0x00000008
+#define AR_ISR_RXEOL 0x00000010
+#define AR_ISR_RXORN 0x00000020
+#define AR_ISR_TXOK 0x00000040
+#define AR_ISR_TXDESC 0x00000080
+#define AR_ISR_TXERR 0x00000100
+#define AR_ISR_TXNOPKT 0x00000200
+#define AR_ISR_TXEOL 0x00000400
+#define AR_ISR_TXURN 0x00000800
+#define AR_ISR_MIB 0x00001000
+#define AR_ISR_SWI 0x00002000
+#define AR_ISR_RXPHY 0x00004000
+#define AR_ISR_RXKCM 0x00008000
+#define AR_ISR_SWBA 0x00010000
+#define AR_ISR_BRSSI 0x00020000
+#define AR_ISR_BMISS 0x00040000
+#define AR_ISR_TXMINTR 0x00080000
+#define AR_ISR_BNR 0x00100000
+#define AR_ISR_RXCHIRP 0x00200000
+#define AR_ISR_BCNMISC 0x00800000
+#define AR_ISR_TIM 0x00800000
+#define AR_ISR_RXMINTR 0x01000000
+#define AR_ISR_QCBROVF 0x02000000
+#define AR_ISR_QCBRURN 0x04000000
+#define AR_ISR_QTRIG 0x08000000
+#define AR_ISR_GENTMR 0x10000000
+#define AR_ISR_TXINTM 0x40000000
+#define AR_ISR_RXINTM 0x80000000
+
+/* Bits for AR_ISR_S0. */
+#define AR_ISR_S0_QCU_TXOK_M 0x000003ff
+#define AR_ISR_S0_QCU_TXOK_S 0
+#define AR_ISR_S0_QCU_TXDESC_M 0x03ff0000
+#define AR_ISR_S0_QCU_TXDESC_S 16
+
+/* Bits for AR_ISR_S1. */
+#define AR_ISR_S1_QCU_TXERR_M 0x000003ff
+#define AR_ISR_S1_QCU_TXERR_S 0
+#define AR_ISR_S1_QCU_TXEOL_M 0x03ff0000
+#define AR_ISR_S1_QCU_TXEOL_S 16
+
+/* Bits for AR_ISR_S2. */
+#define AR_ISR_S2_QCU_TXURN_M 0x000003ff
+#define AR_ISR_S2_QCU_TXURN_S 0
+#define AR_ISR_S2_CST 0x00400000
+#define AR_ISR_S2_GTT 0x00800000
+#define AR_ISR_S2_TIM 0x01000000
+#define AR_ISR_S2_CABEND 0x02000000
+#define AR_ISR_S2_DTIMSYNC 0x04000000
+#define AR_ISR_S2_BCNTO 0x08000000
+#define AR_ISR_S2_CABTO 0x10000000
+#define AR_ISR_S2_DTIM 0x20000000
+#define AR_ISR_S2_TSFOOR 0x40000000
+#define AR_ISR_S2_TBTT_TIME 0x80000000
+
+/* Bits for AR_ISR_S3. */
+#define AR_ISR_S3_QCU_QCBROVF_M 0x000003ff
+#define AR_ISR_S3_QCU_QCBROVF_S 0
+#define AR_ISR_S3_QCU_QCBRURN_M 0x03ff0000
+#define AR_ISR_S3_QCU_QCBRURN_S 0
+
+/* Bits for AR_ISR_S4. */
+#define AR_ISR_S4_QCU_QTRIG_M 0x000003ff
+#define AR_ISR_S4_QCU_QTRIG_S 0
+
+/* Bits for AR_ISR_S5. */
+#define AR_ISR_S5_TIMER_TRIG_M 0x000000ff
+#define AR_ISR_S5_TIMER_TRIG_S 0
+#define AR_ISR_S5_TIMER_THRESH_M 0x0007fe00
+#define AR_ISR_S5_TIMER_THRESH_S 9
+#define AR_ISR_S5_TIM_TIMER 0x00000010
+#define AR_ISR_S5_DTIM_TIMER 0x00000020
+#define AR_ISR_S5_GENTIMER_TRIG_M 0x0000ff80
+#define AR_ISR_S5_GENTIMER_TRIG_S 0
+#define AR_ISR_S5_GENTIMER_THRESH_M 0xff800000
+#define AR_ISR_S5_GENTIMER_THRESH_S 16
+
+/* Bits for AR_IMR. */
+#define AR_IMR_RXOK 0x00000001
+#define AR_IMR_RXDESC 0x00000002
+#define AR_IMR_RXERR 0x00000004
+#define AR_IMR_RXNOPKT 0x00000008
+#define AR_IMR_RXEOL 0x00000010
+#define AR_IMR_RXORN 0x00000020
+#define AR_IMR_TXOK 0x00000040
+#define AR_IMR_TXDESC 0x00000080
+#define AR_IMR_TXERR 0x00000100
+#define AR_IMR_TXNOPKT 0x00000200
+#define AR_IMR_TXEOL 0x00000400
+#define AR_IMR_TXURN 0x00000800
+#define AR_IMR_MIB 0x00001000
+#define AR_IMR_SWI 0x00002000
+#define AR_IMR_RXPHY 0x00004000
+#define AR_IMR_RXKCM 0x00008000
+#define AR_IMR_SWBA 0x00010000
+#define AR_IMR_BRSSI 0x00020000
+#define AR_IMR_BMISS 0x00040000
+#define AR_IMR_TXMINTR 0x00080000
+#define AR_IMR_BNR 0x00100000
+#define AR_IMR_RXCHIRP 0x00200000
+#define AR_IMR_BCNMISC 0x00800000
+#define AR_IMR_TIM 0x00800000
+#define AR_IMR_RXMINTR 0x01000000
+#define AR_IMR_QCBROVF 0x02000000
+#define AR_IMR_QCBRURN 0x04000000
+#define AR_IMR_QTRIG 0x08000000
+#define AR_IMR_GENTMR 0x10000000
+#define AR_IMR_TXINTM 0x40000000
+#define AR_IMR_RXINTM 0x80000000
+
+#ifndef ATHN_INTR_MITIGATION
+#define AR_IMR_DEFAULT \
+ (AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXERR | \
+ AR_IMR_RXORN | AR_IMR_BCNMISC | AR_IMR_RXOK | AR_IMR_TXOK)
+#else
+#define AR_IMR_DEFAULT \
+ (AR_IMR_TXERR | AR_IMR_TXURN | AR_IMR_RXERR | \
+ AR_IMR_RXORN | AR_IMR_BCNMISC | AR_IMR_RXINTM | \
+ AR_IMR_RXMINTR | AR_IMR_TXOK)
+#endif
+#define AR_IMR_HOSTAP (AR_IMR_DEFAULT | AR_IMR_MIB)
+
+/* Bits for AR_IMR_S0. */
+#define AR_IMR_S0_QCU_TXOK(qid) (1 << (qid))
+#define AR_IMR_S0_QCU_TXDESC(qid) (1 << (16 + (qid)))
+
+/* Bits for AR_IMR_S1. */
+#define AR_IMR_S1_QCU_TXERR(qid) (1 << (qid))
+#define AR_IMR_S1_QCU_TXEOL(qid) (1 << (16 + (qid)))
+
+/* Bits for AR_IMR_S2. */
+#define AR_IMR_S2_QCU_TXURN(qid) (1 << (qid))
+#define AR_IMR_S2_CST 0x00400000
+#define AR_IMR_S2_GTT 0x00800000
+#define AR_IMR_S2_TIM 0x01000000
+#define AR_IMR_S2_CABEND 0x02000000
+#define AR_IMR_S2_DTIMSYNC 0x04000000
+#define AR_IMR_S2_BCNTO 0x08000000
+#define AR_IMR_S2_CABTO 0x10000000
+#define AR_IMR_S2_DTIM 0x20000000
+#define AR_IMR_S2_TSFOOR 0x40000000
+
+/* Bits for AR_IMR_S3. */
+#define AR_IMR_S3_QCU_QCBROVF(qid) (1 << (qid))
+#define AR_IMR_S3_QCU_QCBRURN(qid) (1 << (16 + (qid)))
+
+/* Bits for AR_IMR_S4. */
+#define AR_IMR_S4_QCU_QTRIG(qid) (1 << (qid))
+
+/* Bits for AR_IMR_S5. */
+#define AR_IMR_S5_TIM_TIMER 0x00000010
+#define AR_IMR_S5_DTIM_TIMER 0x00000020
+#define AR_IMR_S5_TIMER_TRIG_M 0x000000ff
+#define AR_IMR_S5_TIMER_TRIG_S 0
+#define AR_IMR_S5_TIMER_THRESH_M 0x0000ff00
+#define AR_IMR_S5_TIMER_THRESH_S 0
+
+#define AR_NUM_QCU 10
+#define AR_QCU(x) (1 << (x))
+
+/* Bits for AR_Q_TXE. */
+#define AR_Q_TXE_M 0x000003ff
+#define AR_Q_TXE_S 0
+
+/* Bits for AR_Q_TXD. */
+#define AR_Q_TXD_M 0x000003ff
+#define AR_Q_TXD_S 0
+
+/* Bits for AR_QCBRCFG_*. */
+#define AR_Q_CBRCFG_INTERVAL_M 0x00ffffff
+#define AR_Q_CBRCFG_INTERVAL_S 0
+#define AR_Q_CBRCFG_OVF_THRESH_M 0xff000000
+#define AR_Q_CBRCFG_OVF_THRESH_S 24
+
+/* Bits for AR_Q_RDYTIMECFG_*. */
+#define AR_Q_RDYTIMECFG_DURATION_M 0x00ffffff
+#define AR_Q_RDYTIMECFG_DURATION_S 0
+#define AR_Q_RDYTIMECFG_EN 0x01000000
+
+/* Bits for AR_Q_MISC_*. */
+#define AR_Q_MISC_FSP_M 0x0000000f
+#define AR_Q_MISC_FSP_S 0
+#define AR_Q_MISC_FSP_ASAP 0
+#define AR_Q_MISC_FSP_CBR 1
+#define AR_Q_MISC_FSP_DBA_GATED 2
+#define AR_Q_MISC_FSP_TIM_GATED 3
+#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4
+#define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5
+#define AR_Q_MISC_ONE_SHOT_EN 0x00000010
+#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020
+#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040
+#define AR_Q_MISC_BEACON_USE 0x00000080
+#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100
+#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200
+#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400
+#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800
+
+/* Bits for AR_Q_STS_*. */
+#define AR_Q_STS_PEND_FR_CNT_M 0x00000003
+#define AR_Q_STS_PEND_FR_CNT_S 0
+#define AR_Q_STS_CBR_EXP_CNT_M 0x0000ff00
+#define AR_Q_STS_CBR_EXP_CNT_S 8
+
+#define AR_NUM_DCU 10
+#define AR_DCU(x) (1 << (x))
+
+/* Bits for AR_D_QCUMASK_*. */
+#define AR_D_QCUMASK_M 0x000003ff
+#define AR_D_QCUMASK_S 0
+
+/* Bits for AR_D_GBL_IFS_SIFS. */
+#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003ab
+
+/* Bits for AR_D_TXBLK_CMD. */
+#define AR_D_TXBLK_WRITE_BITMASK_M 0x0000ffff
+#define AR_D_TXBLK_WRITE_BITMASK_S 0
+#define AR_D_TXBLK_WRITE_SLICE_M 0x000f0000
+#define AR_D_TXBLK_WRITE_SLICE_S 16
+#define AR_D_TXBLK_WRITE_DCU_M 0x00f00000
+#define AR_D_TXBLK_WRITE_DCU_S 20
+#define AR_D_TXBLK_WRITE_COMMAND_M 0x0f000000
+#define AR_D_TXBLK_WRITE_COMMAND_S 24
+
+/* Bits for AR_DLCL_IFS. */
+#define AR_D_LCL_IFS_CWMIN_M 0x000003ff
+#define AR_D_LCL_IFS_CWMIN_S 0
+#define AR_D_LCL_IFS_CWMAX_M 0x000ffc00
+#define AR_D_LCL_IFS_CWMAX_S 10
+#define AR_D_LCL_IFS_AIFS_M 0x0ff00000
+#define AR_D_LCL_IFS_AIFS_S 20
+
+/* Bits for AR_D_GBL_IFS_SLOT. */
+#define AR_D_GBL_IFS_SLOT_M 0x0000ffff
+#define AR_D_GBL_IFS_SLOT_S 0
+#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420
+
+/* Bits for AR_DRETRY_LIMIT_*. */
+#define AR_D_RETRY_LIMIT_FR_SH_M 0x0000000f
+#define AR_D_RETRY_LIMIT_FR_SH_S 0
+#define AR_D_RETRY_LIMIT_STA_SH_M 0x00003f00
+#define AR_D_RETRY_LIMIT_STA_SH_S 8
+#define AR_D_RETRY_LIMIT_STA_LG_M 0x000fc000
+#define AR_D_RETRY_LIMIT_STA_LG_S 14
+
+/* Bits for AR_D_GBL_IFS_EIFS. */
+#define AR_D_GBL_IFS_EIFS_M 0x0000ffff
+#define AR_D_GBL_IFS_EIFS_S 0
+#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000a5eb
+
+/* Bits for AR_DCHNTIME_*. */
+#define AR_D_CHNTIME_DUR_M 0x000fffff
+#define AR_D_CHNTIME_DUR_S 0
+#define AR_D_CHNTIME_EN 0x00100000
+
+/* Bits for AR_D_GBL_IFS_MISC. */
+#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007
+#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008
+#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000ffc00
+#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000
+#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000
+#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000
+#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000
+#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000
+
+/* Bits for AR_DMISC_*. */
+#define AR_D_MISC_BKOFF_THRESH_M 0x0000003f
+#define AR_D_MISC_BKOFF_THRESH_S 0
+#define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040
+#define AR_D_MISC_CW_RESET_EN 0x00000080
+#define AR_D_MISC_FRAG_WAIT_EN 0x00000100
+#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200
+#define AR_D_MISC_CW_BKOFF_EN 0x00001000
+#define AR_D_MISC_VIR_COL_HANDLING_M 0x0000c000
+#define AR_D_MISC_VIR_COL_HANDLING_S 14
+#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0
+#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1
+#define AR_D_MISC_BEACON_USE 0x00010000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_M 0x00060000
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1
+#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2
+#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000
+#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000
+#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000
+#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000
+#define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000
+
+/* Bits for AR_D_FPCTL. */
+#define AR_D_FPCTL_DCU_M 0x0000000f
+#define AR_D_FPCTL_DCU_S 0
+#define AR_D_FPCTL_PREFETCH_EN 0x00000010
+#define AR_D_FPCTL_BURST_PREFETCH_M 0x00007fe0
+#define AR_D_FPCTL_BURST_PREFETCH_S 5
+
+/* Bits for AR_D_TXPSE. */
+#define AR_D_TXPSE_CTRL_M 0x000003ff
+#define AR_D_TXPSE_CTRL_S 0
+#define AR_D_TXPSE_STATUS 0x00010000
+
+/* Bits for AR_D_TXSLOTMASK. */
+#define AR_D_TXSLOTMASK_NUM 0x0000000f
+
+/* Bits for AR_MAC_SLEEP. */
+#define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001
+
+/* Bits for AR_CFG_LED. */
+#define AR_CFG_SCLK_RATE_IND_M 0x00000003
+#define AR_CFG_SCLK_RATE_IND_S 0
+#define AR_CFG_SCLK_32MHZ 0
+#define AR_CFG_SCLK_4MHZ 1
+#define AR_CFG_SCLK_1MHZ 2
+#define AR_CFG_SCLK_32KHZ 3
+#define AR_CFG_LED_BLINK_SLOW 0x00000008
+#define AR_CFG_LED_BLINK_THRESH_SEL_M 0x00000070
+#define AR_CFG_LED_BLINK_THRESH_SEL_S 4
+#define AR_CFG_LED_MODE_SEL_M 0x00000380
+#define AR_CFG_LED_MODE_SEL_S 7
+#define AR_CFG_LED_POWER_M 0x00000280
+#define AR_CFG_LED_POWER_S 7
+#define AR_CFG_LED_NETWORK_M 0x00000300
+#define AR_CFG_LED_NETWORK_S 7
+#define AR_CFG_LED_MODE_PROP 0
+#define AR_CFG_LED_MODE_RPROP 1
+#define AR_CFG_LED_MODE_SPLIT 2
+#define AR_CFG_LED_MODE_RAND 3
+#define AR_CFG_LED_MODE_POWER_OFF 4
+#define AR_CFG_LED_MODE_POWER_ON 5
+#define AR_CFG_LED_MODE_NETWORK_OFF 4
+#define AR_CFG_LED_MODE_NETWORK_ON 6
+#define AR_CFG_LED_ASSOC_CTL_M 0x00000c00
+#define AR_CFG_LED_ASSOC_CTL_S 10
+#define AR_CFG_LED_ASSOC_NONE 0
+#define AR_CFG_LED_ASSOC_ACTIVE 1
+#define AR_CFG_LED_ASSOC_PENDING 2
+
+/* Bit for AR_RC. */
+#define AR_RC_AHB 0x00000001
+#define AR_RC_APB 0x00000002
+#define AR_RC_HOSTIF 0x00000100
+
+/* Bits for AR_WA. */
+#define AR5416_WA_DEFAULT 0x0000073f
+#define AR9280_WA_DEFAULT 0x0040073b
+#define AR9285_WA_DEFAULT 0x004a05cb
+#define AR_WA_UNTIE_RESET_EN 0x00008000
+#define AR_WA_RESET_EN 0x00040000
+#define AR_WA_ANALOG_SHIFT 0x00100000
+#define AR_WA_POR_SHORT 0x00200000
+
+/* Bits for AR_PM_STATE. */
+#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
+
+/* Bits for AR_PCIE_PM_CTRL. */
+#define AR_PCIE_PM_CTRL_ENA 0x00080000
+
+/* Bits for AR_HOST_TIMEOUT. */
+#define AR_HOST_TIMEOUT_APB_CNTR_M 0x0000ffff
+#define AR_HOST_TIMEOUT_APB_CNTR_S 0
+#define AR_HOST_TIMEOUT_LCL_CNTR_M 0xffff0000
+#define AR_HOST_TIMEOUT_LCL_CNTR_S 16
+
+/* Bits for AR_EEPROM. */
+#define AR_EEPROM_ABSENT 0x00000100
+#define AR_EEPROM_CORRUPT 0x00000200
+#define AR_EEPROM_PROT_MASK_M 0x03fffc00
+#define AR_EEPROM_PROT_MASK_S 10
+
+/* Bits for AR_SREV. */
+#define AR_SREV_ID_M 0x000000ff
+#define AR_SREV_ID_S 0
+#define AR_SREV_REVISION_M 0x00000007
+#define AR_SREV_REVISION_S 0
+#define AR_SREV_VERSION_M 0x000000f0
+#define AR_SREV_VERSION_S 4
+#define AR_SREV_VERSION2_M 0xfffc0000
+#define AR_SREV_VERSION2_S 12 /* XXX Hack. */
+#define AR_SREV_TYPE2_M 0x0003f000
+#define AR_SREV_TYPE2_S 12
+#define AR_SREV_TYPE2_CHAIN 0x00001000
+#define AR_SREV_TYPE2_HOST_MODE 0x00002000
+#define AR_SREV_REVISION2_M 0x00000f00
+#define AR_SREV_REVISION2_S 8
+#define AR_SREV_VERSION_5416_PCI 0x00d
+#define AR_SREV_VERSION_5416_PCIE 0x00c
+#define AR_SREV_REVISION_5416_10 0
+#define AR_SREV_REVISION_5416_20 1
+#define AR_SREV_REVISION_5416_22 2
+#define AR_SREV_VERSION_9100 0x014
+#define AR_SREV_VERSION_9160 0x040
+#define AR_SREV_REVISION_9160_10 0
+#define AR_SREV_REVISION_9160_11 1
+#define AR_SREV_VERSION_9280 0x080
+#define AR_SREV_REVISION_9280_10 0
+#define AR_SREV_REVISION_9280_20 1
+#define AR_SREV_REVISION_9280_21 2
+#define AR_SREV_VERSION_9285 0x0c0
+#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_9287 0x180
+#define AR_SREV_REVISION_9287_10 0
+#define AR_SREV_REVISION_9287_11 1
+#define AR_SREV_REVISION_9287_12 2
+
+/* Bits for AR_AHB_MODE. */
+#define AR_AHB_EXACT_WR_EN 0x00000000
+#define AR_AHB_BUF_WR_EN 0x00000001
+#define AR_AHB_EXACT_RD_EN 0x00000000
+#define AR_AHB_CACHELINE_RD_EN 0x00000002
+#define AR_AHB_PREFETCH_RD_EN 0x00000004
+#define AR_AHB_PAGE_SIZE_1K 0x00000000
+#define AR_AHB_PAGE_SIZE_2K 0x00000008
+#define AR_AHB_PAGE_SIZE_4K 0x00000010
+#define AR_AHB_CUSTOM_BURST_M 0x000000c0
+#define AR_AHB_CUSTOM_BURST_S 6
+#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3
+
+/* Bits for AR_INTR_SYNC_CAUSE. */
+#define AR_INTR_SYNC_RTC_IRQ 0x00000001
+#define AR_INTR_SYNC_MAC_IRQ 0x00000002
+#define AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS 0x00000004
+#define AR_INTR_SYNC_APB_TIMEOUT 0x00000008
+#define AR_INTR_SYNC_PCI_MODE_CONFLICT 0x00000010
+#define AR_INTR_SYNC_HOST1_FATAL 0x00000020
+#define AR_INTR_SYNC_HOST1_PERR 0x00000040
+#define AR_INTR_SYNC_TRCV_FIFO_PERR 0x00000080
+#define AR_INTR_SYNC_RADM_CPL_EP 0x00000100
+#define AR_INTR_SYNC_RADM_CPL_DLLP_ABORT 0x00000200
+#define AR_INTR_SYNC_RADM_CPL_TLP_ABORT 0x00000400
+#define AR_INTR_SYNC_RADM_CPL_ECRC_ERR 0x00000800
+#define AR_INTR_SYNC_RADM_CPL_TIMEOUT 0x00001000
+#define AR_INTR_SYNC_LOCAL_TIMEOUT 0x00002000
+#define AR_INTR_SYNC_PM_ACCESS 0x00004000
+#define AR_INTR_SYNC_MAC_AWAKE 0x00008000
+#define AR_INTR_SYNC_MAC_ASLEEP 0x00010000
+#define AR_INTR_SYNC_MAC_SLEEP_ACCESS 0x00020000
+#define AR_INTR_SYNC_ALL 0x0003ffff
+
+#define AR_INTR_SYNC_DEFAULT \
+ (AR_INTR_SYNC_HOST1_FATAL | \
+ AR_INTR_SYNC_HOST1_PERR | \
+ AR_INTR_SYNC_RADM_CPL_EP | \
+ AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | \
+ AR_INTR_SYNC_RADM_CPL_TLP_ABORT | \
+ AR_INTR_SYNC_RADM_CPL_ECRC_ERR | \
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT | \
+ AR_INTR_SYNC_LOCAL_TIMEOUT | \
+ AR_INTR_SYNC_MAC_SLEEP_ACCESS)
+
+/* Bits for AR_INTR_SYNC_ENABLE. */
+#define AR_INTR_SYNC_ENABLE_GPIO_M 0xfffc0000
+#define AR_INTR_SYNC_ENABLE_GPIO_S 18
+
+/* Bits for AR_INTR_ASYNC_MASK. */
+#define AR_INTR_ASYNC_MASK_GPIO_M 0xfffc0000
+#define AR_INTR_ASYNC_MASK_GPIO_S 18
+
+/* Bits for AR_INTR_SYNC_MASK. */
+#define AR_INTR_SYNC_MASK_GPIO_M 0xfffc0000
+#define AR_INTR_SYNC_MASK_GPIO_S 18
+
+/* Bits for AR_INTR_ASYNC_CAUSE. */
+#define AR_INTR_RTC_IRQ 0x00000001
+#define AR_INTR_MAC_IRQ 0x00000002
+#define AR_INTR_EEP_PROT_ACCESS 0x00000004
+#define AR_INTR_MAC_AWAKE 0x00020000
+#define AR_INTR_MAC_ASLEEP 0x00040000
+#define AR_INTR_SPURIOUS 0xffffffff
+
+/* Bits for AR_INTR_ASYNC_ENABLE. */
+#define AR_INTR_ASYNC_ENABLE_GPIO_M 0xfffc0000
+#define AR_INTR_ASYNC_ENABLE_GPIO_S 18
+
+/* Bits for AR_GPIO_OE_OUT. */
+#define AR_GPIO_OE_OUT_DRV_M 0x00000003
+#define AR_GPIO_OE_OUT_DRV_S 0
+#define AR_GPIO_OE_OUT_DRV_NO 0
+#define AR_GPIO_OE_OUT_DRV_LOW 1
+#define AR_GPIO_OE_OUT_DRV_HI 2
+#define AR_GPIO_OE_OUT_DRV_ALL 3
+
+/* Bits for AR_GPIO_INPUT_EN_VAL. */
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004
+#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400
+#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000
+#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000
+#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
+#define AR_GPIO_JTAG_DISABLE 0x00020000
+
+/* Bits for AR_GPIO_INPUT_MUX1. */
+#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_M 0x00000f00
+#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_M 0x000f0000
+#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16
+
+/* Bits for AR_GPIO_INPUT_MUX2. */
+#define AR_GPIO_INPUT_MUX2_CLK25_M 0x0000000f
+#define AR_GPIO_INPUT_MUX2_CLK25_S 0
+#define AR_GPIO_INPUT_MUX2_RFSILENT_M 0x000000f0
+#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4
+#define AR_GPIO_INPUT_MUX2_RTC_RESET_M 0x00000f00
+#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8
+
+/* Bits for AR_GPIO_OUTPUT_MUX[1-3]. */
+#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1
+#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2
+#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3
+#define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5
+#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6
+
+/* Bits for AR_EEPROM_STATUS_DATA. */
+#define AR_EEPROM_STATUS_DATA_VAL_M 0x0000ffff
+#define AR_EEPROM_STATUS_DATA_VAL_S 0
+#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000
+#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000
+#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000
+#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000
+
+/* Bits for AR_PCIE_MSI. */
+#define AR_PCIE_MSI_ENABLE 0x00000001
+
+/* Bits for AR_RTC_RC. */
+#define AR_RTC_RC_MAC_WARM 0x00000001
+#define AR_RTC_RC_MAC_COLD 0x00000002
+#define AR_RTC_RC_COLD_RESET 0x00000004
+#define AR_RTC_RC_WARM_RESET 0x00000008
+
+/* Bits for AR_RTC_PLL_CONTROL. */
+#define AR_RTC_PLL_DIV_M 0x0000001f
+#define AR_RTC_PLL_DIV_S 0
+#define AR_RTC_PLL_DIV2 0x00000020
+#define AR_RTC_PLL_REFDIV_5 0x000000c0
+#define AR_RTC_PLL_CLKSEL_M 0x00000300
+#define AR_RTC_PLL_CLKSEL_S 8
+#define AR_RTC_9160_PLL_DIV_M 0x000003ff
+#define AR_RTC_9160_PLL_DIV_S 0
+#define AR_RTC_9160_PLL_REFDIV_M 0x00003c00
+#define AR_RTC_9160_PLL_REFDIV_S 10
+#define AR_RTC_9160_PLL_CLKSEL_M 0x0000c000
+#define AR_RTC_9160_PLL_CLKSEL_S 14
+
+/* Bits for AR_RTC_RESET. */
+#define AR_RTC_RESET_EN 0x00000001
+
+/* Bits for AR_RTC_STATUS. */
+#define AR_RTC_STATUS_M 0x0000000f
+#define AR_RTC_STATUS_S 0
+#define AR_RTC_STATUS_SHUTDOWN 0x00000001
+#define AR_RTC_STATUS_ON 0x00000002
+#define AR_RTC_STATUS_SLEEP 0x00000004
+#define AR_RTC_STATUS_WAKEUP 0x00000008
+
+/* Bits for AR_RTC_SLEEP_CLK. */
+#define AR_RTC_FORCE_DERIVED_CLK 0x00000002
+
+/* Bits for AR_RTC_FORCE_WAKE. */
+#define AR_RTC_FORCE_WAKE_EN 0x00000001
+#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002
+
+/*
+ * Analog registers.
+ */
+/* Bits for AR_AN_RF2G1_CH0. */
+#define AR_AN_RF2G1_CH0_OB_M 0x03800000
+#define AR_AN_RF2G1_CH0_OB_S 23
+#define AR_AN_RF2G1_CH0_DB_M 0x1c000000
+#define AR_AN_RF2G1_CH0_DB_S 26
+
+/* Bits for AR_AN_RF5G1_CH0. */
+#define AR_AN_RF5G1_CH0_OB5_M 0x00070000
+#define AR_AN_RF5G1_CH0_OB5_S 16
+#define AR_AN_RF5G1_CH0_DB5_M 0x00380000
+#define AR_AN_RF5G1_CH0_DB5_S 19
+
+/* Bits for AR_AN_RF2G1_CH1. */
+#define AR_AN_RF2G1_CH1_OB_M 0x03800000
+#define AR_AN_RF2G1_CH1_OB_S 23
+#define AR_AN_RF2G1_CH1_DB_M 0x1c000000
+#define AR_AN_RF2G1_CH1_DB_S 26
+
+/* Bits for AR_AN_RF5G1_CH1. */
+#define AR_AN_RF5G1_CH1_OB5_M 0x00070000
+#define AR_AN_RF5G1_CH1_OB5_S 16
+#define AR_AN_RF5G1_CH1_DB5_M 0x00380000
+#define AR_AN_RF5G1_CH1_DB5_S 19
+
+/* Bits for AR_AN_SYNTH9. */
+#define AR_AN_SYNTH9_REFDIVA_M 0xf8000000
+#define AR_AN_SYNTH9_REFDIVA_S 27
+
+/* Bits for AR_AN_TOP1. */
+#define AR_AN_TOP1_DACLPMODE 0x00040000
+
+/* Bits for AR_AN_TOP2. */
+#define AR_AN_TOP2_XPABIAS_LVL_M 0xc0000000
+#define AR_AN_TOP2_XPABIAS_LVL_S 30
+#define AR_AN_TOP2_LOCALBIAS 0x00200000
+#define AR_AN_TOP2_PWDCLKIND 0x00400000
+
+
+/* Bits for AR_STA_ID1. */
+#define AR_STA_ID1_SADH_M 0x0000ffff
+#define AR_STA_ID1_SADH_S 0
+#define AR_STA_ID1_STA_AP 0x00010000
+#define AR_STA_ID1_ADHOC 0x00020000
+#define AR_STA_ID1_PWR_SAV 0x00040000
+#define AR_STA_ID1_KSRCHDIS 0x00080000
+#define AR_STA_ID1_PCF 0x00100000
+#define AR_STA_ID1_USE_DEFANT 0x00200000
+#define AR_STA_ID1_DEFANT_UPDATE 0x00400000
+#define AR_STA_ID1_RTS_USE_DEF 0x00800000
+#define AR_STA_ID1_ACKCTS_6MB 0x01000000
+#define AR_STA_ID1_BASE_RATE_11B 0x02000000
+#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000
+#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000
+#define AR_STA_ID1_KSRCH_MODE 0x10000000
+#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000
+#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000
+#define AR_STA_ID1_MCAST_KSRCH 0x80000000
+
+/* Bits for AR_BSS_ID1. */
+#define AR_BSS_ID1_U16_M 0x0000ffff
+#define AR_BSS_ID1_U16_S 0
+#define AR_BSS_ID1_AID_M 0x07ff0000
+#define AR_BSS_ID1_AID_S 16
+
+/* Bits for AR_TIME_OUT. */
+#define AR_TIME_OUT_ACK_M 0x00003fff
+#define AR_TIME_OUT_ACK_S 0
+#define AR_TIME_OUT_CTS_M 0x3fff0000
+#define AR_TIME_OUT_CTS_S 16
+#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001d56
+
+/* Bits for AR_RSSI_THR. */
+#define AR_RSSI_THR_M 0x000000ff
+#define AR_RSSI_THR_S 0
+#define AR_RSSI_THR_BM_THR_M 0x0000ff00
+#define AR_RSSI_THR_BM_THR_S 8
+#define AR_RSSI_BCN_WEIGHT_M 0x1f000000
+#define AR_RSSI_BCN_WEIGHT_S 24
+#define AR_RSSI_BCN_RSSI_RST 0x20000000
+
+/* Bits for AR_USEC. */
+#define AR_USEC_USEC_M 0x0000007f
+#define AR_USEC_USEC_S 0
+#define AR_USEC_TX_LAT_M 0x007fc000
+#define AR_USEC_TX_LAT_S 14
+#define AR_USEC_RX_LAT_M 0x1f800000
+#define AR_USEC_RX_LAT_S 23
+#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074
+
+/* Bits for AR_RESET_TSF. */
+#define AR_RESET_TSF_ONCE 0x01000000
+
+/* Bits for AR_RX_FILTER. */
+#define AR_RX_FILTER_UCAST 0x00000001
+#define AR_RX_FILTER_MCAST 0x00000002
+#define AR_RX_FILTER_BCAST 0x00000004
+#define AR_RX_FILTER_CONTROL 0x00000008
+#define AR_RX_FILTER_BEACON 0x00000010
+#define AR_RX_FILTER_PROM 0x00000020
+#define AR_RX_FILTER_PROBEREQ 0x00000080
+#define AR_RX_FILTER_MYBEACON 0x00000200
+#define AR_RX_FILTER_COMPR_BAR 0x00000400
+#define AR_RX_FILTER_PSPOLL 0x00004000
+
+/* Bits for AR_DIAG_SW. */
+#define AR_DIAG_CACHE_ACK 0x00000001
+#define AR_DIAG_ACK_DIS 0x00000002
+#define AR_DIAG_CTS_DIS 0x00000004
+#define AR_DIAG_ENCRYPT_DIS 0x00000008
+#define AR_DIAG_DECRYPT_DIS 0x00000010
+#define AR_DIAG_RX_DIS 0x00000020
+#define AR_DIAG_LOOP_BACK 0x00000040
+#define AR_DIAG_CORR_FCS 0x00000080
+#define AR_DIAG_CHAN_INFO 0x00000100
+#define AR_DIAG_SCRAM_SEED_M 0x0001fe00
+#define AR_DIAG_SCRAM_SEED_S 8 /* XXX zarb devrait etre 9? */
+#define AR_DIAG_FRAME_NV0 0x00020000
+#define AR_DIAG_OBS_PT_SEL1_M 0x000c0000
+#define AR_DIAG_OBS_PT_SEL1_S 18
+#define AR_DIAG_FORCE_RX_CLEAR 0x00100000
+#define AR_DIAG_IGNORE_VIRT_CS 0x00200000
+#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000
+#define AR_DIAG_EIFS_CTRL_ENA 0x00800000
+#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000
+#define AR_DIAG_RX_ABORT 0x02000000
+#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000
+#define AR_DIAG_OBS_PT_SEL2 0x08000000
+#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000
+#define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000
+
+/* Bits for AR_AES_MUTE_MASK0. */
+#define AR_AES_MUTE_MASK0_FC_M 0x0000ffff
+#define AR_AES_MUTE_MASK0_FC_S 0
+#define AR_AES_MUTE_MASK0_QOS_M 0xffff0000
+#define AR_AES_MUTE_MASK0_QOS_S 16
+
+/* Bits for AR_AES_MUTE_MASK1. */
+#define AR_AES_MUTE_MASK1_SEQ_M 0x0000ffff
+#define AR_AES_MUTE_MASK1_SEQ_S 0
+#define AR_AES_MUTE_MASK1_FC_MGMT_M 0xffff0000
+#define AR_AES_MUTE_MASK1_FC_MGMT_S 16
+#define AR_AES_MUTE_MASK1_FC0_MGMT_M 0x00ff0000
+#define AR_AES_MUTE_MASK1_FC0_MGMT_S 16
+#define AR_AES_MUTE_MASK1_FC1_MGMT_M 0xff000000
+#define AR_AES_MUTE_MASK1_FC1_MGMT_S 24
+
+/* Bits for AR_GATED_CLKS. */
+#define AR_GATED_CLKS_TX 0x00000002
+#define AR_GATED_CLKS_RX 0x00000004
+#define AR_GATED_CLKS_REG 0x00000008
+
+/* Bits for AR_OBS_BUS_CTRL. */
+#define AR_OBS_BUS_SEL_1 0x00040000
+#define AR_OBS_BUS_SEL_2 0x00080000
+#define AR_OBS_BUS_SEL_3 0x000c0000
+#define AR_OBS_BUS_SEL_4 0x08040000
+#define AR_OBS_BUS_SEL_5 0x08080000
+
+/* Bits for AR_OBS_BUS_1. */
+#define AR_OBS_BUS_1_PCU 0x00000001
+#define AR_OBS_BUS_1_RX_END 0x00000002
+#define AR_OBS_BUS_1_RX_WEP 0x00000004
+#define AR_OBS_BUS_1_RX_BEACON 0x00000008
+#define AR_OBS_BUS_1_RX_FILTER 0x00000010
+#define AR_OBS_BUS_1_TX_HCF 0x00000020
+#define AR_OBS_BUS_1_QUIET_TIME 0x00000040
+#define AR_OBS_BUS_1_CHAN_IDLE 0x00000080
+#define AR_OBS_BUS_1_TX_HOLD 0x00000100
+#define AR_OBS_BUS_1_TX_FRAME 0x00000200
+#define AR_OBS_BUS_1_RX_FRAME 0x00000400
+#define AR_OBS_BUS_1_RX_CLEAR 0x00000800
+#define AR_OBS_BUS_1_WEP_STATE_M 0x0003f000
+#define AR_OBS_BUS_1_WEP_STATE_S 12
+#define AR_OBS_BUS_1_RX_STATE_M 0x01f00000
+#define AR_OBS_BUS_1_RX_STATE_S 20
+#define AR_OBS_BUS_1_TX_STATE_M 0x7e000000
+#define AR_OBS_BUS_1_TX_STATE_S 25
+
+/* Bits for AR_SLEEP1. */
+#define AR_SLEEP1_ASSUME_DTIM 0x00080000
+#define AR_SLEEP1_CAB_TIMEOUT_M 0xffe00000
+#define AR_SLEEP1_CAB_TIMEOUT_S 21
+/* Default value. */
+#define AR_CAB_TIMEOUT_VAL 10
+
+/* Bits for AR_SLEEP2. */
+#define AR_SLEEP2_BEACON_TIMEOUT_M 0xffe00000
+#define AR_SLEEP2_BEACON_TIMEOUT_S 21
+
+/* Bits for AR_TPC. */
+#define AR_TPC_ACK_M 0x0000003f
+#define AR_TPC_ACK_S 0
+#define AR_TPC_CTS_M 0x00003f00
+#define AR_TPC_CTS_S 8
+#define AR_TPC_CHIRP_M 0x003f0000
+#define AR_TPC_CHIRP_S 16
+
+/* Bits for AR_QUIET1. */
+#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
+#define AR_QUIET1_NEXT_QUIET_S 0
+#define AR_QUIET1_QUIET_ENABLE 0x00010000
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000
+
+/* Bits for AR_QUIET2. */
+#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff
+#define AR_QUIET2_QUIET_PERIOD_S 0
+#define AR_QUIET2_QUIET_DUR_M 0xffff0000
+#define AR_QUIET2_QUIET_DUR_S 16
+
+/* Bits for AR_TSF_PARM. */
+#define AR_TSF_INCREMENT_M 0x000000ff
+#define AR_TSF_INCREMENT_S 0
+
+/* Bits for AR_QOS_NO_ACK. */
+#define AR_QOS_NO_ACK_TWO_BIT_M 0x0000000f
+#define AR_QOS_NO_ACK_TWO_BIT_S 0
+#define AR_QOS_NO_ACK_BIT_OFF_M 0x0000007f
+#define AR_QOS_NO_ACK_BIT_OFF_S 4
+#define AR_QOS_NO_ACK_BYTE_OFF_M 0x00000180
+#define AR_QOS_NO_ACK_BYTE_OFF_S 7
+
+/* Bits for AR_PHY_ERR. */
+#define AR_PHY_ERR_DCHIRP 0x00000008
+#define AR_PHY_ERR_RADAR 0x00000020
+#define AR_PHY_ERR_OFDM_TIMING 0x00020000
+#define AR_PHY_ERR_CCK_TIMING 0x02000000
+
+/* Bits for AR_PCU_MISC. */
+#define AR_PCU_FORCE_BSSID_MATCH 0x00000001
+#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004
+#define AR_PCU_TX_ADD_TSF 0x00000008
+#define AR_PCU_CCK_SIFS_MODE 0x00000010
+#define AR_PCU_RX_ANT_UPDT 0x00000800
+#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000
+#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000
+#define AR_PCU_BUG_12306_FIX_ENA 0x00020000
+#define AR_PCU_FORCE_QUIET_COLL 0x00040000
+#define AR_PCU_BT_ANT_PREVENT_RX 0x00100000
+#define AR_PCU_TBTT_PROTECT 0x00200000
+#define AR_PCU_CLEAR_VMF 0x01000000
+#define AR_PCU_CLEAR_BA_VALID 0x04000000
+
+/* Bits for AR_BT_COEX_MODE. */
+#define AR_BT_TIME_EXTEND_M 0x000000ff
+#define AR_BT_TIME_EXTEND_S 0
+#define AR_BT_TXSTATE_EXTEND 0x00000100
+#define AR_BT_TX_FRAME_EXTEND 0x00000200
+#define AR_BT_MODE_M 0x00000c00
+#define AR_BT_MODE_S 10
+#define AR_BT_MODE_LEGACY 0
+#define AR_BT_MODE_UNSLOTTED 1
+#define AR_BT_MODE_SLOTTED 2
+#define AR_BT_MODE_DISABLED 3
+#define AR_BT_QUIET 0x00001000
+#define AR_BT_QCU_THRESH_M 0x0001e000
+#define AR_BT_QCU_THRESH_S 13
+#define AR_BT_RX_CLEAR_POLARITY 0x00020000
+#define AR_BT_PRIORITY_TIME_M 0x00fc0000
+#define AR_BT_PRIORITY_TIME_S 18
+#define AR_BT_FIRST_SLOT_TIME_M 0xff000000
+#define AR_BT_FIRST_SLOT_TIME_S 24
+
+/* Bits for AR_BT_COEX_WEIGHT. */
+#define AR_BTCOEX_BT_WGHT_M 0x0000ffff
+#define AR_BTCOEX_BT_WGHT_S 0
+#define AR_STOMP_LOW_BT_WGHT 0xff55
+#define AR_BTCOEX_WL_WGHT_M 0xffff0000
+#define AR_BTCOEX_WL_WGHT_S 16
+#define AR_STOMP_LOW_WL_WGHT 0xaaa8
+
+/* Bits for AR_BT_COEX_MODE2. */
+#define AR_BT_BCN_MISS_THRESH_M 0x000000ff
+#define AR_BT_BCN_MISS_THRESH_S 0
+#define AR_BT_BCN_MISS_CNT_M 0x0000ff00
+#define AR_BT_BCN_MISS_CNT_S 8
+#define AR_BT_HOLD_RX_CLEAR 0x00010000
+#define AR_BT_DISABLE_BT_ANT 0x00100000
+
+/* Bits for AR_PCU_TXBUF_CTRL. */
+#define AR_PCU_TXBUF_CTRL_SIZE_M 0x000007ff
+#define AR_PCU_TXBUF_CTRL_SIZE_S 0
+#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700
+#define AR9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380
+
+/* Bits for AR_PCU_MISC_MODE2. */
+#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002
+#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004
+#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040
+#define AR_PCU_MISC_MODE2_CFP_IGNORE 0x00000080
+#define AR_PCU_MISC_MODE2_MGMT_QOS_M 0x0000ff00
+#define AR_PCU_MISC_MODE2_MGMT_QOS_S 8
+#define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DUR 0x00010000
+#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000
+#define AR_PCU_MISC_MODE2_HWWAR1 0x00100000
+#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
+
+/* Bits for AR_MAC_PCU_LOGIC_ANALYZER. */
+#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000
+
+/* Bits for AR_MAC_PCU_ASYNC_FIFO_REG3. */
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
+#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+
+/* Bits for AR_PHY_ERR_[123]. */
+#define AR_PHY_ERR_COUNT_M 0x00ffffff
+#define AR_PHY_ERR_COUNT_S 0
+
+/* Bits for AR_TSFOOR_THRESHOLD. */
+#define AR_TSFOOR_THRESHOLD_VAL_M 0x0000ffff
+#define AR_TSFOOR_THRESHOLD_VAL_S 0
+
+/* Bit for AR_TXSIFS. */
+#define AR_TXSIFS_TIME_M 0x000000ff
+#define AR_TXSIFS_TIME_S 0
+#define AR_TXSIFS_TX_LATENCY_M 0x00000f00
+#define AR_TXSIFS_TX_LATENCY_S 8
+#define AR_TXSIFS_ACK_SHIFT_M 0x00007000
+#define AR_TXSIFS_ACK_SHIFT_S 12
+
+/* Bits for AR_TXOP_X. */
+#define AR_TXOP_X_VAL 0x000000ff
+
+/* Bits for AR_TIMER_MODE. */
+#define AR_TBTT_TIMER_EN 0x00000001
+#define AR_DBA_TIMER_EN 0x00000002
+#define AR_SWBA_TIMER_EN 0x00000004
+#define AR_HCF_TIMER_EN 0x00000008
+#define AR_TIM_TIMER_EN 0x00000010
+#define AR_DTIM_TIMER_EN 0x00000020
+#define AR_QUIET_TIMER_EN 0x00000040
+#define AR_NDP_TIMER_EN 0x00000080
+#define AR_TIMER_OVERFLOW_INDEX_M 0x00000700
+#define AR_TIMER_OVERFLOW_INDEX_S 8
+#define AR_TIMER_THRESH_M 0xfffff000
+#define AR_TIMER_THRESH_S 12
+
+/* Bits for AR_SLP32_MODE. */
+#define AR_SLP32_HALF_CLK_LATENCY_M 0x000fffff
+#define AR_SLP32_HALF_CLK_LATENCY_S 0
+#define AR_SLP32_ENA 0x00100000
+#define AR_SLP32_TSF_WRITE_STATUS 0x00200000
+
+/* Bits for AR_SLP32_WAKE. */
+#define AR_SLP32_WAKE_XTL_TIME_M 0x0000ffff
+#define AR_SLP32_WAKE_XTL_TIME_S 0
+
+/* Bits for AR_SLP_MIB_CTRL. */
+#define AR_SLP_MIB_CLEAR 0x00000001
+#define AR_SLP_MIB_PENDING 0x00000002
+
+/* Bits for AR_2040_MODE. */
+#define AR_2040_JOINED_RX_CLEAR 0x00000001
+
+/* Bits for AR_KEYTABLE_TYPE. */
+#define AR_KEYTABLE_TYPE_M 0x00000007
+#define AR_KEYTABLE_TYPE_S 0
+#define AR_KEYTABLE_TYPE_40 0
+#define AR_KEYTABLE_TYPE_104 1
+#define AR_KEYTABLE_TYPE_128 3
+#define AR_KEYTABLE_TYPE_TKIP 4
+#define AR_KEYTABLE_TYPE_AES 5
+#define AR_KEYTABLE_TYPE_CCM 6
+#define AR_KEYTABLE_TYPE_CLR 7
+#define AR_KEYTABLE_ANT 0x00000008
+#define AR_KEYTABLE_VALID 0x00008000
+
+
+
+/* Bits for AR_PHY_TEST. */
+#define AR_PHY_TEST_RFSILENT_BB 0x00002000
+#define AR_PHY_TEST_AGC_CLR 0x10000000
+
+/* Bits for AR_PHY_TURBO. */
+#define AR_PHY_FC_TURBO_MODE 0x00000001
+#define AR_PHY_FC_TURBO_SHORT 0x00000002
+#define AR_PHY_FC_DYN2040_EN 0x00000004
+#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
+#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
+#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
+#define AR_PHY_FC_HT_EN 0x00000040
+#define AR_PHY_FC_SHORT_GI_40 0x00000080
+#define AR_PHY_FC_WALSH 0x00000100
+#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
+#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
+
+/* Bits for AR_PHY_TIMING3. */
+#define AR_PHY_TIMING3_DSC_MAN_M 0xfffe0000
+#define AR_PHY_TIMING3_DSC_MAN_S 17
+#define AR_PHY_TIMING3_DSC_EXP_M 0x0001e000
+#define AR_PHY_TIMING3_DSC_EXP_S 13
+
+/* Bits for AR_PHY_CHIP_ID. */
+#define AR_PHY_CHIP_ID_REV_0 0x80
+#define AR_PHY_CHIP_ID_REV_1 0x81
+#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
+
+/* Bits for AR_PHY_ACTIVE. */
+#define AR_PHY_ACTIVE_EN 0x00000001
+#define AR_PHY_ACTIVE_DIS 0x00000000
+
+/* Bits for AR_PHY_RF_CTL2. */
+#define AR_PHY_TX_END_DATA_START_M 0x000000ff
+#define AR_PHY_TX_END_DATA_START_S 0
+#define AR_PHY_TX_END_PA_ON_M 0x0000ff00
+#define AR_PHY_TX_END_PA_ON_S 8
+
+/* Bits for AR_PHY_RF_CTL3. */
+#define AR_PHY_TX_END_TO_A2_RX_ON_M 0x00ff0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
+
+/* Bits for AR_PHY_ADC_CTL. */
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_M 0x00000003
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
+#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
+#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
+#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN_M 0x00030000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
+
+/* Bits for AR_PHY_ADC_SERIAL_CTL. */
+#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
+
+/* Bits for AR_PHY_RF_CTL4. */
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_M 0xff000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_M 0x00ff0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_M 0x0000ff00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_M 0x000000ff
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
+
+/* Bits for AR_PHY_SETTLING. */
+#define AR_PHY_SETTLING_SWITCH_M 0x00003f80
+#define AR_PHY_SETTLING_SWITCH_S 7
+
+/* Bits for AR_PHY_RXGAIN. */
+#define AR_PHY_RXGAIN_TXRX_ATTEN_M 0x0003f000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_M 0x007c0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_M 0x00003f80
+#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_M 0x001fc000
+#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
+
+/* Bits for AR_PHY_DESIRED_SZ. */
+#define AR_PHY_DESIRED_SZ_ADC_M 0x000000ff
+#define AR_PHY_DESIRED_SZ_ADC_S 0
+#define AR_PHY_DESIRED_SZ_PGA_M 0x0000ff00
+#define AR_PHY_DESIRED_SZ_PGA_S 8
+#define AR_PHY_DESIRED_SZ_TOT_DES_M 0x0ff00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+
+/* Bits for AR_PHY_FIND_SIG. */
+#define AR_PHY_FIND_SIG_FIRSTEP_M 0x0003f000
+#define AR_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR_PHY_FIND_SIG_FIRPWR_M 0x03fc0000
+#define AR_PHY_FIND_SIG_FIRPWR_S 18
+
+/* Bits for AR_PHY_AGC_CTL1. */
+#define AR_PHY_AGC_CTL1_COARSE_LOW_M 0x00007f80
+#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
+#define AR_PHY_AGC_CTL1_COARSE_HIGH_M 0x003f8000
+#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
+
+/* Bits for AR_PHY_AGC_CONTROL. */
+#define AR_PHY_AGC_CONTROL_CAL 0x00000001
+#define AR_PHY_AGC_CONTROL_NF 0x00000002
+#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000
+#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000
+#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
+
+/* Bits for AR_PHY_CCA. */
+#define AR_PHY_MAXCCA_PWR_M 0x000001ff
+#define AR_PHY_MAXCCA_PWR_S 0
+#define AR_PHY_MINCCA_PWR_M 0x0ff80000
+#define AR_PHY_MINCCA_PWR_S 19
+#define AR_PHY_CCA_THRESH62_M 0x0007f000
+#define AR_PHY_CCA_THRESH62_S 12
+#define AR9280_PHY_MINCCA_PWR_M 0x1ff00000
+#define AR9280_PHY_MINCCA_PWR_S 20
+#define AR9280_PHY_CCA_THRESH62_M 0x000ff000
+#define AR9280_PHY_CCA_THRESH62_S 12
+
+/* Bits for AR_PHY_SFCORR_LOW. */
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_M 0x00003f00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_M 0x001fc000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_M 0x0fe00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
+
+/* Bits for AR_PHY_SFCORR. */
+#define AR_PHY_SFCORR_M2COUNT_THR_M 0x0000001f
+#define AR_PHY_SFCORR_M2COUNT_THR_S 0
+#define AR_PHY_SFCORR_M1_THRESH_M 0x00fe0000
+#define AR_PHY_SFCORR_M1_THRESH_S 17
+#define AR_PHY_SFCORR_M2_THRESH_M 0x7f000000
+#define AR_PHY_SFCORR_M2_THRESH_S 24
+
+/* Bits for AR_PHY_PLL_CTL. */
+#define AR_PHY_PLL_CTL_40 0xaa
+#define AR_PHY_PLL_CTL_40_5413 0x04
+#define AR_PHY_PLL_CTL_44 0xab
+#define AR_PHY_PLL_CTL_44_2133 0xeb
+#define AR_PHY_PLL_CTL_40_2133 0xea
+
+#define AR_PHY_RX_DELAY_DELAY_M 0x00003fff
+#define AR_PHY_RX_DELAY_DELAY_S 0
+
+/* Bits for AR_PHY_TIMING_CTRL4_0. */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_M 0x0000001f
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_M 0x000007e0
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x00000800
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_M 0x0000f000
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
+#define AR_PHY_TIMING_CTRL4_DO_CAL 0x00010000
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
+#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
+
+/* Bits for AR_PHY_TIMING5. */
+#define AR_PHY_TIMING5_CYCPWR_THR1_M 0x000000fe
+#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
+
+/* Bits for AR_PHY_POWER_TX_RATE_MAX. */
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+
+/* Bits for AR_PHY_FRAME_CTL. */
+#define AR_PHY_FRAME_CTL_TX_CLIP_M 0x00000038
+#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
+
+/* Bits for AR_PHY_TXPWRADJ. */
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_M 0x00000fc0
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_M 0x00fc0000
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
+
+/* Bits for AR_PHY_RADAR_EXT. */
+#define AR_PHY_RADAR_EXT_ENA 0x00004000
+
+/* Bits for AR_PHY_RADAR_0. */
+#define AR_PHY_RADAR_0_ENA 0x00000001
+#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
+#define AR_PHY_RADAR_0_INBAND_M 0x0000003e
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI_M 0x00000fc0
+#define AR_PHY_RADAR_0_PRSSI_S 6
+#define AR_PHY_RADAR_0_HEIGHT_M 0x0003f000
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI_M 0x00fc0000
+#define AR_PHY_RADAR_0_RRSSI_S 18
+#define AR_PHY_RADAR_0_FIRPWR_M 0x7f000000
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+
+/* Bits for AR_PHY_RADAR_1. */
+#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_M 0x003f0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
+#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_M 0x00001f00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN_M 0x000000ff
+#define AR_PHY_RADAR_1_MAXLEN_S 0
+
+/* Bits for AR_PHY_SIGMA_DELTA. */
+#define AR_PHY_SIGMA_DELTA_ADC_SEL_M 0x00000003
+#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR_PHY_SIGMA_DELTA_FILT2_M 0x000000f8
+#define AR_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR_PHY_SIGMA_DELTA_FILT1_M 0x00001f00
+#define AR_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP_M 0x01ffe000
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+/* Bits for AR_PHY_RESTART. */
+#define AR_PHY_RESTART_DIV_GC_M 0x001c0000
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+/* Bits for AR_PHY_RFBUS_REQ. */
+#define AR_PHY_RFBUS_REQ_EN 0x00000001
+
+#define AR_PHY_TIMING8_PILOT_MASK_2_M 0x000fffff
+#define AR_PHY_TIMING8_PILOT_MASK_2_S 0
+
+#define AR_PHY_BIN_MASK2_4_MASK_4_M 0x00003fff
+#define AR_PHY_BIN_MASK2_4_MASK_4_S 0
+
+#define AR_PHY_TIMING10_PILOT_MASK_2_M 0x000fffff
+#define AR_PHY_TIMING10_PILOT_MASK_2_S 0
+
+/* Bits for AR_PHY_TIMING11. */
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_M 0x000fffff
+#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
+#define AR_PHY_TIMING11_SPUR_FREQ_SD_M 0x3ff00000
+#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
+#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
+#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
+
+/* Bits for AR_PHY_NEW_ADC_DC_GAIN_CORR(). */
+#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
+#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
+
+/* Bits for AR_PHY_EXT_CCA0. */
+#define AR_PHY_EXT_CCA0_THRESH62_M 0x000000ff
+#define AR_PHY_EXT_CCA0_THRESH62_S 0
+
+/* Bits for AR_PHY_EXT_CCA. */
+#define AR_PHY_EXT_MAXCCA_PWR_M 0x000001ff
+#define AR_PHY_EXT_MAXCCA_PWR_S 0
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_M 0x0000fe00
+#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9
+#define AR_PHY_EXT_CCA_THRESH62_M 0x007f0000
+#define AR_PHY_EXT_CCA_THRESH62_S 16
+#define AR_PHY_EXT_MINCCA_PWR_M 0xff800000
+#define AR_PHY_EXT_MINCCA_PWR_S 23
+#define AR9280_PHY_EXT_MINCCA_PWR_M 0x01ff0000
+#define AR9280_PHY_EXT_MINCCA_PWR_S 16
+
+/* Bits for AR_PHY_SFCORR_EXT. */
+#define AR_PHY_SFCORR_EXT_M1_THRESH_M 0x0000007f
+#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
+#define AR_PHY_SFCORR_EXT_M2_THRESH_M 0x00003f80
+#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_M 0x001fc000
+#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_M 0x0fe00000
+#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_M 0xf0000000
+#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
+
+/* Bits for AR_PHY_HALFGI. */
+#define AR_PHY_HALFGI_DSC_EXP_M 0x0000000f
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+#define AR_PHY_HALFGI_DSC_MAN_M 0x0007fff0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+
+#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
+
+/* Bits for AR_PHY_CALMODE. */
+#define AR_PHY_CALMODE_IQ 0x00000000
+#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
+#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
+#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
+
+/* Bits for AR_PHY_RFBUS_GRANT. */
+#define AR_PHY_RFBUS_GRANT_EN 0x00000001
+
+#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
+/* Bits for AR_PHY_MODE. */
+#define AR_PHY_MODE_ASYNCFIFO 0x00000080
+#define AR_PHY_MODE_AR2133 0x00000008
+#define AR_PHY_MODE_AR5111 0x00000000
+#define AR_PHY_MODE_AR5112 0x00000008
+#define AR_PHY_MODE_DYNAMIC 0x00000004
+#define AR_PHY_MODE_RF2GHZ 0x00000002
+#define AR_PHY_MODE_RF5GHZ 0x00000000
+#define AR_PHY_MODE_CCK 0x00000001
+#define AR_PHY_MODE_OFDM 0x00000000
+#define AR_PHY_MODE_DYN_CCK_DISABLE 0x00000100
+
+/* Bits for AR_PHY_CCK_TX_CTRL. */
+#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_M 0x0000000c
+#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
+
+/* Bits for AR_PHY_CCK_DETECT. */
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_M 0x0000003f
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_M 0x00001fc0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x00002000
+
+/* Bits for AR_PHY_GAIN_2GHZ. */
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_M 0x00fc0000
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_M 0x00003c00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_M 0x0000001f
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_M 0x003e0000
+#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_M 0x0001f000
+#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_M 0x00000fc0
+#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_M 0x0000003f
+#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
+
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_M 0x01f80000
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
+
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_M 0x0001fc00
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
+
+#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
+
+/* Bits for AR_PHY_TPCRG1. */
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_M 0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+#define AR_PHY_TPCRG1_PD_GAIN_1_M 0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
+#define AR_PHY_TPCRG1_PD_GAIN_2_M 0x000c0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
+#define AR_PHY_TPCRG1_PD_GAIN_3_M 0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
+#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
+
+#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_M 0x000001fe
+#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
+
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_M 0x03000000
+#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
+
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_M 0x01f80000
+#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
+
+#define AR_PHY_TX_DESIRED_SCALE_CCK_M 0x0000003e
+#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
+
+/* Bits for AR_PHY_TX_PWRCTRL9. */
+#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
+
+/* Bits for AR_PHY_TX_GAIN_TBL. */
+#define AR_PHY_TX_GAIN_M 0x0007f000
+#define AR_PHY_TX_GAIN_S 12
+
+/* Bits for AR_PHY_SPUR_REG. */
+#define AR_PHY_SPUR_REG_MASK_RATE_CNTL 0x03fc0000
+#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x00020000
+#define AR_PHY_SPUR_REG_MASK_RATE_SELECT 0x0001fe00
+#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x00000100
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_M 0x0000007f
+#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
+#define AR_SPUR_RSSI_THRESH 40
+
+/* Bits for AR_PHY_ANALOG_SWAP. */
+#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
+
+/* Bits for AR_PHY_TPCRG5. */
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_M 0x0000000f
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_M 0x000003f0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_M 0x0000fc00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_M 0x003f0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_M 0x0fc00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
+
+/* Bits for AR_PHY_CL_CAL_CTL. */
+#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
+#define AR_PHY_CL_CAL_ENABLE 0x00000002
+
+/* Bits for AR_PHY_XPA_CFG. */
+#define AR_PHY_FORCE_XPA_CFG 0x000000001
+
+/* Bits for AR_PHY_CH[01]_TX_PWRCTRL11. */
+#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_M 0x0000fc00
+#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
+#define AR_PHY_TX_PWRCTRL_OLPC_PWR_M 0x00ff0000
+#define AR_PHY_TX_PWRCTRL_OLPC_PWR_S 16
+
+/* Bits for AR_PHY_NEW_ADC_DC_GAIN_CORR. */
+#define AR_PHY_NEW_ADC_DC_GAIN_QGAIN_M 0x0000003f
+#define AR_PHY_NEW_ADC_DC_GAIN_QGAIN_S 0
+#define AR_PHY_NEW_ADC_DC_GAIN_IGAIN_M 0x00000fc0
+#define AR_PHY_NEW_ADC_DC_GAIN_IGAIN_S 6
+#define AR_PHY_NEW_ADC_DC_GAIN_QDC_M 0x001ff000
+#define AR_PHY_NEW_ADC_DC_GAIN_QDC_S 12
+#define AR_PHY_NEW_ADC_DC_GAIN_IDC_M 0x3fe00000
+#define AR_PHY_NEW_ADC_DC_GAIN_IDC_S 21
+
+#define AR_BASE_PHY_ACTIVE_DELAY 100
+
+#define AR_CLOCK_RATE_CCK 22
+#define AR_CLOCK_RATE_5GHZ_OFDM 40
+#define AR_CLOCK_RATE_2GHZ_OFDM 44
+
+#define AR_PWR_DECREASE_FOR_2_CHAIN 6 /* 10 * log10(2) * 2 */
+#define AR_PWR_DECREASE_FOR_3_CHAIN 9 /* 10 * log10(3) * 2 */
+
+#define AR_SLEEP_SLOP 3 /* TUs */
+
+#define AR_MIN_BEACON_TIMEOUT_VAL 1
+#define AR_FUDGE 2
+/* Divides by 1024 (usecs to TU) without doing 64-bit arithmetic. */
+#define AR_TSF_TO_TU(hi, lo) ((hi) << 22 | (lo) >> 10)
+
+#define AR_KEY_CACHE_SIZE 128
+#define AR_RSVD_KEYTABLE_ENTRIES 4
+
+#define AR_CAL_SAMPLES 64 /* XXX AR9280? */
+#define AR_MAX_LOG_CAL 2 /* XXX AR9280? */
+
+/*
+ * Tx DMA descriptor.
+ */
+struct ar_tx_desc {
+ uint32_t ds_link;
+ uint32_t ds_data;
+ uint32_t ds_ctl0;
+ uint32_t ds_ctl1;
+ uint32_t ds_ctl2;
+ uint32_t ds_ctl3;
+ uint32_t ds_ctl4;
+ uint32_t ds_ctl5;
+ uint32_t ds_ctl6;
+ uint32_t ds_ctl7;
+ uint32_t ds_ctl8;
+ uint32_t ds_ctl9;
+ uint32_t ds_ctl10;
+ uint32_t ds_ctl11;
+ uint32_t ds_status0;
+ uint32_t ds_status1;
+ uint32_t ds_tstamp;
+ uint32_t ds_ba_bitmap_lo;
+ uint32_t ds_ba_bitmap_hi;
+ uint32_t ds_evm0;
+ uint32_t ds_evm1;
+ uint32_t ds_evm2;
+ uint32_t ds_status8;
+ uint32_t ds_status9;
+ /*
+ * Padding to make Tx descriptors 128 bytes such that they will
+ * not cross a 4KB boundary.
+ */
+ uint32_t pad[8];
+} __packed;
+
+/* Bits for ds_ctl0. */
+#define AR_TXC0_FRAME_LEN_M 0x00000fff
+#define AR_TXC0_FRAME_LEN_S 0
+#define AR_TXC0_VIRT_MORE_FRAG 0x00001000
+#define AR_TXC0_XMIT_POWER_M 0x003f0000
+#define AR_TXC0_XMIT_POWER_S 16
+#define AR_TXC0_RTS_ENABLE 0x00400000
+#define AR_TXC0_VEOL 0x00800000
+#define AR_TXC0_CLR_DEST_MASK 0x01000000
+#define AR_TXC0_INTR_REQ 0x20000000
+#define AR_TXC0_DEST_IDX_VALID 0x40000000
+#define AR_TXC0_CTS_ENABLE 0x80000000
+
+/* Bits for ds_ctl1. */
+#define AR_TXC1_BUF_LEN_M 0x00000fff
+#define AR_TXC1_BUF_LEN_S 0
+#define AR_TXC1_MORE 0x00001000
+#define AR_TXC1_DEST_IDX_M 0x000fe000
+#define AR_TXC1_DEST_IDX_S 13
+#define AR_TXC1_FRAME_TYPE_M 0x00f00000
+#define AR_TXC1_FRAME_TYPE_S 20
+#define AR_FRAME_TYPE_NORMAL 0
+#define AR_FRAME_TYPE_ATIM 1
+#define AR_FRAME_TYPE_PSPOLL 2
+#define AR_FRAME_TYPE_BEACON 3
+#define AR_FRAME_TYPE_PROBE_RESP 4
+#define AR_TXC1_NO_ACK 0x01000000
+#define AR_TXC1_INSERT_TS 0x02000000
+#define AR_TXC1_EXT_ONLY 0x08000000
+#define AR_TXC1_EXT_AND_CTL 0x10000000
+#define AR_TXC1_MORE_AGGR 0x20000000
+#define AR_TXC1_IS_AGGR 0x40000000
+
+/* Bits for ds_ctl2. */
+#define AR_TXC2_BURST_DUR_M 0x00007fff
+#define AR_TXC2_BURST_DUR_S 0
+#define AR_TXC2_DUR_UPDATE_ENA 0x00008000
+#define AR_TXC2_XMIT_DATA_TRIES0_M 0x000f0000
+#define AR_TXC2_XMIT_DATA_TRIES0_S 16
+#define AR_TXC2_XMIT_DATA_TRIES1_M 0x00f00000
+#define AR_TXC2_XMIT_DATA_TRIES1_S 20
+#define AR_TXC2_XMIT_DATA_TRIES2_M 0x0f000000
+#define AR_TXC2_XMIT_DATA_TRIES2_S 24
+#define AR_TXC2_XMIT_DATA_TRIES3_M 0xf0000000
+#define AR_TXC2_XMIT_DATA_TRIES3_S 28
+
+/* Bits for ds_ctl3. */
+#define AR_TXC3_XMIT_RATE0_M 0x000000ff
+#define AR_TXC3_XMIT_RATE0_S 0
+#define AR_TXC3_XMIT_RATE1_M 0x0000ff00
+#define AR_TXC3_XMIT_RATE1_S 8
+#define AR_TXC3_XMIT_RATE2_M 0x00ff0000
+#define AR_TXC3_XMIT_RATE2_S 16
+#define AR_TXC3_XMIT_RATE3_M 0xff000000
+#define AR_TXC3_XMIT_RATE3_S 24
+
+/* Bits for ds_ctl4. */
+#define AR_TXC4_PACKET_DUR0_M 0x00007fff
+#define AR_TXC4_PACKET_DUR0_S 0
+#define AR_TXC4_RTSCTS_QUAL0 0x00008000
+#define AR_TXC4_PACKET_DUR1_M 0x7fff0000
+#define AR_TXC4_PACKET_DUR1_S 16
+#define AR_TXC4_RTSCTS_QUAL1 0x80000000
+/* Shortcut. */
+#define AR_TXC4_RTSCTS_QUAL01 \
+ (AR_TXC4_RTSCTS_QUAL0 | AR_TXC4_RTSCTS_QUAL1)
+
+/* Bits for ds_ctl5. */
+#define AR_TXC5_PACKET_DUR2_M 0x00007fff
+#define AR_TXC5_PACKET_DUR2_S 0
+#define AR_TXC5_RTSCTS_QUAL2 0x00008000
+#define AR_TXC5_PACKET_DUR3_M 0x7fff0000
+#define AR_TXC5_PACKET_DUR3_S 16
+#define AR_TXC5_RTSCTS_QUAL3 0x80000000
+/* Shortcut. */
+#define AR_TXC5_RTSCTS_QUAL23 \
+ (AR_TXC5_RTSCTS_QUAL2 | AR_TXC5_RTSCTS_QUAL3)
+
+/* Bits for ds_ctl6. */
+#define AR_TXC6_AGGR_LEN_M 0x0000ffff
+#define AR_TXC6_AGGR_LEN_S 0
+#define AR_TXC6_PAD_DELIM_M 0x03fc0000
+#define AR_TXC6_PAD_DELIM_S 18
+#define AR_TXC6_ENCR_TYPE_M 0x0c000000
+#define AR_TXC6_ENCR_TYPE_S 26
+#define AR_ENCR_TYPE_CLEAR 0
+#define AR_ENCR_TYPE_WEP 1
+#define AR_ENCR_TYPE_AES 2
+#define AR_ENCR_TYPE_TKIP 3
+
+/* Bits for ds_ctl7. */
+#define AR_TXC7_2040_0 0x00000001
+#define AR_TXC7_GI0 0x00000002
+#define AR_TXC7_CHAIN_SEL0_M 0x0000001c
+#define AR_TXC7_CHAIN_SEL0_S 2
+#define AR_TXC7_2040_1 0x00000020
+#define AR_TXC7_GI1 0x00000040
+#define AR_TXC7_CHAIN_SEL1_M 0x00000380
+#define AR_TXC7_CHAIN_SEL1_S 7
+#define AR_TXC7_2040_2 0x00000400
+#define AR_TXC7_GI2 0x00000800
+#define AR_TXC7_CHAIN_SEL2_M 0x00007000
+#define AR_TXC7_CHAIN_SEL2_S 12
+#define AR_TXC7_2040_3 0x00008000
+#define AR_TXC7_GI3 0x00010000
+#define AR_TXC7_CHAIN_SEL3_M 0x000e0000
+#define AR_TXC7_CHAIN_SEL3_S 17
+#define AR_TXC7_RTSCTS_RATE_M 0x0ff00000
+#define AR_TXC7_RTSCTS_RATE_S 20
+/* Shortcuts. */
+#define AR_TXC7_2040_0123 \
+ (AR_TXC7_2040_0 | AR_TXC7_2040_1 | AR_TXC7_2040_2 | AR_TXC7_2040_3)
+#define AR_TXC7_GI0123 \
+ (AR_TXC7_GI0 | AR_TXC7_GI1 | AR_TXC7_GI2 | AR_TXC7_GI3)
+
+/* Bits for ds_status0. */
+#define AR_TXS0_RSSI_ANT0(i) (((x) >> ((i) * 8)) & 0xff)
+#define AR_TXS0_BA_STATUS 0x40000000
+
+/* Bits for ds_status1. */
+#define AR_TXS1_FRM_XMIT_OK 0x00000001
+#define AR_TXS1_EXCESSIVE_RETRIES 0x00000002
+#define AR_TXS1_FIFO_UNDERRUN 0x00000004
+#define AR_TXS1_FILTERED 0x00000008
+#define AR_TXS1_RTS_FAIL_CNT_M 0x000000f0
+#define AR_TXS1_RTS_FAIL_CNT_S 4
+#define AR_TXS1_DATA_FAIL_CNT_M 0x00000f00
+#define AR_TXS1_DATA_FAIL_CNT_S 8
+#define AR_TXS1_VIRT_RETRY_CNT_M 0x0000f000
+#define AR_TXS1_VIRT_RETRY_CNT_S 12
+#define AR_TXS1_TX_DELIM_UNDERRUN 0x00010000
+#define AR_TXS1_TX_DATA_UNDERRUN 0x00020000
+#define AR_TXS1_DESC_CFG_ERR 0x00040000
+#define AR_TXS1_TX_TIMER_EXPIRED 0x00080000
+/* Shortcuts. */
+#define AR_TXS1_UNDERRUN \
+ (AR_TXS1_FIFO_UNDERRUN | \
+ AR_TXS1_TX_DELIM_UNDERRUN | \
+ AR_TXS1_TX_DATA_UNDERRUN)
+
+/* Bits for ds_status9. */
+#define AR_TXS9_DONE 0x00000001
+#define AR_TXS9_SEQNUM_M 0x00001ffe
+#define AR_TXS9_SEQNUM_S 1
+#define AR_TXS9_TXOP_EXCEEDED 0x00020000
+#define AR_TXS9_FINAL_IDX_M 0x00600000
+#define AR_TXS9_FINAL_IDX_S 21
+#define AR_TXS9_POWER_MGMT 0x02000000
+
+/*
+ * Rx DMA descriptor.
+ */
+struct ar_rx_desc {
+ uint32_t ds_link;
+ uint32_t ds_data;
+ uint32_t ds_ctl0;
+ uint32_t ds_ctl1;
+ uint32_t ds_status0;
+ uint32_t ds_status1;
+ uint32_t ds_status2;
+ uint32_t ds_status3;
+ uint32_t ds_status4;
+ uint32_t ds_status5;
+ uint32_t ds_status6;
+ uint32_t ds_status7;
+ uint32_t ds_status8;
+ /*
+ * Padding to make Rx descriptors 64 bytes such that they will
+ * not cross a 4KB boundary.
+ */
+ uint32_t pad[3];
+} __packed;
+
+/* Bits for ds_ctl1. */
+#define AR_RXC1_BUF_LEN_M 0x00000fff
+#define AR_RXC1_BUF_LEN_S 0
+#define AR_RXC1_INTR_REQ 0x00002000
+
+/* Bits for ds_ctl2. */
+#define AR_RXS0_RSSI_ANT00(x) (((x) >> 0) & 0xff)
+#define AR_RXS0_RSSI_ANT01(x) (((x) >> 8) & 0xff)
+#define AR_RXS0_RSSI_ANT02(x) (((x) >> 16) & 0xff)
+#define AR_RXS0_RATE_M 0xff000000
+#define AR_RXS0_RATE_S 24
+
+/* Bits for ds_status1. */
+#define AR_RXS1_DATA_LEN_M 0x00000fff
+#define AR_RXS1_DATA_LEN_S 0
+#define AR_RXS1_MORE 0x00001000
+
+/* Bits for ds_status3. */
+#define AR_RXS3_GI 0x00000001
+#define AR_RXS3_2040 0x00000002
+#define AR_RXS3_PARALLEL_40 0x00000004
+#define AR_RXS3_ANTENNA_M 0xffffff00 /* XXX pas bon? */
+#define AR_RXS3_ANTENNA_S 8
+#define AR_RXS3_RATE_M 0x000003fc
+#define AR_RXS3_RATE_S 2
+
+/* Bits for ds_status4. */
+#define AR_RXS4_RSSI_COMBINED_M 0xff000000
+#define AR_RXS4_RSSI_COMBINED_S 24
+
+/* Bits for ds_status8. */
+#define AR_RXS8_DONE 0x00000001
+#define AR_RXS8_FRAME_OK 0x00000002
+#define AR_RXS8_CRC_ERR 0x00000004
+#define AR_RXS8_DECRYPT_CRC_ERR 0x00000008
+#define AR_RXS8_PHY_ERR 0x00000010
+#define AR_RXS8_MICHAEL_ERR 0x00000020
+#define AR_RXS8_PRE_DELIM_CRC_ERR 0x00000040
+#define AR_RXS8_PHY_ERR_CODE_M 0x0000ff00
+#define AR_RXS8_PHY_ERR_CODE_S 8
+#define AR_RXS8_KEY_IDX_VALID 0x00000100
+#define AR_RXS8_KEY_IDX_M 0x0000fe00
+#define AR_RXS8_KEY_IDX_S 9
+#define AR_RXS8_POST_DELIM_CRC_ERR 0x00040000
+#define AR_RXS8_DECRYPT_BUSY_ERR 0x40000000
+
+
+/* Maximum number of chains supported by any chipset. */
+#define AR_MAX_CHAINS 3
+
+/* Default number of key cache entries. */
+#define AR_KEYTABLE_SIZE 128
+
+/* GPIO pins. */
+#define AR_GPIO_LED_PIN 1
+#define AR_GPIO_WLANACTIVE_PIN 5
+#define AR_GPIO_BTACTIVE_PIN 6
+#define AR_GPIO_BTPRIORITY_PIN 7
+
+/* XXX need to cleanup that mess. */
+#define AR_SREV_5416(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_5416_PCI || \
+ (sc)->mac_ver == AR_SREV_VERSION_5416_PCIE)
+#define AR_SREV_5416_20_OR_LATER(sc) \
+ ((AR_SREV_5416(sc) && \
+ (sc)->mac_rev >= AR_SREV_REVISION_5416_20) || \
+ (sc)->mac_ver >= AR_SREV_VERSION_9100)
+#define AR_SREV_5416_22_OR_LATER(sc) \
+ ((AR_SREV_5416(sc) && \
+ (sc)->mac_rev >= AR_SREV_REVISION_5416_22) || \
+ (sc)->mac_ver >= AR_SREV_VERSION_9100)
+
+#define AR_SREV_9160(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9160)
+#define AR_SREV_9160_10_OR_LATER(sc) \
+ ((sc)->mac_ver >= AR_SREV_VERSION_9160)
+#define AR_SREV_9160_11(sc) \
+ (AR_SREV_9160(sc) && \
+ (sc)->mac_rev == AR_SREV_REVISION_9160_11)
+
+#define AR_SREV_9280(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9280)
+#define AR_SREV_9280_10_OR_LATER(sc) \
+ ((sc)->mac_ver >= AR_SREV_VERSION_9280)
+#define AR_SREV_9280_10(sc) \
+ (AR_SREV_9280(sc) && \
+ (sc)->mac_rev == AR_SREV_REVISION_9280_10)
+#define AR_SREV_9280_20(sc) \
+ (AR_SREV_9280(sc) && \
+ (sc)->mac_rev >= AR_SREV_REVISION_9280_20)
+#define AR_SREV_9280_20_OR_LATER(sc) \
+ ((sc)->mac_ver > AR_SREV_VERSION_9280 || \
+ (AR_SREV_9280(sc) && (sc)->mac_rev >= AR_SREV_REVISION_9280_20))
+
+#define AR_SREV_9285(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9285)
+#define AR_SREV_9285_10_OR_LATER(sc) \
+ ((sc)->mac_ver >= AR_SREV_VERSION_9285)
+#define AR_SREV_9285_11(sc) \
+ (AR_SREV_9285(sc) && \
+ (sc)->mac_rev == AR_SREV_REVISION_9285_11)
+#define AR_SREV_9285_11_OR_LATER(sc) \
+ ((sc)->mac_ver > AR_SREV_VERSION_9285 || \
+ (AR_SREV_9285(sc) && (sc)->mac_rev >= AR_SREV_REVISION_9285_11))
+#define AR_SREV_9285_12(sc) \
+ (AR_SREV_9285(sc) && \
+ ((sc)->mac_rev == AR_SREV_REVISION_9285_12))
+#define AR_SREV_9285_12_OR_LATER(sc) \
+ ((sc)->mac_ver > AR_SREV_VERSION_9285 || \
+ (AR_SREV_9285(sc) && (sc)->mac_rev >= AR_SREV_REVISION_9285_12))
+
+#define AR_SREV_9287(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9287)
+#define AR_SREV_9287_10_OR_LATER(sc) \
+ ((sc)->mac_ver >= AR_SREV_VERSION_9287)
+#define AR_SREV_9287_10(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9287 && \
+ (sc)->mac_rev == AR_SREV_REVISION_9287_10)
+#define AR_SREV_9287_11(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9287 && \
+ (sc)->mac_rev == AR_SREV_REVISION_9287_11)
+#define AR_SREV_9287_11_OR_LATER(sc) \
+ ((sc)->mac_ver > AR_SREV_VERSION_9287 || \
+ (AR_SREV_9287(sc) && (sc)->mac_rev >= AR_SREV_REVISION_9287_11))
+#define AR_SREV_9287_12(sc) \
+ ((sc)->mac_ver == AR_SREV_VERSION_9287 && \
+ (sc)->mac_rev == AR_SREV_REVISION_9287_12)
+#define AR_SREV_9287_12_OR_LATER(sc) \
+ ((sc)->mac_ver > AR_SREV_VERSION_9287 || \
+ (AR_SREV_9287(sc) && (sc)->mac_rev >= AR_SREV_REVISION_9287_12))
+
+#define AR_SINGLE_CHIP(sc) AR_SREV_9280_10_OR_LATER(sc)
+
+#define AR_RADIO_SREV_MAJOR 0xf0
+#define AR_RAD5133_SREV_MAJOR 0xc0
+#define AR_RAD2133_SREV_MAJOR 0xd0
+#define AR_RAD5122_SREV_MAJOR 0xe0
+#define AR_RAD2122_SREV_MAJOR 0xf0
+
+/*
+ * Common ROM structures.
+ */
+#define AR_EEPROM_MAGIC_OFFSET 0x0000
+#if BYTE_ORDER == BIG_ENDIAN
+#define AR_EEPROM_MAGIC 0x5aa5
+#else
+#define AR_EEPROM_MAGIC 0xa55a
+#endif
+
+#define AR_BCHAN_UNUSED 0xff
+#define AR_NO_SPUR 0x8000
+
+#define AR_NUM_PDADC_VALUES 128
+#define AR_PD_GAINS_IN_MASK 4 /* NB: Max for all chips. */
+
+#define AR_MAX_PWR_RANGE_IN_HALF_DB 64
+
+#define AR_MAX_RATE_POWER 63
+
+#define AR_HT40_POWER_INC_FOR_PDADC 2
+
+#define AR_EEPROM_MODAL_SPURS 5
+
+#define AR_BASE_FREQ_2GHZ 2300
+#define AR_BASE_FREQ_5GHZ 4900
+
+#define AR_PWR_TABLE_OFFSET_DB (-5)
+
+/* XXX does not belong here!!! */
+#define AR9285_PD_GAIN_BOUNDARY_DEFAULT 58
+#define AR9280_TX_GAIN_TABLE_SIZE 22
+
+#define AR_EEP_TXGAIN_ORIGINAL 0
+#define AR_EEP_TXGAIN_HIGH_POWER 1
+
+/*
+ * ROM header that is common to all existing ROM layouts.
+ */
+struct ar_base_eep_header {
+ uint16_t length;
+ uint16_t checksum;
+ uint16_t version;
+#define AR_EEP_VER 0xe
+#define AR_EEP_VER_MINOR_MASK 0x0fff
+#define AR_EEP_MINOR_VER_2 2
+#define AR_EEP_MINOR_VER_3 3
+#define AR_EEP_MINOR_VER_7 7
+#define AR_EEP_MINOR_VER_9 9
+#define AR_EEP_MINOR_VER_10 10
+#define AR_EEP_MINOR_VER_16 16
+#define AR_EEP_MINOR_VER_17 17
+#define AR_EEP_MINOR_VER_19 19
+#define AR_EEP_MINOR_VER_20 20
+#define AR_EEP_MINOR_VER_21 21
+#define AR_EEP_MINOR_VER_22 22
+
+ uint8_t opCapFlags;
+#define AR_OPFLAGS_11A 0x01
+#define AR_OPFLAGS_11G 0x02
+#define AR_OPFLAGS_11N_5G40 0x04
+#define AR_OPFLAGS_11N_2G40 0x08
+#define AR_OPFLAGS_11N_5G20 0x10
+#define AR_OPFLAGS_11N_2G20 0x20
+/* Shortcut. */
+#define AR_OPFLAGS_11N 0x3c
+
+ uint8_t eepMisc;
+ uint16_t regDmn[2];
+ uint8_t macAddr[6];
+ uint8_t rxMask;
+ uint8_t txMask;
+ uint16_t rfSilent;
+#define AR_EEP_RFSILENT_ENABLED 0x0001
+#define AR_EEP_RFSILENT_GPIO_SEL_M 0x001c
+#define AR_EEP_RFSILENT_GPIO_SEL_S 2
+#define AR_EEP_RFSILENT_POLARITY 0x0002
+
+ uint16_t blueToothOptions;
+ uint16_t deviceCap;
+#define AR_EEP_DEVCAP_COMPRESS_DIS 0x0001
+#define AR_EEP_DEVCAP_AES_DIS 0x0002
+#define AR_EEP_DEVCAP_FASTFRAME_DIS 0x0004
+#define AR_EEP_DEVCAP_BURST_DIS 0x0008
+#define AR_EEP_DEVCAP_MAXQCU_M 0x01f0
+#define AR_EEP_DEVCAP_MAXQCU_S 4
+#define AR_EEP_DEVCAP_HEAVY_CLIP_EN 0x0200
+#define AR_EEP_DEVCAP_KC_ENTRIES_M 0xf000
+#define AR_EEP_DEVCAP_KC_ENTRIES_S 12
+
+ uint32_t binBuildNumber;
+ uint8_t deviceType;
+} __packed;
+
+struct ar_spur_chan {
+ uint16_t spurChan;
+ uint8_t spurRangeLow;
+ uint8_t spurRangeHigh;
+} __packed;
+
+struct ar_cal_data_per_freq_olpc {
+ uint8_t pwrPdg[2][5];
+ uint8_t vpdPdg[2][5];
+ uint8_t pcdac[2][5];
+ uint8_t empty[2][5];
+} __packed;
+
+struct ar_cal_target_power_leg {
+ uint8_t bChannel;
+ uint8_t tPow2x[4];
+} __packed;
+
+struct ar_cal_target_power_ht {
+ uint8_t bChannel;
+ uint8_t tPow2x[8];
+} __packed;
+
+struct ar_cal_ctl_edges {
+ uint8_t bChannel;
+ uint8_t tPowerFlag;
+#define AR_CAL_CTL_EDGES_POWER_M 0x3f
+#define AR_CAL_CTL_EDGES_POWER_S 0
+#define AR_CAL_CTL_EDGES_FLAG_M 0xc0
+#define AR_CAL_CTL_EDGES_FLAG_S 6
+} __packed;
+
+#define AR_SD_NO_CTL 0xe0
+#define AR_NO_CTL 0xff
+#define AR_CTL_MODE_M 0x07
+#define AR_CTL_MODE_S 0
+#define AR_CTL_11A 0
+#define AR_CTL_11B 1
+#define AR_CTL_11G 2
+#define AR_CTL_2GHT20 5
+#define AR_CTL_5GHT20 6
+#define AR_CTL_2GHT40 7
+#define AR_CTL_5GHT40 8
+
+/*
+ * Serializer/Deserializer programming for non-PCIe devices.
+ */
+static const uint32_t ar_nonpcie_serdes[] = {
+ 0x9248fc00,
+ 0x24924924,
+ 0x28000029,
+ 0x57160824,
+ 0x25980579,
+ 0x00000000,
+ 0x1aaabe40,
+ 0xbe105554,
+ 0x000e1007
+};
+
+/*
+ * Macros to access registers.
+ */
+#define AR_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
+
+#define AR_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
+
+#define AR_SETBITS(sc, reg, mask) \
+ AR_WRITE(sc, reg, AR_READ(sc, reg) | (mask))
+
+#define AR_CLRBITS(sc, reg, mask) \
+ AR_WRITE(sc, reg, AR_READ(sc, reg) & ~(mask))
+
+/*
+ * Macros to access subfields in registers.
+ */
+/* Mask and Shift (getter). */
+#define MS(val, field) \
+ (((val) & field##_M) >> field##_S)
+
+/* Shift and Mask (setter). */
+#define SM(field, val) \
+ (((val) << field##_S) & field##_M)
+
+/* Rewrite. */
+#define RW(var, field, val) \
+ (((var) & ~field##_M) | SM(field, val))
diff --git a/sys/dev/ic/athnvar.h b/sys/dev/ic/athnvar.h
new file mode 100644
index 00000000000..d727bf7dce4
--- /dev/null
+++ b/sys/dev/ic/athnvar.h
@@ -0,0 +1,513 @@
+/* $OpenBSD: athnvar.h,v 1.1 2009/11/14 16:55:11 damien Exp $ */
+
+/*-
+ * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define ATHN_DEBUG 1
+#define ATHN_INTR_MITIGATION 1
+#define ATHN_BT_COEXISTENCE 1
+
+#ifdef ATHN_DEBUG
+#define DPRINTF(x) do { if (athn_debug > 0) printf x; } while (0)
+#define DPRINTFN(n, x) do { if (athn_debug >= (n)) printf x; } while (0)
+extern int athn_debug;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n, x)
+#endif
+
+#define ATHN_RXBUFSZ 3872
+#define ATHN_TXBUFSZ 4096
+
+#define ATHN_NRXBUFS 64
+#define ATHN_NTXBUFS 64 /* Shared between all Tx queues. */
+#define ATHN_MAX_SCATTER 16
+
+struct athn_rx_radiotap_header {
+ struct ieee80211_radiotap_header wr_ihdr;
+ uint64_t wr_tsft;
+ uint8_t wr_flags;
+ uint8_t wr_rate;
+ uint16_t wr_chan_freq;
+ uint16_t wr_chan_flags;
+ int8_t wr_dbm_antsignal;
+ uint8_t wr_antenna;
+} __packed;
+
+#define ATHN_RX_RADIOTAP_PRESENT \
+ (1 << IEEE80211_RADIOTAP_TSFT | \
+ 1 << IEEE80211_RADIOTAP_FLAGS | \
+ 1 << IEEE80211_RADIOTAP_RATE | \
+ 1 << IEEE80211_RADIOTAP_CHANNEL | \
+ 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL | \
+ 1 << IEEE80211_RADIOTAP_ANTENNA)
+
+struct athn_tx_radiotap_header {
+ struct ieee80211_radiotap_header wt_ihdr;
+ uint8_t wt_flags;
+ uint8_t wt_rate;
+ uint16_t wt_chan_freq;
+ uint16_t wt_chan_flags;
+ uint8_t wt_hwqueue;
+} __packed;
+
+#define ATHN_TX_RADIOTAP_PRESENT \
+ (1 << IEEE80211_RADIOTAP_FLAGS | \
+ 1 << IEEE80211_RADIOTAP_RATE | \
+ 1 << IEEE80211_RADIOTAP_CHANNEL | \
+ 1 << IEEE80211_RADIOTAP_HWQUEUE)
+
+struct athn_tx_buf {
+ SIMPLEQ_ENTRY(athn_tx_buf) bf_list;
+
+ struct ar_tx_desc *bf_descs;
+ bus_dmamap_t bf_map;
+ bus_addr_t bf_daddr;
+
+ struct mbuf *bf_m;
+ struct ieee80211_node *bf_ni;
+};
+
+struct athn_txq {
+ SIMPLEQ_HEAD(, athn_tx_buf) head;
+ struct ar_tx_desc *lastds;
+};
+
+struct athn_rx_buf {
+ SIMPLEQ_ENTRY(athn_rx_buf) bf_list;
+
+ struct ar_rx_desc *bf_desc;
+ bus_dmamap_t bf_map;
+
+ struct mbuf *bf_m;
+ bus_addr_t bf_daddr;
+};
+
+struct athn_rxq {
+ struct athn_rx_buf bf[ATHN_NRXBUFS];
+
+ struct ar_rx_desc *descs;
+ struct ar_rx_desc *lastds;
+ bus_dmamap_t map;
+ bus_dma_segment_t seg;
+
+ SIMPLEQ_HEAD(, athn_rx_buf) head;
+};
+
+/* Software rate indexes. */
+#define ATHN_RIDX_CCK1 0
+#define ATHN_RIDX_OFDM6 4
+#define ATHN_RIDX_MCS0 12
+#define ATHN_RIDX_MCS15 27
+#define ATHN_RIDX_MAX 27
+#define ATHN_IS_OFDM_RIDX(ridx) (athn_rates[ridx].phy == IEEE80211_T_OFDM)
+#define ATHN_IS_HT_RIDX(ridx) ((ridx) >= ATHN_RIDX_MCS0)
+
+static const struct athn_rate {
+ uint8_t rate; /* Rate in 500Kbps unit or MCS if 0x80. */
+ uint8_t hwrate; /* HW representation. */
+ enum ieee80211_phytype phy;
+} athn_rates[] = {
+ { 2, 0x1b, IEEE80211_T_DS },
+ { 4, 0x1a, IEEE80211_T_DS },
+ { 11, 0x19, IEEE80211_T_DS },
+ { 22, 0x18, IEEE80211_T_DS },
+ { 12, 0x0b, IEEE80211_T_OFDM },
+ { 18, 0x0f, IEEE80211_T_OFDM },
+ { 24, 0x0a, IEEE80211_T_OFDM },
+ { 36, 0x0e, IEEE80211_T_OFDM },
+ { 48, 0x09, IEEE80211_T_OFDM },
+ { 72, 0x0d, IEEE80211_T_OFDM },
+ { 96, 0x08, IEEE80211_T_OFDM },
+ { 108, 0x0c, IEEE80211_T_OFDM },
+ { 0x80, 0x80, IEEE80211_T_OFDM },
+ { 0x81, 0x81, IEEE80211_T_OFDM },
+ { 0x82, 0x82, IEEE80211_T_OFDM },
+ { 0x83, 0x83, IEEE80211_T_OFDM },
+ { 0x84, 0x84, IEEE80211_T_OFDM },
+ { 0x85, 0x85, IEEE80211_T_OFDM },
+ { 0x86, 0x86, IEEE80211_T_OFDM },
+ { 0x87, 0x87, IEEE80211_T_OFDM },
+ { 0x88, 0x88, IEEE80211_T_OFDM },
+ { 0x89, 0x89, IEEE80211_T_OFDM },
+ { 0x8a, 0x8a, IEEE80211_T_OFDM },
+ { 0x8b, 0x8b, IEEE80211_T_OFDM },
+ { 0x8c, 0x8c, IEEE80211_T_OFDM },
+ { 0x8d, 0x8d, IEEE80211_T_OFDM },
+ { 0x8e, 0x8e, IEEE80211_T_OFDM },
+ { 0x8f, 0x8f, IEEE80211_T_OFDM }
+};
+
+struct athn_series {
+ uint8_t tries;
+ uint8_t hwrate;
+ uint16_t dur;
+};
+
+struct athn_pier {
+ uint8_t fbin;
+ const uint8_t *pwr[AR_PD_GAINS_IN_MASK];
+ const uint8_t *vpd[AR_PD_GAINS_IN_MASK];
+};
+
+/*
+ * Structures used to store initialization values.
+ */
+struct athn_ini {
+ int nregs;
+ const uint16_t *regs;
+ const uint32_t *vals_5g20;
+#ifndef IEEE80211_NO_HT
+ const uint32_t *vals_5g40;
+ const uint32_t *vals_2g40;
+#endif
+ const uint32_t *vals_2g20;
+ int ncmregs;
+ const uint16_t *cmregs;
+ const uint32_t *cmvals;
+};
+
+struct athn_gain {
+ int nregs;
+ const uint16_t *regs;
+ const uint32_t *vals_5g;
+ const uint32_t *vals_2g;
+};
+
+struct athn_addac {
+ int nvals;
+ const uint32_t *vals;
+};
+
+/* Tx queue software indexes. */
+#define ATHN_QID_AC_BE 0
+#define ATHN_QID_PSPOLL 1
+#define ATHN_QID_AC_BK 2
+#define ATHN_QID_AC_VI 3
+#define ATHN_QID_AC_VO 4
+#define ATHN_QID_UAPSD 5
+#define ATHN_QID_CAB 6
+#define ATHN_QID_BEACON 7
+#define ATHN_QID_COUNT 8
+
+/* Map Access Category to Tx queue Id. */
+static const uint8_t athn_ac2qid[EDCA_NUM_AC] = {
+ ATHN_QID_AC_BE, /* EDCA_AC_BE */
+ ATHN_QID_AC_BK, /* EDCA_AC_BK */
+ ATHN_QID_AC_VI, /* EDCA_AC_VI */
+ ATHN_QID_AC_VO /* EDCA_AC_VO */
+};
+
+static const uint8_t athn_5ghz_chans[] = {
+ /* UNII 1. */
+ 36, 40, 44, 48,
+ /* UNII 2. */
+ 52, 56, 60, 64,
+ /* Middle band. */
+ 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
+ /* UNII 3. */
+ 149, 153, 157, 161, 165
+};
+
+/* Number of data bits per OFDM symbol for MCS[0-15]. */
+/* See tables 20-29, 20-30, 20-33, 20-34. */
+static const uint16_t ar_mcs_ndbps[][2] = {
+ /* 20MHz 40MHz */
+ { 26, 54 }, /* MCS0 */
+ { 52, 108 }, /* MCS1 */
+ { 78, 162 }, /* MCS2 */
+ { 104, 216 }, /* MCS3 */
+ { 156, 324 }, /* MCS4 */
+ { 208, 432 }, /* MCS5 */
+ { 234, 486 }, /* MCS6 */
+ { 260, 540 }, /* MCS7 */
+ { 26, 108 }, /* MCS8 */
+ { 52, 216 }, /* MCS9 */
+ { 78, 324 }, /* MCS10 */
+ { 104, 432 }, /* MCS11 */
+ { 156, 648 }, /* MCS12 */
+ { 208, 864 }, /* MCS13 */
+ { 234, 972 }, /* MCS14 */
+ { 260, 1080 } /* MCS15 */
+};
+
+#define ATHN_POWER_OFDM6 0
+#define ATHN_POWER_OFDM9 1
+#define ATHN_POWER_OFDM12 2
+#define ATHN_POWER_OFDM18 3
+#define ATHN_POWER_OFDM24 4
+#define ATHN_POWER_OFDM36 5
+#define ATHN_POWER_OFDM48 6
+#define ATHN_POWER_OFDM54 7
+#define ATHN_POWER_CCK1_LP 8
+#define ATHN_POWER_CCK2_LP 9
+#define ATHN_POWER_CCK2_SP 10
+#define ATHN_POWER_CCK55_LP 11
+#define ATHN_POWER_CCK55_SP 12
+#define ATHN_POWER_CCK11_LP 13
+#define ATHN_POWER_CCK11_SP 14
+#define ATHN_POWER_XR 15
+#define ATHN_POWER_HT20(mcs) (16 + (mcs))
+#define ATHN_POWER_HT40(mcs) (24 + (mcs))
+#define ATHN_POWER_CCK_DUP 32
+#define ATHN_POWER_OFDM_DUP 33
+#define ATHN_POWER_CCK_EXT 34
+#define ATHN_POWER_OFDM_EXT 35
+#define ATHN_POWER_COUNT 36
+
+struct athn_node {
+ struct ieee80211_node ni;
+ struct ieee80211_amrr_node amn;
+ uint8_t ridx[IEEE80211_RATE_MAXSIZE];
+ uint8_t fallback[IEEE80211_RATE_MAXSIZE];
+};
+
+#define ATHN_ANI_PERIOD 100
+#define ATHN_ANI_RSSI_THR_HIGH 40
+#define ATHN_ANI_RSSI_THR_LOW 7
+struct athn_ani {
+ uint8_t noise_immunity_level;
+ uint8_t spur_immunity_level;
+ uint8_t firstep_level;
+ uint8_t ofdm_weak_signal;
+ uint8_t cck_weak_signal;
+
+ uint32_t listen_time;
+
+ uint32_t ofdm_trig_high;
+ uint32_t ofdm_trig_low;
+
+ int32_t cck_trig_high;
+ int32_t cck_trig_low;
+
+ uint32_t ofdm_phy_err_base;
+ uint32_t cck_phy_err_base;
+ uint32_t ofdm_phy_err_count;
+ uint32_t cck_phy_err_count;
+
+ uint32_t cyccnt;
+ uint32_t txfcnt;
+ uint32_t rxfcnt;
+};
+
+struct athn_iq_cal {
+ uint32_t pwr_meas_i;
+ uint32_t pwr_meas_q;
+ int32_t iq_corr_meas;
+};
+
+struct athn_adc_cal {
+ uint32_t pwr_meas_odd_i;
+ uint32_t pwr_meas_even_i;
+ uint32_t pwr_meas_odd_q;
+ uint32_t pwr_meas_even_q;
+};
+
+struct athn_calib {
+ int nsamples;
+ struct athn_iq_cal iq[AR_MAX_CHAINS];
+ struct athn_adc_cal adc_gain[AR_MAX_CHAINS];
+ struct athn_adc_cal adc_dc_offset[AR_MAX_CHAINS];
+};
+
+#define ATHN_NF_CAL_HIST_MAX 5
+
+struct athn_softc;
+
+struct athn_ops {
+ void (*setup)(struct athn_softc *);
+ void (*set_txpower)(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+ void (*spur_mitigate)(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+ const struct ar_spur_chan *(*get_spur_chans)(struct athn_softc *, int);
+ void (*init_from_rom)(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+ int (*set_synth)(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+ void (*swap_rom)(struct athn_softc *);
+ void (*olpc_init)(struct athn_softc *);
+};
+
+struct athn_softc {
+ struct device sc_dev;
+ struct ieee80211com sc_ic;
+
+ int (*sc_enable)(struct athn_softc *);
+ void (*sc_disable)(struct athn_softc *);
+ void (*sc_power)(struct athn_softc *, int);
+ void (*sc_disable_aspm)(struct athn_softc *);
+
+ int (*sc_newstate)(struct ieee80211com *,
+ enum ieee80211_state, int);
+
+ bus_dma_tag_t sc_dmat;
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+
+ struct timeout scan_to;
+ struct timeout calib_to;
+ struct ieee80211_amrr amrr;
+
+ u_int flags;
+#define ATHN_FLAG_PCIE (1 << 0)
+#define ATHN_FLAG_OLPC (1 << 1)
+#define ATHN_FLAG_SPLIT_MMIC (1 << 2)
+#define ATHN_FLAG_RFSILENT (1 << 3)
+#define ATHN_FLAG_RFSILENT_REVERSED (1 << 4)
+#define ATHN_FLAG_BTCOEX2WIRE (1 << 5)
+#define ATHN_FLAG_BTCOEX3WIRE (1 << 6)
+/* Shortcut. */
+#define ATHN_FLAG_BTCOEX (ATHN_FLAG_BTCOEX2WIRE | ATHN_FLAG_BTCOEX3WIRE)
+
+ uint8_t ngpiopins;
+ int rfsilent_pin;
+
+ uint16_t mac_ver;
+ uint8_t mac_rev;
+ uint8_t rf_rev;
+ uint16_t eep_rev;
+ uint32_t phy_rev;
+
+ uint8_t txchainmask;
+ uint8_t rxchainmask;
+ uint8_t ntxchains;
+ uint8_t nrxchains;
+
+ uint8_t calib_mask;
+#define ATHN_CAL_IQ (1 << 0)
+#define ATHN_CAL_ADC_GAIN (1 << 1)
+#define ATHN_CAL_ADC_DC (1 << 2)
+
+ /* Open Loop Power Control. */
+ int8_t tx_gain_tbl[AR9280_TX_GAIN_TABLE_SIZE];
+ int8_t pdadc;
+ int8_t tcomp;
+
+ uint32_t rwbuf[64];
+
+ int kc_entries;
+
+ void *eep;
+ uint32_t eep_base;
+ uint32_t eep_size;
+
+ struct athn_rxq rxq;
+ struct athn_txq txq[31]; /* 0x1f ??? */
+
+ struct ar_tx_desc *descs;
+ bus_dmamap_t map;
+ bus_dma_segment_t seg;
+ SIMPLEQ_HEAD(, athn_tx_buf) txbufs;
+ struct athn_tx_buf txpool[ATHN_NTXBUFS];
+
+ int sc_tx_timer;
+
+ const struct athn_ini *ini;
+ const struct athn_gain *rx_gain;
+ const struct athn_gain *tx_gain;
+ const struct athn_addac *addac;
+ const uint32_t *serdes;
+ uint32_t workaround;
+
+
+ struct athn_ops ops;
+
+ int fixed_ridx;
+
+ int16_t def_nf;
+ struct {
+ int16_t nf[AR_MAX_CHAINS];
+ int16_t nf_ext[AR_MAX_CHAINS];
+ } nf_hist[ATHN_NF_CAL_HIST_MAX];
+ int nf_hist_cur;
+ int16_t nf_priv[AR_MAX_CHAINS];
+ int16_t nf_ext_priv[AR_MAX_CHAINS];
+
+ struct athn_calib calib;
+ struct athn_ani ani;
+
+#if NBPFILTER > 0
+ caddr_t sc_drvbpf;
+
+ union {
+ struct athn_rx_radiotap_header th;
+ uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
+ } sc_rxtapu;
+#define sc_rxtap sc_rxtapu.th
+ int sc_rxtap_len;
+
+ union {
+ struct athn_tx_radiotap_header th;
+ uint8_t pad[IEEE80211_RADIOTAP_HDRLEN];
+ } sc_txtapu;
+#define sc_txtap sc_txtapu.th
+ int sc_txtap_len;
+#endif
+};
+
+extern int athn_attach(struct athn_softc *);
+extern void athn_detach(struct athn_softc *);
+extern int athn_intr(void *);
+extern int ar5416_attach(struct athn_softc *);
+extern int ar9280_attach(struct athn_softc *);
+extern int ar9285_attach(struct athn_softc *);
+extern int ar9287_attach(struct athn_softc *);
+extern uint8_t athn_reverse_bits(uint8_t, int);
+extern uint8_t athn_chan2fbin(struct ieee80211_channel *);
+extern void athn_set_viterbi_mask(struct athn_softc *, int);
+extern void athn_write_txpower(struct athn_softc *, int16_t[]);
+extern void athn_get_lg_tpow(struct athn_softc *,
+ struct ieee80211_channel *, uint8_t,
+ const struct ar_cal_target_power_leg *, int, uint8_t[]);
+extern void athn_get_ht_tpow(struct athn_softc *,
+ struct ieee80211_channel *, uint8_t,
+ const struct ar_cal_target_power_ht *, int, uint8_t[]);
+extern void athn_get_pdadcs(struct athn_softc *, uint8_t,
+ struct athn_pier *, struct athn_pier *, int, int, uint8_t,
+ uint8_t *, uint8_t *);
+extern void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *,
+ int *);
+/* XXX not here. */
+extern void ar5416_set_txpower(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar5416_swap_rom(struct athn_softc *);
+extern void ar9280_2_0_olpc_get_pdadcs(struct athn_softc *,
+ struct ieee80211_channel *, int, uint8_t[], uint8_t[],
+ uint8_t *);
+extern int ar9280_set_synth(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar9280_spur_mitigate(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar9287_1_2_enable_async_fifo(struct athn_softc *);
+extern void ar9287_1_2_setup_async_fifo(struct athn_softc *);
+extern const struct ar_spur_chan *ar5416_get_spur_chans(struct athn_softc *,
+ int);
+extern int ar5416_init_calib(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern int ar9285_1_2_init_calib(struct athn_softc *,
+ struct ieee80211_channel *, struct ieee80211_channel *);
+extern void ar9285_pa_calib(struct athn_softc *);
+extern void ar9280_reset_rx_gain(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar9280_reset_tx_gain(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar5416_reset_addac(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar5416_reset_bb_gain(struct athn_softc *,
+ struct ieee80211_channel *);
+extern void ar5416_rf_reset(struct athn_softc *,
+ struct ieee80211_channel *);