svn commit: r240447 - head/sys/dev/ath/ath_hal/ar5416
Adrian Chadd
adrian at FreeBSD.org
Thu Sep 13 07:22:41 UTC 2012
Author: adrian
Date: Thu Sep 13 07:22:40 2012
New Revision: 240447
URL: http://svn.freebsd.org/changeset/base/240447
Log:
Introduce an AR5416 flavour of the IFS and mac usec/timing configuration
used when running the chips in half/quarter rate.
This sets up some default parameters which are then overridden by the
driver (which manually configures things like slot timing at interface
start time.)
Although this is a copy-and-modify from the AR5212 HAL, I did peek
at the reference HAL and the ath9k driver to see what they did.
Ath9k in particular doesn't hard-code this - instead, their version
of ar5416InitUserSettings() does all of the relevant math.
TODO:
* do the math, not hard code things!
* fix the mac clock calculation for the AR9287; since it runs the
MAC clock at a higher rate, requiring all the duration calculations
to change;
* Do a whole lot more validation for half/quarter rates.
Obtained from: Qualcomm Atheros, Linux ath9k
Modified:
head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c Thu Sep 13 07:19:53 2012 (r240446)
+++ head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c Thu Sep 13 07:22:40 2012 (r240447)
@@ -62,6 +62,8 @@ static HAL_BOOL ar5416SetPowerPerRateTab
uint16_t powerLimit);
static void ar5416Set11nRegs(struct ath_hal *ah, const struct ieee80211_channel *chan);
static void ar5416MarkPhyInactive(struct ath_hal *ah);
+static void ar5416SetIFSTiming(struct ath_hal *ah,
+ const struct ieee80211_channel *chan);
/*
* Places the device in and out of reset and then places sane
@@ -310,11 +312,26 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMO
ah->ah_resetTxQueue(ah, i);
ar5416InitIMR(ah, opmode);
- ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
+ ar5416SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);
ar5416InitQoS(ah);
/* This may override the AR_DIAG_SW register */
ar5416InitUserSettings(ah);
+ /* XXX this won't work for AR9287! */
+ if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan)) {
+ ar5416SetIFSTiming(ah, chan);
+#if 0
+ /*
+ * AR5413?
+ * Force window_length for 1/2 and 1/4 rate channels,
+ * the ini file sets this to zero otherwise.
+ */
+ OS_REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
+ AR_PHY_FRAME_CTL_WINLEN, 3);
+ }
+#endif
+ }
+
if (AR_SREV_KIWI_13_OR_LATER(ah)) {
/*
* Enable ASYNC FIFO
@@ -2751,3 +2768,125 @@ ar5416MarkPhyInactive(struct ath_hal *ah
{
OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
}
+
+#define AR5416_IFS_SLOT_FULL_RATE_40 0x168 /* 9 us half, 40 MHz core clock (9*40) */
+#define AR5416_IFS_SLOT_HALF_RATE_40 0x104 /* 13 us half, 20 MHz core clock (13*20) */
+#define AR5416_IFS_SLOT_QUARTER_RATE_40 0xD2 /* 21 us quarter, 10 MHz core clock (21*10) */
+
+#define AR5416_IFS_EIFS_FULL_RATE_40 0xE60 /* (74 + (2 * 9)) * 40MHz core clock */
+#define AR5416_IFS_EIFS_HALF_RATE_40 0xDAC /* (149 + (2 * 13)) * 20MHz core clock */
+#define AR5416_IFS_EIFS_QUARTER_RATE_40 0xD48 /* (298 + (2 * 21)) * 10MHz core clock */
+
+#define AR5416_IFS_SLOT_FULL_RATE_44 0x18c /* 9 us half, 44 MHz core clock (9*44) */
+#define AR5416_IFS_SLOT_HALF_RATE_44 0x11e /* 13 us half, 22 MHz core clock (13*22) */
+#define AR5416_IFS_SLOT_QUARTER_RATE_44 0xe7 /* 21 us quarter, 11 MHz core clock (21*11) */
+
+#define AR5416_IFS_EIFS_FULL_RATE_44 0xfd0 /* (74 + (2 * 9)) * 44MHz core clock */
+#define AR5416_IFS_EIFS_HALF_RATE_44 0xf0a /* (149 + (2 * 13)) * 22MHz core clock */
+#define AR5416_IFS_EIFS_QUARTER_RATE_44 0xe9c /* (298 + (2 * 21)) * 11MHz core clock */
+
+#define AR5416_INIT_USEC_40 40
+#define AR5416_HALF_RATE_USEC_40 19 /* ((40 / 2) - 1 ) */
+#define AR5416_QUARTER_RATE_USEC_40 9 /* ((40 / 4) - 1 ) */
+
+#define AR5416_INIT_USEC_44 44
+#define AR5416_HALF_RATE_USEC_44 21 /* ((44 / 2) - 1 ) */
+#define AR5416_QUARTER_RATE_USEC_44 10 /* ((44 / 4) - 1 ) */
+
+
+/* XXX What should these be for 40/44MHz clocks (and half/quarter) ? */
+#define AR5416_RX_NON_FULL_RATE_LATENCY 63
+#define AR5416_TX_HALF_RATE_LATENCY 108
+#define AR5416_TX_QUARTER_RATE_LATENCY 216
+
+/*
+ * Adjust various register settings based on half/quarter rate clock setting.
+ * This includes:
+ *
+ * + USEC, TX/RX latency,
+ * + IFS params: slot, eifs, misc etc.
+ *
+ * TODO:
+ *
+ * + Verify which other registers need to be tweaked;
+ * + Verify the behaviour of this for 5GHz fast and non-fast clock mode;
+ * + This just plain won't work for long distance links - the coverage class
+ * code isn't aware of the slot/ifs/ACK/RTS timeout values that need to
+ * change;
+ * + Verify whether the 32KHz USEC value needs to be kept for the 802.11n
+ * series chips?
+ * + Calculate/derive values for 2GHz, 5GHz, 5GHz fast clock
+ */
+static void
+ar5416SetIFSTiming(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ uint32_t txLat, rxLat, usec, slot, refClock, eifs, init_usec;
+ int clk_44 = 0;
+
+ HALASSERT(IEEE80211_IS_CHAN_HALF(chan) ||
+ IEEE80211_IS_CHAN_QUARTER(chan));
+
+ /* 2GHz and 5GHz fast clock - 44MHz; else 40MHz */
+ if (IEEE80211_IS_CHAN_2GHZ(chan))
+ clk_44 = 1;
+ else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
+ IS_5GHZ_FAST_CLOCK_EN(ah, chan))
+ clk_44 = 1;
+
+ /* XXX does this need save/restoring for the 11n chips? */
+ refClock = OS_REG_READ(ah, AR_USEC) & AR_USEC_USEC32;
+
+ /*
+ * XXX This really should calculate things, not use
+ * hard coded values! Ew.
+ */
+ if (IEEE80211_IS_CHAN_HALF(chan)) {
+ if (clk_44) {
+ slot = AR5416_IFS_SLOT_HALF_RATE_44;
+ rxLat = AR5416_RX_NON_FULL_RATE_LATENCY <<
+ AR5416_USEC_RX_LAT_S;
+ txLat = AR5416_TX_HALF_RATE_LATENCY <<
+ AR5416_USEC_TX_LAT_S;
+ usec = AR5416_HALF_RATE_USEC_44;
+ eifs = AR5416_IFS_EIFS_HALF_RATE_44;
+ init_usec = AR5416_INIT_USEC_44 >> 1;
+ } else {
+ slot = AR5416_IFS_SLOT_HALF_RATE_40;
+ rxLat = AR5416_RX_NON_FULL_RATE_LATENCY <<
+ AR5416_USEC_RX_LAT_S;
+ txLat = AR5416_TX_HALF_RATE_LATENCY <<
+ AR5416_USEC_TX_LAT_S;
+ usec = AR5416_HALF_RATE_USEC_40;
+ eifs = AR5416_IFS_EIFS_HALF_RATE_40;
+ init_usec = AR5416_INIT_USEC_40 >> 1;
+ }
+ } else { /* quarter rate */
+ if (clk_44) {
+ slot = AR5416_IFS_SLOT_QUARTER_RATE_44;
+ rxLat = AR5416_RX_NON_FULL_RATE_LATENCY <<
+ AR5416_USEC_RX_LAT_S;
+ txLat = AR5416_TX_QUARTER_RATE_LATENCY <<
+ AR5416_USEC_TX_LAT_S;
+ usec = AR5416_QUARTER_RATE_USEC_44;
+ eifs = AR5416_IFS_EIFS_QUARTER_RATE_44;
+ init_usec = AR5416_INIT_USEC_44 >> 2;
+ } else {
+ slot = AR5416_IFS_SLOT_QUARTER_RATE_40;
+ rxLat = AR5416_RX_NON_FULL_RATE_LATENCY <<
+ AR5416_USEC_RX_LAT_S;
+ txLat = AR5416_TX_QUARTER_RATE_LATENCY <<
+ AR5416_USEC_TX_LAT_S;
+ usec = AR5416_QUARTER_RATE_USEC_40;
+ eifs = AR5416_IFS_EIFS_QUARTER_RATE_40;
+ init_usec = AR5416_INIT_USEC_40 >> 2;
+ }
+ }
+
+ /* XXX verify these! */
+ OS_REG_WRITE(ah, AR_USEC, (usec | refClock | txLat | rxLat));
+ OS_REG_WRITE(ah, AR_D_GBL_IFS_SLOT, slot);
+ OS_REG_WRITE(ah, AR_D_GBL_IFS_EIFS, eifs);
+ OS_REG_RMW_FIELD(ah, AR_D_GBL_IFS_MISC,
+ AR_D_GBL_IFS_MISC_USEC_DURATION, init_usec);
+}
+
More information about the svn-src-head
mailing list