Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Sep 2012 07:22:41 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r240447 - head/sys/dev/ath/ath_hal/ar5416
Message-ID:  <201209130722.q8D7Mf5t043642@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
+}
+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201209130722.q8D7Mf5t043642>