From owner-svn-src-all@FreeBSD.ORG Thu Sep 13 07:22:41 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 645EB106566B; Thu, 13 Sep 2012 07:22:41 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4F3398FC1A; Thu, 13 Sep 2012 07:22:41 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8D7Mf5h043644; Thu, 13 Sep 2012 07:22:41 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8D7Mf5t043642; Thu, 13 Sep 2012 07:22:41 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201209130722.q8D7Mf5t043642@svn.freebsd.org> From: Adrian Chadd Date: Thu, 13 Sep 2012 07:22:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r240447 - head/sys/dev/ath/ath_hal/ar5416 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Sep 2012 07:22:41 -0000 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); +} +