summaryrefslogtreecommitdiff
path: root/sys/dev/ic/ar9285.c
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2010-05-10 17:44:22 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2010-05-10 17:44:22 +0000
commit752b30688d178e71a271482cf41961c54cce1b10 (patch)
treeac540f43c352fea3f174841a97e6a7c3b30012c1 /sys/dev/ic/ar9285.c
parent84c9dd0d237ccba9e15a9356be17a8e307bbbd29 (diff)
athn(4) is going to support a new family of Atheros 802.11n
chips (AR9003), which differs from the currently supported families (AR5008, AR9001 and AR9002). The main differences (from a driver point of view) are: * DMA: Tx and Rx descriptors have changed. A single Tx descriptor can now reference up to 4 scatter/gather DMA segments. There is now a DMA ring for reporting Tx status with separate Tx status descriptors (this ring is used to report Tx status for all the Tx FIFOs). Rx status descriptors are now put at the beginning of Rx buffers and do not need to be allocated separately from buffers. There are two Rx FIFOs (low priority and high priority) instead of one. * ROM: The AR9003 family uses OTP-ROM instead of EEPROM. Reading the ROM is totally insane since vendors can provide only the chunks of ROM that differ from a default image (and thus the default image has to be stored in the driver). This is referenced as "compressed ROM" in the Linux driver, though there is no real compression involved, at least for the moment. * PHY registers: All PHY registers have changed. Some registers offsets do not fit on 16 bits anymore, but since they are 32-bit aligned, we can still make them fit on 16 bits to save .rodata space in initialization tables. * MAC registers: Some MAC registers offsets have changed (GPIO, interrupt masks) which is quite annoying (though ~98% remain the same.) * Initialization values: Initialization values are now split in mac/soc/bb/radio blocks and pre/core/post phases in the Linux driver. I have chosen to not go that road and merge these blocks in modal and non-modal initialization values (similar to the other families). The initialization order remains exactly the same as the Linux driver though. To manage these differences, I have split athn.c in two backends: ar5008.c contains the bits that are specific to the AR5008, AR9001 and AR9002 families (used by ar5416.c, ar9280.c, ar9285.c and ar9287.c) and that were previously in athn.c. ar9003.c contains the bits that are specific to the new AR9003 family (used by ar9380.c only for now.) I have introduced a thin hardware abstraction layer (actually a set of pointers to functions) that is used in athn.c. My intent is to keep this abstraction layer as thin as possible and not to create another ugly pile of abstraction layers a la MadWifi. I think I've managed to keep things sane, probably at the expense of duplicating some code in both ar5008.c and ar9003.c, but at least we do not have to dig through layers and layers of virtual descriptors to figure out what is mapped to the hardware. Tested for non-regression on various AR5416 (sparc64+i386), AR9281 and AR9285 (i386 only) adapters. AR9380 part is not tested (hardware is not available to the general public yet). Committed over my AR9285 2.0.
Diffstat (limited to 'sys/dev/ic/ar9285.c')
-rw-r--r--sys/dev/ic/ar9285.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/sys/dev/ic/ar9285.c b/sys/dev/ic/ar9285.c
index f9442fa8bac..9c52217f513 100644
--- a/sys/dev/ic/ar9285.c
+++ b/sys/dev/ic/ar9285.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar9285.c,v 1.7 2010/04/20 22:05:43 tedu Exp $ */
+/* $OpenBSD: ar9285.c,v 1.8 2010/05/10 17:44:21 damien Exp $ */
/*-
* Copyright (c) 2009-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -62,6 +62,7 @@
#include <dev/ic/athnreg.h>
#include <dev/ic/athnvar.h>
+#include <dev/ic/ar5008reg.h>
#include <dev/ic/ar9280reg.h>
#include <dev/ic/ar9285reg.h>
@@ -74,6 +75,8 @@ void ar9285_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
void ar9285_pa_calib(struct athn_softc *);
int ar9285_1_2_cl_cal(struct athn_softc *, struct ieee80211_channel *,
struct ieee80211_channel *);
+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 *,
@@ -81,11 +84,28 @@ void ar9285_set_power_calib(struct athn_softc *,
void ar9285_set_txpower(struct athn_softc *, struct ieee80211_channel *,
struct ieee80211_channel *);
+/* Extern functions. */
+uint8_t athn_chan2fbin(struct ieee80211_channel *);
+void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
+int ar5008_attach(struct athn_softc *);
+void ar5008_write_txpower(struct athn_softc *, int16_t power[]);
+void ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *,
+ struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *);
+void ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
+ uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]);
+void ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
+ uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]);
+int ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *,
+ struct ieee80211_channel *);
+void ar9280_spur_mitigate(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->eep_size = sizeof(struct ar9285_eeprom);
sc->def_nf = AR9285_PHY_CCA_MAX_GOOD_VALUE;
sc->ngpiopins = 12;
sc->led_pin = 1;
@@ -103,7 +123,8 @@ ar9285_attach(struct athn_softc *sc)
else
sc->ini = &ar9285_1_0_ini;
sc->serdes = ar9280_2_0_serdes;
- return (0);
+
+ return (ar5008_attach(sc));
}
void
@@ -153,7 +174,7 @@ ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz)
const struct ar9285_eeprom *eep = sc->eep;
KASSERT(is2ghz);
- return eep->modalHeader.spurChans;
+ return (eep->modalHeader.spurChans);
}
void
@@ -214,7 +235,7 @@ ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
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);
+ AR_WRITE(sc, AR9285_AN_TOP4, AR9285_AN_TOP4_UNLOCKED);
if (modal->version >= 3) {
/* Setup antenna diversity from ROM. */
@@ -378,8 +399,7 @@ ar9285_pa_calib(struct athn_softc *sc)
return;
if (AR_SREV_9285_11(sc)) {
- /* XXX magic 0x14. */
- AR_WRITE(sc, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT | 0x14);
+ AR_WRITE(sc, AR9285_AN_TOP4, AR9285_AN_TOP4_UNLOCKED);
DELAY(10);
}
@@ -585,7 +605,7 @@ ar9285_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
hipier.pwr[i] = pierdata[lo].pwrPdg[i];
hipier.vpd[i] = pierdata[lo].vpdPdg[i];
}
- athn_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
+ ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
AR9285_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
}
@@ -607,7 +627,7 @@ ar9285_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
overlap = eep->modalHeader.pdGainOverlap;
nxpdgains = 0;
- memset(xpdgains, 0, sizeof xpdgains);
+ memset(xpdgains, 0, sizeof(xpdgains));
for (i = AR9285_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
if (nxpdgains >= AR9285_NUM_PD_GAINS)
break;
@@ -663,36 +683,37 @@ ar9285_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
/* XXX */
/* Get CCK target powers. */
- athn_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
+ ar5008_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,
+ ar5008_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,
+ ar5008_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,
+ ar5008_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);
+ ar5008_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,
+ ar5008_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);
+ memset(power, 0, sizeof(power));
/* Shuffle target powers accross transmit rates. */
power[ATHN_POWER_OFDM6 ] =
power[ATHN_POWER_OFDM9 ] =
@@ -735,5 +756,5 @@ ar9285_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
}
/* Commit transmit power values to hardware. */
- athn_write_txpower(sc, power);
+ ar5008_write_txpower(sc, power);
}