svn commit: r226489 - head/sys/dev/ath/ath_hal/ar5212

Adrian Chadd adrian at FreeBSD.org
Tue Oct 18 03:17:06 UTC 2011


Author: adrian
Date: Tue Oct 18 03:17:06 2011
New Revision: 226489
URL: http://svn.freebsd.org/changeset/base/226489

Log:
  Port over some missing code from the ar5212 reference driver reset path.
  
  The final missing bit here is enabling the PCI configuration register
  read, but there's currently no glue available for the HAL to read (and
  write) PCI configuration space registers.
  
  Obtained from:	Atheros

Modified:
  head/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
  head/sys/dev/ath/ath_hal/ar5212/ar5212reg.h

Modified: head/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c	Tue Oct 18 03:01:41 2011	(r226488)
+++ head/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c	Tue Oct 18 03:17:06 2011	(r226489)
@@ -96,6 +96,16 @@ write_common(struct ath_hal *ah, const H
 #define IS_DISABLE_FAST_ADC_CHAN(x) (((x) == 2462) || ((x) == 2467))
 
 /*
+ * XXX NDIS 5.x code had MAX_RESET_WAIT set to 2000 for AP code
+ * and 10 for Client code
+ */
+#define	MAX_RESET_WAIT			10
+
+#define	TX_QUEUEPEND_CHECK		1
+#define	TX_ENABLE_CHECK			2
+#define	RX_ENABLE_CHECK			4
+
+/*
  * Places the device in and out of reset and then places sane
  * values in the registers based on EEPROM config, initialization
  * vectors (as determined by the mode), and station configuration
@@ -1104,6 +1114,76 @@ ar5212ResetCalValid(struct ath_hal *ah, 
 	return AH_TRUE;
 }
 
+/**************************************************************
+ * ar5212MacStop
+ *
+ * Disables all active QCUs and ensure that the mac is in a
+ * quiessence state.
+ */
+static HAL_BOOL
+ar5212MacStop(struct ath_hal *ah)
+{
+	HAL_BOOL     status;
+	uint32_t    count;
+	uint32_t    pendFrameCount;
+	uint32_t    macStateFlag;
+	uint32_t    queue;
+
+	status = AH_FALSE;
+
+	/* Disable Rx Operation ***********************************/
+	OS_REG_SET_BIT(ah, AR_CR, AR_CR_RXD);
+
+	/* Disable TX Operation ***********************************/
+#ifdef NOT_YET
+	ar5212SetTxdpInvalid(ah);
+#endif
+	OS_REG_SET_BIT(ah, AR_Q_TXD, AR_Q_TXD_M);
+
+	/* Polling operation for completion of disable ************/
+	macStateFlag = TX_ENABLE_CHECK | RX_ENABLE_CHECK;
+
+	for (count = 0; count < MAX_RESET_WAIT; count++) {
+		if (macStateFlag & RX_ENABLE_CHECK) {
+			if (!OS_REG_IS_BIT_SET(ah, AR_CR, AR_CR_RXE)) {
+				macStateFlag &= ~RX_ENABLE_CHECK;
+			}
+		}
+
+		if (macStateFlag & TX_ENABLE_CHECK) {
+			if (!OS_REG_IS_BIT_SET(ah, AR_Q_TXE, AR_Q_TXE_M)) {
+				macStateFlag &= ~TX_ENABLE_CHECK;
+				macStateFlag |= TX_QUEUEPEND_CHECK;
+			}
+		}
+		if (macStateFlag & TX_QUEUEPEND_CHECK) {
+			pendFrameCount = 0;
+			for (queue = 0; queue < AR_NUM_DCU; queue++) {
+				pendFrameCount += OS_REG_READ(ah,
+				    AR_Q0_STS + (queue * 4)) &
+				    AR_Q_STS_PEND_FR_CNT;
+			}
+			if (pendFrameCount == 0) {
+				macStateFlag &= ~TX_QUEUEPEND_CHECK;
+			}
+		}
+		if (macStateFlag == 0) {
+			status = AH_TRUE;
+			break;
+		}
+		OS_DELAY(50);
+	}
+
+	if (status != AH_TRUE) {
+		HALDEBUG(ah, HAL_DEBUG_RESET,
+		    "%s:Failed to stop the MAC state 0x%x\n",
+		    __func__, macStateFlag);
+	}
+
+	return status;
+}
+
+
 /*
  * Write the given reset bit mask into the reset register
  */
@@ -1113,12 +1193,75 @@ ar5212SetResetReg(struct ath_hal *ah, ui
 	uint32_t mask = resetMask ? resetMask : ~0;
 	HAL_BOOL rt;
 
-	/* XXX ar5212MacStop & co. */
-
+	/* Never reset the PCIE core */
 	if (AH_PRIVATE(ah)->ah_ispcie) {
 		resetMask &= ~AR_RC_PCI;
 	}
 
+	if (resetMask & (AR_RC_MAC | AR_RC_PCI)) {
+		/*
+		 * To ensure that the driver can reset the
+		 * MAC, wake up the chip
+		 */
+		rt = ar5212SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE);
+
+		if (rt != AH_TRUE) {
+			return rt;
+		}
+
+		/*
+		 * Disable interrupts
+		 */
+		OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+		OS_REG_READ(ah, AR_IER);
+
+		if (ar5212MacStop(ah) != AH_TRUE) {
+			/*
+			 * Failed to stop the MAC gracefully; let's be more forceful then
+			 */
+
+			/* need some delay before flush any pending MMR writes */
+			OS_DELAY(15);
+			OS_REG_READ(ah, AR_RXDP);
+
+			resetMask |= AR_RC_MAC | AR_RC_BB;
+			/* _Never_ reset PCI Express core */
+			if (! AH_PRIVATE(ah)->ah_ispcie) {
+				resetMask |= AR_RC_PCI;
+			}
+#if 0
+			/*
+			 * Flush the park address of the PCI controller
+			*/
+			/* Read PCI slot information less than Hainan revision */
+			if (AH_PRIVATE(ah)->ah_bustype == HAL_BUS_TYPE_PCI) {
+				if (!IS_5112_REV5_UP(ah)) {
+#define PCI_COMMON_CONFIG_STATUS    0x06
+					u_int32_t    i;
+					u_int16_t    reg16;
+
+					for (i = 0; i < 32; i++) {
+						ath_hal_read_pci_config_space(ah,
+						    PCI_COMMON_CONFIG_STATUS,
+						    &reg16, sizeof(reg16));
+					}
+				}
+#undef PCI_COMMON_CONFIG_STATUS
+			}
+#endif
+		} else {
+			/*
+			 * MAC stopped gracefully; no need to warm-reset the PCI bus
+			 */
+
+			resetMask &= ~AR_RC_PCI;
+
+			/* need some delay before flush any pending MMR writes */
+			OS_DELAY(15);
+			OS_REG_READ(ah, AR_RXDP);
+		}
+	}
+
 	(void) OS_REG_READ(ah, AR_RXDP);/* flush any pending MMR writes */
 	OS_REG_WRITE(ah, AR_RC, resetMask);
 	OS_DELAY(15);			/* need to wait at least 128 clocks

Modified: head/sys/dev/ath/ath_hal/ar5212/ar5212reg.h
==============================================================================
--- head/sys/dev/ath/ath_hal/ar5212/ar5212reg.h	Tue Oct 18 03:01:41 2011	(r226488)
+++ head/sys/dev/ath/ath_hal/ar5212/ar5212reg.h	Tue Oct 18 03:17:06 2011	(r226489)
@@ -94,7 +94,9 @@
 #define	AR_QTXDP(_i)	(AR_Q0_TXDP + ((_i)<<2))
 
 #define	AR_Q_TXE	0x0840	/* MAC Transmit Queue enable */
+#define	AR_Q_TXE_M	0x000003FF	/* Mask for TXE (QCU 0-9) */
 #define	AR_Q_TXD	0x0880	/* MAC Transmit Queue disable */
+#define	AR_Q_TXD_M	0x000003FF	/* Mask for TXD (QCU 0-9) */
 
 #define	AR_Q0_CBRCFG	0x08c0	/* MAC CBR configuration */
 #define	AR_Q1_CBRCFG	0x08c4	/* MAC CBR configuration */


More information about the svn-src-head mailing list