patch-2.4.25 linux-2.4.25/drivers/net/sk98lin/skxmac2.c

Next file: linux-2.4.25/drivers/net/starfire.c
Previous file: linux-2.4.25/drivers/net/sk98lin/sktimer.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.24/drivers/net/sk98lin/skxmac2.c linux-2.4.25/drivers/net/sk98lin/skxmac2.c
@@ -2,8 +2,8 @@
  *
  * Name:	skxmac2.c
  * Project:	Gigabit Ethernet Adapters, Common Modules
- * Version:	$Revision: 1.99 $
- * Date:	$Date: 2003/07/11 12:19:33 $
+ * Version:	$Revision: 1.102 $
+ * Date:	$Date: 2003/10/02 16:53:58 $
  * Purpose:	Contains functions to initialize the MACs and PHYs
  *
  ******************************************************************************/
@@ -27,6 +27,23 @@
  * History:
  *
  *	$Log: skxmac2.c,v $
+ *	Revision 1.102  2003/10/02 16:53:58  rschmidt
+ *	Changed setting of GMAC parameters with new macros.
+ *	Added define SLIM around SkGm...LowPowerMode().
+ *	Editorial changes.
+ *	
+ *	Revision 1.101  2003/09/16 14:49:07  rschmidt
+ *	Added routines SkGmClearRst(), SkXmClearRst, SkMacClearRst().
+ *	Added WA code for Yukon-Lite's COMA mode in SkGmHardRst().
+ *	Replaced PCI-Config R/W through internal access.
+ *	Fixed return from coma mode in SkGmLeaveLowPowerMode().
+ *	Fixed compiler warnings for different types.
+ *	Editorial changes.
+ *	
+ *	Revision 1.100  2003/09/16 07:09:11  mschmid
+ *	Added functions SkGmEnterLowPowerMode() and
+ *	SkGmLeaveLowPowerMode()
+ *	
  *	Revision 1.99  2003/07/11 12:19:33  rschmidt
  *	Reduced init values for Master & Slave downshift counters to
  *	minimum values.
@@ -164,7 +181,7 @@
  *	Revision 1.74  2002/08/12 14:00:17  rschmidt
  *	Replaced usage of Broadcom PHY Ids with defines.
  *	Corrected error messages in SkGmMacStatistic().
- *	Made SkMacPromiscMode() public for ADDR-Modul.
+ *	Made SkMacPromiscMode() public for ADDR-Module.
  *	Editorial changes.
  *	
  *	Revision 1.73  2002/08/08 16:26:24  rschmidt
@@ -475,7 +492,7 @@
 
 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
 static const char SysKonnectFileId[] =
-	"@(#) $Id: skxmac2.c,v 1.99 2003/07/11 12:19:33 rschmidt Exp $ (C) Marvell.";
+	"@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
 #endif
 
 #ifdef GENESIS
@@ -1343,7 +1360,7 @@
  * Description:
  *	The XMAC of the specified 'Port' and all connected devices
  *	(PHY and SERDES) will receive a reset signal on its *Reset pins.
- *	External PHYs must be reset be clearing a bit in the GPIO register
+ *	External PHYs must be reset by clearing a bit in the GPIO register
  *  (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
  *
  * ATTENTION:
@@ -1386,23 +1403,62 @@
 
 	/* For external PHYs there must be special handling */
 	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-		/* reset external PHY */
+		
 		SK_IN32(IoC, B2_GP_IO, &Reg);
+		
 		if (Port == 0) {
-			Reg |= GP_DIR_0; /* set to output */
-			Reg &= ~GP_IO_0;
+			Reg |= GP_DIR_0; 	/* set to output */
+			Reg &= ~GP_IO_0;	/* set PHY reset (active low) */
 		}
 		else {
-			Reg |= GP_DIR_2; /* set to output */
-			Reg &= ~GP_IO_2;
+			Reg |= GP_DIR_2;	/* set to output */
+			Reg &= ~GP_IO_2;	/* set PHY reset (active low) */
 		}
+		/* reset external PHY */
 		SK_OUT32(IoC, B2_GP_IO, Reg);
 
 		/* short delay */
 		SK_IN32(IoC, B2_GP_IO, &Reg);
 	}
-
 }	/* SkXmHardRst */
+
+
+/******************************************************************************
+ *
+ *	SkXmClearRst() - Release the PHY & XMAC reset
+ *
+ * Description:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkXmClearRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	DWord;
+	
+	/* clear HW reset */
+	SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+	if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+
+		SK_IN32(IoC, B2_GP_IO, &DWord);
+
+		if (Port == 0) {
+			DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
+		}
+		else {
+			DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
+		}
+		/* Clear PHY reset */
+		SK_OUT32(IoC, B2_GP_IO, DWord);
+
+		/* Enable GMII interface */
+		XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
+	}
+}	/* SkXmClearRst */
 #endif /* GENESIS */
 
 
@@ -1452,10 +1508,6 @@
  *
  * Description:
  *
- * ATTENTION:
- * 	It is absolutely necessary to reset the SW_RST Bit first
- *	before calling this function.
- *
  * Returns:
  *	nothing
  */
@@ -1464,6 +1516,20 @@
 SK_IOC	IoC,	/* IO context */
 int		Port)	/* Port Index (MAC_1 + n) */
 {
+	SK_U32	DWord;
+	
+	/* WA code for COMA mode */
+	if (pAC->GIni.GIYukonLite &&
+		pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+		
+		SK_IN32(IoC, B2_GP_IO, &DWord);
+
+		DWord |= (GP_DIR_9 | GP_IO_9);
+
+		/* set PHY reset */
+		SK_OUT32(IoC, B2_GP_IO, DWord);
+	}
+
 	/* set GPHY Control reset */
 	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
 
@@ -1471,6 +1537,73 @@
 	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
 
 }	/* SkGmHardRst */
+
+
+/******************************************************************************
+ *
+ *	SkGmClearRst() - Release the GPHY & GMAC reset
+ *
+ * Description:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmClearRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	DWord;
+	
+#ifdef XXX
+		/* clear GMAC Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
+
+		/* set GMAC Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+#endif /* XXX */
+
+	/* WA code for COMA mode */
+	if (pAC->GIni.GIYukonLite &&
+		pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+		
+		SK_IN32(IoC, B2_GP_IO, &DWord);
+
+		DWord |= GP_DIR_9;		/* set to output */
+		DWord &= ~GP_IO_9;		/* clear PHY reset (active high) */
+
+		/* clear PHY reset */
+		SK_OUT32(IoC, B2_GP_IO, DWord);
+	}
+
+	/* set HWCFG_MODE */
+	DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
+		GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
+		(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
+		GPC_HWCFG_GMII_FIB);
+
+	/* set GPHY Control reset */
+	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
+
+	/* release GPHY Control reset */
+	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
+
+#ifdef VCPU
+	VCpuWait(9000);
+#endif /* VCPU */
+
+	/* clear GMAC Control reset */
+	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+
+#ifdef VCPU
+	VCpuWait(2000);
+	
+	SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
+			
+	SK_IN32(IoC, B0_ISRC, &DWord);
+#endif /* VCPU */
+
+}	/* SkGmClearRst */
 #endif /* YUKON */
 
 
@@ -1553,6 +1686,38 @@
 }	/* SkMacHardRst */
 
 
+/******************************************************************************
+ *
+ *	SkMacClearRst() - Clear the MAC reset
+ *
+ * Description:	calls a clear MAC reset routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacClearRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	
+#ifdef GENESIS
+	if (pAC->GIni.GIGenesis) {
+		
+		SkXmClearRst(pAC, IoC, Port);
+	}
+#endif /* GENESIS */
+	
+#ifdef YUKON
+	if (pAC->GIni.GIYukon) {
+		
+		SkGmClearRst(pAC, IoC, Port);
+	}
+#endif /* YUKON */
+
+}	/* SkMacClearRst */
+
+
 #ifdef GENESIS
 /******************************************************************************
  *
@@ -1574,7 +1739,6 @@
 int		Port)		/* Port Index (MAC_1 + n) */
 {
 	SK_GEPORT	*pPrt;
-	SK_U32		Reg;
 	int			i;
 	SK_U16		SWord;
 
@@ -1594,32 +1758,10 @@
 	}
 
 	if (pPrt->PState == SK_PRT_RESET) {
-		/*
-		 * clear HW reset
-		 * Note: The SW reset is self clearing, therefore there is
-		 *	 nothing to do here.
-		 */
-		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
 
-		/* Ensure that XMAC reset release is done (errata from LReinbold?) */
-		SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
+		SkXmClearRst(pAC, IoC, Port);
 
-		/* Clear PHY reset */
 		if (pPrt->PhyType != SK_PHY_XMAC) {
-
-			SK_IN32(IoC, B2_GP_IO, &Reg);
-			
-			if (Port == 0) {
-				Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */
-			}
-			else {
-				Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */
-			}
-			SK_OUT32(IoC, B2_GP_IO, Reg);
-
-			/* Enable GMII interface */
-			XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
-
 			/* read Id from external PHY (all have the same address) */
 			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
 
@@ -1831,43 +1973,11 @@
 	}
 
 	if (pPrt->PState == SK_PRT_RESET) {
-		/* set GPHY Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
-
-		/* set GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-
-#ifdef XXX
-		/* clear GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
-
-		/* set GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-#endif /* XXX */
-
-		/* set HWCFG_MODE */
-		DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
-			GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
-			(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
-			GPC_HWCFG_GMII_FIB);
-
-		/* set GPHY Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
-
-		/* release GPHY Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
-
-#ifdef VCPU
-		VCpuWait(9000);
-#endif /* VCPU */
-
-		/* clear GMAC Control reset */
-		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
-
-#ifdef VCPU
-		VCpuWait(2000);
-#endif /* VCPU */
+		
+		SkGmHardRst(pAC, IoC, Port);
 
+		SkGmClearRst(pAC, IoC, Port);
+		
 		/* Auto-negotiation ? */
 		if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
 			/* Auto-negotiation disabled */
@@ -1906,6 +2016,7 @@
 			SWord |= GM_GPCR_DUP_FULL;
 		}
 
+		/* flow-control settings */
 		switch (pPrt->PFlowCtrlMode) {
 		case SK_FLOW_MODE_NONE:
 			/* set Pause Off */
@@ -1940,7 +2051,7 @@
 	(void)SkGmResetCounter(pAC, IoC, Port);
 
 	/* setup Transmit Control Register */
-	GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR);
+	GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
 
 	/* setup Receive Control Register */
 	GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
@@ -1954,7 +2065,9 @@
 	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
 #endif /* VCPU */
 
-    SWord = (SK_U16)(JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26));
+    SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
+			TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
+			TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
 	
 	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
 
@@ -1963,7 +2076,12 @@
 	GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
 #endif /* VCPU */
 	
-	SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH;
+	SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
+
+	if (pPrt->PMacLimit4) {
+		/* reset of collision counter after 4 consecutive collisions */
+		SWord |= GM_SMOD_LIMIT_4;
+	}
 
 	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
 		/* enable jumbo mode (Max. Frame Length = 9018) */
@@ -2021,11 +2139,13 @@
 	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
 	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
 
+#if defined(SK_DIAG) || defined(DEBUG)
 	/* read General Purpose Status */
 	GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
 	
 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("MAC Stat Reg=0x%04X\n", SWord));
+		("MAC Stat Reg.=0x%04X\n", SWord));
+#endif /* SK_DIAG || DEBUG */
 
 #ifdef SK_DIAG
 	c_print("MAC Stat Reg=0x%04X\n", SWord);
@@ -2226,6 +2346,7 @@
 				SKERR_HWI_E015MSG);
 		}
 
+		/* Set Flow-control capabilities */
 		switch (pPrt->PFlowCtrlMode) {
 		case SK_FLOW_MODE_NONE:
 			Ctrl |= PHY_X_P_NO_PAUSE;
@@ -2306,7 +2427,9 @@
 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
 		/* Set DuplexMode in Config register */
-		Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			Ctrl1 |= PHY_CT_DUP_MD;
+		}
 
 		/* Determine Master/Slave manually if not already done */
 		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
@@ -2346,6 +2469,7 @@
 				SKERR_HWI_E015MSG);
 		}
 
+		/* Set Flow-control capabilities */
 		switch (pPrt->PFlowCtrlMode) {
 		case SK_FLOW_MODE_NONE:
 			Ctrl3 |= PHY_B_P_NO_PAUSE;
@@ -2375,12 +2499,12 @@
 	/* Write 1000Base-T Control Register */
 	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
+		("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
 	
 	/* Write AutoNeg Advertisement Register */
 	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
+		("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
 	
 	if (DoLoop) {
 		/* Set the Phy Loopback bit, too */
@@ -2409,6 +2533,281 @@
 
 
 #ifdef YUKON
+#ifndef SK_SLIM
+/******************************************************************************
+ *
+ *	SkGmEnterLowPowerMode()
+ *
+ * Description:	
+ *	This function sets the Marvell Alaska PHY to the low power mode
+ *	given by parameter mode.
+ *	The following low power modes are available:
+ *		
+ *		- Coma Mode (Deep Sleep):
+ *			Power consumption: ~15 - 30 mW
+ *			The PHY cannot wake up on its own.
+ *
+ *		- IEEE 22.2.4.1.5 compatible power down mode
+ *			Power consumption: ~240 mW
+ *			The PHY cannot wake up on its own.
+ *
+ *		- energy detect mode
+ *			Power consumption: ~160 mW
+ *			The PHY can wake up on its own by detecting activity
+ *			on the CAT 5 cable.
+ *
+ *		- energy detect plus mode
+ *			Power consumption: ~150 mW
+ *			The PHY can wake up on its own by detecting activity
+ *			on the CAT 5 cable.
+ *			Connected devices can be woken up by sending normal link
+ *			pulses every one second.
+ *
+ * Note:
+ *
+ * Returns:
+ *		0: ok
+ *		1: error
+ */
+int SkGmEnterLowPowerMode(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (e.g. MAC_1) */
+SK_U8	Mode)		/* low power mode */
+{
+	SK_U16	Word;
+	SK_U32	DWord;
+	SK_U8	LastMode;
+	int		Ret = 0;
+
+	if (pAC->GIni.GIYukonLite &&
+	    pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+
+		/* save current power mode */
+		LastMode = pAC->GIni.GP[Port].PPhyPowerState;
+		pAC->GIni.GP[Port].PPhyPowerState = Mode;
+
+		switch (Mode) {
+			/* coma mode (deep sleep) */
+			case PHY_PM_DEEP_SLEEP:
+				/* setup General Purpose Control Register */
+				GM_OUT16(IoC, 0, GM_GP_CTRL, GM_GPCR_FL_PASS |
+					GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
+
+				/* apply COMA mode workaround */
+				SkGmPhyWrite(pAC, IoC, Port, 29, 0x001f);
+				SkGmPhyWrite(pAC, IoC, Port, 30, 0xfff3);
+
+				SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
+
+				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+				
+				/* Set PHY to Coma Mode */
+				SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord | PCI_PHY_COMA);
+				
+				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+			break;
+			
+			/* IEEE 22.2.4.1.5 compatible power down mode */
+			case PHY_PM_IEEE_POWER_DOWN:
+				/*
+				 * - disable MAC 125 MHz clock
+				 * - allow MAC power down
+				 */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+				Word |= PHY_M_PC_DIS_125CLK;
+				Word &=	~PHY_M_PC_MAC_POW_UP;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+				/*
+				 * register changes must be followed by a software
+				 * reset to take effect
+				 */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+				Word |= PHY_CT_RESET;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+
+				/* switch IEEE compatible power down mode on */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+				Word |= PHY_CT_PDOWN;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+			break;
+
+			/* energy detect and energy detect plus mode */
+			case PHY_PM_ENERGY_DETECT:
+			case PHY_PM_ENERGY_DETECT_PLUS:
+				/*
+				 * - disable MAC 125 MHz clock
+				 */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+				Word |= PHY_M_PC_DIS_125CLK;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+				
+				/* activate energy detect mode 1 */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+
+				/* energy detect mode */
+				if (Mode == PHY_PM_ENERGY_DETECT) {
+					Word |= PHY_M_PC_EN_DET;
+				}
+				/* energy detect plus mode */
+				else {
+					Word |= PHY_M_PC_EN_DET_PLUS;
+				}
+
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+				/*
+				 * reinitialize the PHY to force a software reset
+				 * which is necessary after the register settings
+				 * for the energy detect modes.
+				 * Furthermore reinitialisation prevents that the
+				 * PHY is running out of a stable state.
+				 */
+				SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+			break;
+
+			/* don't change current power mode */
+			default:
+				pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+				Ret = 1;
+			break;
+		}
+	}
+	/* low power modes are not supported by this chip */
+	else {
+		Ret = 1;
+	}
+
+	return(Ret);
+
+}	/* SkGmEnterLowPowerMode */
+
+/******************************************************************************
+ *
+ *	SkGmLeaveLowPowerMode()
+ *
+ * Description:	
+ *	Leave the current low power mode and switch to normal mode
+ *
+ * Note:
+ *
+ * Returns:
+ *		0:	ok
+ *		1:	error
+ */
+int SkGmLeaveLowPowerMode(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port)		/* Port Index (e.g. MAC_1) */
+{
+	SK_U32	DWord;
+	SK_U16	Word;
+	SK_U8	LastMode;
+	int		Ret = 0;
+
+	if (pAC->GIni.GIYukonLite &&
+		pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+
+		/* save current power mode */
+		LastMode = pAC->GIni.GP[Port].PPhyPowerState;
+		pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+
+		switch (LastMode) {
+			/* coma mode (deep sleep) */
+			case PHY_PM_DEEP_SLEEP:
+				SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
+
+				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+				
+				/* Release PHY from Coma Mode */
+				SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord & ~PCI_PHY_COMA);
+				
+				SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+				
+				SK_IN32(IoC, B2_GP_IO, &DWord);
+
+				/* set to output */
+				DWord |= (GP_DIR_9 | GP_IO_9);
+
+				/* set PHY reset */
+				SK_OUT32(IoC, B2_GP_IO, DWord);
+
+				DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
+
+				/* clear PHY reset */
+				SK_OUT32(IoC, B2_GP_IO, DWord);
+			break;
+			
+			/* IEEE 22.2.4.1.5 compatible power down mode */
+			case PHY_PM_IEEE_POWER_DOWN:
+				/*
+				 * - enable MAC 125 MHz clock
+				 * - set MAC power up
+				 */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+				Word &= ~PHY_M_PC_DIS_125CLK;
+				Word |=	PHY_M_PC_MAC_POW_UP;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+				/*
+				 * register changes must be followed by a software
+				 * reset to take effect
+				 */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+				Word |= PHY_CT_RESET;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+
+				/* switch IEEE compatible power down mode off */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+				Word &= ~PHY_CT_PDOWN;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+			break;
+
+			/* energy detect and energy detect plus mode */
+			case PHY_PM_ENERGY_DETECT:
+			case PHY_PM_ENERGY_DETECT_PLUS:
+				/*
+				 * - enable MAC 125 MHz clock
+				 */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+				Word &= ~PHY_M_PC_DIS_125CLK;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+				
+				/* disable energy detect mode */
+				SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+				Word &= ~PHY_M_PC_EN_DET_MSK;
+				SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+
+				/*
+				 * reinitialize the PHY to force a software reset
+				 * which is necessary after the register settings
+				 * for the energy detect modes.
+				 * Furthermore reinitialisation prevents that the
+				 * PHY is running out of a stable state.
+				 */
+				SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+			break;
+
+			/* don't change current power mode */
+			default:
+				pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+				Ret = 1;
+			break;
+		}
+	}
+	/* low power modes are not supported by this chip */
+	else {
+		Ret = 1;
+	}
+
+	return(Ret);
+
+}	/* SkGmLeaveLowPowerMode */
+#endif /* !SK_SLIM */
+
+
 /******************************************************************************
  *
  *	SkGmInitPhyMarv() - Initialize the Marvell Phy registers
@@ -2457,7 +2856,6 @@
 	VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
 		Port, DoLoop);
 #else /* VCPU */
-	
 	if (DoLoop) {
 		/* Set 'MAC Power up'-bit, set Manual MDI configuration */
 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
@@ -2475,16 +2873,20 @@
 	
 		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
+			("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
 	}
 
 	/* Read PHY Control */
 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
 
+	if (!AutoNeg) {
+		/* Disable Auto-negotiation */
+		PhyCtrl &= ~PHY_CT_ANE;
+	}
+
 	PhyCtrl |= PHY_CT_RESET;
 	/* Assert software reset */
 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-
 #endif /* VCPU */
 
 	PhyCtrl = 0 /* PHY_CT_COL_TST */;
@@ -2533,13 +2935,9 @@
 		if (!DoLoop) {
 			PhyCtrl |= PHY_CT_RESET;
 		}
-		/*
-		 * Do NOT enable Auto-negotiation here. This would hold
-		 * the link down because no IDLES are transmitted
-		 */
 	}
 	else {
-		PhyCtrl |= PHY_CT_ANE;
+		/* Set Auto-negotiation advertisement */
 		
 		if (pAC->GIni.GICopperType) {
 			/* Set Speed capabilities */
@@ -2554,6 +2952,7 @@
 				break;
 			case SK_LSPEED_100MBPS:
 				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+					/* advertise 10Base-T also */
 					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
 				break;
 			case SK_LSPEED_10MBPS:
@@ -2581,7 +2980,7 @@
 					SKERR_HWI_E015MSG);
 			}
 			
-			/* Set Auto-negotiation advertisement */
+			/* Set Flow-control capabilities */
 			switch (pPrt->PFlowCtrlMode) {
 			case SK_FLOW_MODE_NONE:
 				AutoNegAdv |= PHY_B_P_NO_PAUSE;
@@ -2618,7 +3017,7 @@
 					SKERR_HWI_E015MSG);
 			}
 			
-			/* Set Auto-negotiation advertisement */
+			/* Set Flow-control capabilities */
 			switch (pPrt->PFlowCtrlMode) {
 			case SK_FLOW_MODE_NONE:
 				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
@@ -2640,7 +3039,7 @@
 
 		if (!DoLoop) {
 			/* Restart Auto-negotiation */
-			PhyCtrl |= PHY_CT_RE_CFG;
+			PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
 		}
 	}
 	
@@ -2659,12 +3058,12 @@
 	/* Write 1000Base-T Control Register */
 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("1000B-T Ctrl=0x%04X\n", C1000BaseT));
+		("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
 	
 	/* Write AutoNeg Advertisement Register */
 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv));
+		("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
 #endif /* VCPU */
 	
 	if (DoLoop) {
@@ -2694,6 +3093,8 @@
 
 	/* Write to the PHY Control register */
 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
 
 #ifdef VCPU
 	VCpuWait(2000);
@@ -2712,7 +3113,7 @@
 	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
 
 	if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
-		/* only in forced 100Mbps mode */
+		/* only in forced 100 Mbps mode */
 		if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
 
 			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
@@ -2741,7 +3142,7 @@
 	/* Read AutoNeg Advertisement Register */
 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
 	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-		("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv));
+		("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
 	
 	/* Read Ext. PHY Specific Control */
 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
@@ -2818,13 +3219,15 @@
 	/* Auto-negotiation ? */
 	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
 		/*
-		 * level one spec say: "1000Mbps: manual mode not allowed"
+		 * level one spec say: "1000 Mbps: manual mode not allowed"
 		 * but lets see what happens...
 		 */
 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 			("InitPhyLone: no auto-negotiation Port %d\n", Port));
 		/* Set DuplexMode in Config register */
-		Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			Ctrl1 |= PHY_CT_DUP_MD;
+		}
 
 		/* Determine Master/Slave manually if not already done */
 		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
@@ -2857,6 +3260,7 @@
 				SKERR_HWI_E015MSG);
 		}
 
+		/* Set Flow-control capabilities */
 		switch (pPrt->PFlowCtrlMode) {
 		case SK_FLOW_MODE_NONE:
 			Ctrl3 |= PHY_L_P_NO_PAUSE;
@@ -2877,7 +3281,6 @@
 
 		/* Restart Auto-negotiation */
 		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
-
 	}
 	
 	/* Write 1000Base-T Control Register */
@@ -3019,10 +3422,10 @@
 
 	/* Check Duplex mismatch */
 	if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 	}
 	else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 	}
 	else {
 		/* Error */
@@ -3055,7 +3458,7 @@
 		/* PAUSE mismatch -> no PAUSE */
 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 	}
-	pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
+	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
 
 	return(SK_AND_OK);
 }	/* SkXmAutoNegDoneXmac */
@@ -3110,10 +3513,10 @@
 
 	/* Check Duplex mismatch */
 	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 	}
 	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 	}
 	else {
 		/* Error */
@@ -3156,7 +3559,7 @@
 		/* PAUSE mismatch -> no PAUSE */
 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 	}
-	pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
+	pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
 
 	return(SK_AND_OK);
 }	/* SkXmAutoNegDoneBcom */
@@ -3192,6 +3595,8 @@
 
 	/* Get PHY parameters */
 	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Link P.Abil.=0x%04X\n", LPAb));
 	
 	if ((LPAb & PHY_M_AN_RF) != 0) {
 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
@@ -3222,15 +3627,15 @@
 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 			("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
 		pPrt->PAutoNegFail = SK_TRUE;
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
 		return(SK_AND_DUP_CAP);
 	}
 	
 	if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 	}
 	else {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 	}
 	
 	/* Check PAUSE mismatch ??? */
@@ -3255,13 +3660,13 @@
 	/* set used link speed */
 	switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
 	case (unsigned)PHY_M_PS_SPEED_1000:
-		pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
+		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
 		break;
 	case PHY_M_PS_SPEED_100:
-		pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
+		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
 		break;
 	default:
-		pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
+		pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
 	}
 
 	return(SK_AND_OK);
@@ -3312,10 +3717,10 @@
 
 	/* Check Duplex mismatch */
 	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 	}
 	else {
-		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
+		pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 	}
 	
 	/* Check Master/Slave resolution */
@@ -3338,6 +3743,7 @@
 	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
 	/* we must manually resolve the abilities here */
 	pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+	
 	switch (pPrt->PFlowCtrlMode) {
 	case SK_FLOW_MODE_NONE:
 		/* default */
@@ -3457,6 +3863,9 @@
 		return(Rtv);
 	}
 
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("AutoNeg done Port %d\n", Port));
+	
 	/* We checked everything and may now enable the link */
 	pPrt->PAutoNegFail = SK_FALSE;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)