コード例 #1
0
/*******************************************************************************
* mvEthPhyRestartAN - Restart ethernet Phy Auto-Negotiation.
*
* DESCRIPTION:
*       This function resets a given ethernet Phy.
*
* INPUT:
*       phyAddr - Phy address.
*       timeout - in millisec; 0 - no timeout (don't wait)
*
* OUTPUT:
*       None.
*
* RETURN:   MV_OK       - Success
*           MV_TIMEOUT  - Timeout
*
*******************************************************************************/
MV_STATUS mvEthPhyRestartAN(MV_U32 phyAddr, int timeout)
{
	MV_U16  phyRegData;

	/* Reset the PHY */
	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
		return MV_FAIL;

	/* Set bit 12 to Enable autonegotiation of the PHY */
	phyRegData |= ETH_PHY_CTRL_AN_ENABLE_MASK;

	/* Set bit 9 to Restart autonegotiation of the PHY */
	phyRegData |= ETH_PHY_CTRL_AN_RESTART_MASK;
	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData);

	if (timeout == 0)
		return MV_OK;

	/* Wait untill Auotonegotiation completed */
	while (timeout > 0) {
		mvOsSleep(100);
		timeout -= 100;

		if (mvEthPhyRegRead(phyAddr, ETH_PHY_STATUS_REG, &phyRegData) != MV_OK)
			return MV_FAIL;

		if (phyRegData & ETH_PHY_STATUS_AN_DONE_MASK)
			return MV_OK;
	}
	return MV_TIMEOUT;
}
コード例 #2
0
/*******************************************************************************
* mvEthPhyReset - Reset ethernet Phy.
*
* DESCRIPTION:
*       This function resets a given ethernet Phy.
*
* INPUT:
*       phyAddr - Phy address.
*       timeout - in millisec
*
* OUTPUT:
*       None.
*
* RETURN:   MV_OK       - Success
*           MV_TIMEOUT  - Timeout
*
*******************************************************************************/
MV_STATUS mvEthPhyReset(MV_U32 phyAddr, int timeout)
{
	MV_U16  phyRegData;

	/* Reset the PHY */
	if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
		return MV_FAIL;

	/* Set bit 15 to reset the PHY */
	phyRegData |= ETH_PHY_CTRL_RESET_MASK;
	mvEthPhyRegWrite(phyAddr, ETH_PHY_CTRL_REG, phyRegData);

	/* Wait untill Reset completed */
	while (timeout > 0) {
		mvOsSleep(100);
		timeout -= 100;

		if (mvEthPhyRegRead(phyAddr, ETH_PHY_CTRL_REG, &phyRegData) != MV_OK)
			return MV_FAIL;

		if ((phyRegData & ETH_PHY_CTRL_RESET_MASK) == 0)
			return MV_OK;
	}
	return MV_TIMEOUT;
}
コード例 #3
0
/******************************************************************************
* mvEthCompSataConfig
*
* DESCRIPTION:
*	Configure ethernet complex for sata port output.
*
* INPUT:
*	ethCompCfg - Ethernet complex configuration bitmap.
*
* OUTPUT:
*	None.
*
* RETURN:
*	MV_OK on success,
*	MV_ERROR otherwise.
*******************************************************************************/
MV_STATUS mvEthCompSataConfig(MV_U32 ethCompCfg)
{
	MV_U32 reg;
	MV_U32 tmp;
	MV_U16 serdesReg;

	if (!(ethCompCfg & ESC_OPT_SATA))
		return MV_OK;

	/* 3.8.3. LP_SERDES_PHY initialization:
	 * 3.8.3.1. Set LP_SERDES to reset: set Regunit Software Reset Control
	 * register to Reset (0x1).
	 */
	MV_REG_BIT_SET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);

	/* 3.8.3.2. De-assert LP_SERDES reset: set Regunit Software Reset
	 * Control register to 0x0.
	 */
	MV_REG_BIT_RESET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);

	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));

	/* 3.8.2.4. Connect LP_SERDES_PHY to required source: set Regunit
	 * Ethernet_Complex_Control_0 register, field "LpphyMode" to "lpphyMode".
	 */
	tmp = 0x1;

	reg &= ~ETHCC_LPPHYMODE_MASK;
	reg |= (tmp << ETHCC_LPPHYMODE_OFFSET);
	reg |= ETHCC_LP_SERDES_DATA_SWAP_TX_MASK | ETHCC_LP_SERDES_DATA_SWAP_RX_MASK;
	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);

	mvEthCompSetSerdesDefaults();

	/* 3.8.3.3. Power up LP_SERDES: set Gunit Serdes Configuration
	 * (SERDESCFG) register, fields "PU_TX", "PU_RX, "PU_PLL" (bits 1,2,3)
	 * to Enable (0x1)
	 */
	reg = MV_REG_READ(MV_SATACOMP_SERDESCFG_REG);
	reg &= ~SERDES_CFG_PU_TX_MASK;
	reg &= ~SERDES_CFG_PU_RX_MASK;
	reg &= ~SERDES_CFG_PU_PLL_MASK;
	MV_REG_WRITE(MV_SATACOMP_SERDESCFG_REG, reg);

	/* 3.8.3.4. Configuring the LP_SERDES to Reference clock 25M, and
	 * PHY_MODE to SERDES APB3 Reg 0x1. Access to LP_SERDES registers is
	 * done by accessing Gunit0, base address
	 * (0xE00 + (Serdes Reg Address << 2)) 0xE00 + 0x1<<2 = 0x4 + 0xE00 = 0xE04.
	 * Configure to -0xF88.
	 */
	mvEthCompSerdesRegWrite(0x1, 0xF801);

	/* 3.8.3.5. Configyre LP_SERED data rate, by setting Gunit Serdes
	 * Configuration (SERDESCFG) register, fields "PIN_PHY_GEN_TX" and
	 * "PIN_PHY_GEN_RX" to 5Gbps (0xA).
	 */
	tmp = 0x1;

	reg = MV_REG_READ(MV_SATACOMP_SERDESCFG_REG);
	reg &= ~SERDES_CFG_PHY_GEN_RX_MASK;
	reg |= (tmp << SERDES_CFG_PHY_GEN_RX_OFFSET);
	reg &= ~SERDES_CFG_PHY_GEN_TX_MASK;
	reg |= (tmp << SERDES_CFG_PHY_GEN_TX_OFFSET);
	MV_REG_WRITE(MV_SATACOMP_SERDESCFG_REG, reg);

	/* Set PHY Gen Tx & Rx to 0xA, Same as in reg MV_ETHCOMP_SERDESCFG_REG
	 ** Bit[9] - Dig_test_bus_en.
	 */
	mvEthCompSerdesRegWrite(0x26, 0x111);

	/* 3.8.3.6. Configuring the LP_SERDES to 10 bit interface, by setting
	 * its internal register 0x23[11:10] to 0x1. Access to LP_SERDES
	 * registers is done by accessing Gunit0, base address
	 * (0xE00 + (Serdes Reg Address << 2)) = 0xE00 + 0x23<<2 =  0xE00 + 0x8c = 0xE8c.
	 */
	serdesReg = mvEthCompSerdesRegRead(0x23);
	serdesReg &= ~(0x3 << 10);

	if ((ethCompCfg & ESC_OPT_SATA) || (ethCompCfg & ESC_OPT_QSGMII))
		serdesReg |= (0x1 << 10);

	mvEthCompSerdesRegWrite(0x23, serdesReg);

	/* 3.8.3.7. Wait for LP_SERDES pin "PLL_READY" to be 0x1. This pin is
	 * reflected in Gunit Serdes Status (SERDESSTS) register, bit[2].
	 */
	do {
		reg = MV_REG_READ(MV_SATACOMP_SERDESSTS_REG);
	} while ((reg & (1 << 2)) == 0);

	/* 3.8.3.8. Set PIN_RX_INIT to 1b1 for at least 16 TXDCLK cycles. Set
	 * Gunit Serdes Configuration (SERDESCFG) register, field "PIN_RX_INIT"
	 * to Enable (0x1).
	 */
	MV_REG_BIT_SET(MV_SATACOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);
	mvOsSleep(10);

	/* 3.8.3.9. Wait for LP_SERDES pin "PIN_RX_INIT_DONE" to be 0x1. This
	 * pin is reflected in Gunit Serdes Status (SERDESSTS) register, bit[0].
	 */
	do {
		reg = MV_REG_READ(MV_SATACOMP_SERDESSTS_REG);
	} while ((reg & 0x1) == 0);

	/* 3.8.3.10. Set PIN_RX_INIT back to 0x0. Set Gunit Serdes Configuration
	 * (SERDESCFG) register; field "PIN_RX_INIT" to Enable (0x0).
	 */
	MV_REG_BIT_RESET(MV_SATACOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);

	return MV_OK;
}
コード例 #4
0
/******************************************************************************
* mvEthCompSerdesConfig
*
* DESCRIPTION:
*	Initialize serdes according to require PHY mode.
*
* INPUT:
*	ethCompCfg - Ethernet complex configuration bitmap.
*
* OUTPUT:
*	None.
*
* RETURN:
*	MV_OK on success,
*	MV_ERROR otherwise.
*******************************************************************************/
static MV_STATUS mvEthCompSerdesConfig(MV_U32 ethCompCfg)
{
	MV_U32 reg;
	MV_U32 tmp;
	MV_U16 serdesReg;

	reg = MV_REG_READ(MV_ETHCOMP_CTRL_REG(0));

	/* 3.8.2.4. Connect LP_SERDES_PHY to required source: set Regunit
	 * Ethernet_Complex_Control_0 register, field "LpphyMode" to "lpphyMode".
	 */
	if (ethCompCfg & (ESC_OPT_SGMII | ESC_OPT_SGMII_2_5))
		tmp = 0x0;
	else if (ethCompCfg & ESC_OPT_QSGMII)
		tmp = 0x2;
	else if (ethCompCfg & ESC_OPT_SATA)
		tmp = 0x1;
	else
		tmp = 0x3;

	reg &= ~ETHCC_LPPHYMODE_MASK;
	reg |= (tmp << ETHCC_LPPHYMODE_OFFSET);
	MV_REG_WRITE(MV_ETHCOMP_CTRL_REG(0), reg);

	/* 3.8.2.5. Change signal detect indication polarity: set Regunit
	 * QSGMII Control 1 register, field "QsgmiiInvSigdet" to 0x1.
	 */
	if (ethCompCfg & ESC_OPT_QSGMII) {
		reg = MV_REG_READ(MV_ETHCOMP_QSGMII_CONTROL_REG(1));
		reg &= ~QSGCTRL_INV_SIG_DET_MASK;
		reg |= (0x1 << QSGCTRL_INV_SIG_DET_OFFSET);
		MV_REG_WRITE(MV_ETHCOMP_QSGMII_CONTROL_REG(1), reg);
	}

	/* 3.8.3. LP_SERDES_PHY initialization:
	 * 3.8.3.1. Set LP_SERDES to reset: set Regunit Software Reset Control
	 * register to Reset (0x1).
	 */
	MV_REG_BIT_SET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);

	/* 3.8.3.2. De-assert LP_SERDES reset: set Regunit Software Reset
	 * Control register to 0x0.
	 */
	MV_REG_BIT_RESET(SOFT_RESET_CTRL_REG, SRC_LPSRDSSWRSTN_MASK);

	mvEthCompSetSerdesDefaults();
	if (ethCompCfg & ESC_OPT_QSGMII) {
		mvEthCompSerdesRegWrite(0x25, 0x0);
		mvEthCompSerdesRegWrite(0x24, mvEthCompSerdesRegRead(0x24) | 0x8000);
		mvEthCompSerdesRegWrite(0xD, 0x0BE0);
		mvEthCompSerdesRegWrite(0xE, 0x5055);
	} else if (ethCompCfg & ESC_OPT_SGMII_2_5) {
		mvEthCompSerdesRegWrite(0xD, 0x0BEF);
		mvEthCompSerdesRegWrite(0xE, 0x9055);
	} else if (ethCompCfg & ESC_OPT_SGMII) {
		mvEthCompSerdesRegWrite(0xD, 0x0430);
		mvEthCompSerdesRegWrite(0xE, 0x0080);
	}

	/* 3.8.3.3. Power up LP_SERDES: set Gunit Serdes Configuration
	 * (SERDESCFG) register, fields "PU_TX", "PU_RX, "PU_PLL" (bits 1,2,3)
	 * to Enable (0x1)
	 */
	reg = MV_REG_READ(MV_ETHCOMP_SERDESCFG_REG);
	reg &= ~SERDES_CFG_PU_TX_MASK;
	reg &= ~SERDES_CFG_PU_RX_MASK;
	reg &= ~SERDES_CFG_PU_PLL_MASK;
	MV_REG_WRITE(MV_ETHCOMP_SERDESCFG_REG, reg);

	/* 3.8.3.4. Configuring the LP_SERDES to Reference clock 25M, and
	 * PHY_MODE to SERDES APB3 Reg 0x1. Access to LP_SERDES registers is
	 * done by accessing Gunit0, base address
	 * (0xE00 + (Serdes Reg Address << 2)) 0xE00 + 0x1<<2 = 0x4 + 0xE00 = 0xE04.
	 * Configure to -0xF88.
	 */
	mvEthCompSerdesRegWrite(0x1, 0xF880);	/* Was 0xF881 */

	/* 3.8.3.5. Configyre LP_SERED data rate, by setting Gunit Serdes
	 * Configuration (SERDESCFG) register, fields "PIN_PHY_GEN_TX" and
	 * "PIN_PHY_GEN_RX" to 5Gbps (0xA).
	 */
	tmp = 0x4;
	if (ethCompCfg & ESC_OPT_QSGMII)
		tmp = 0xA;
	if (ethCompCfg & ESC_OPT_SATA)
		tmp = 0x1;

	reg = MV_REG_READ(MV_ETHCOMP_SERDESCFG_REG);
	reg &= ~SERDES_CFG_PHY_GEN_RX_MASK;
	reg |= (tmp << SERDES_CFG_PHY_GEN_RX_OFFSET);
	reg &= ~SERDES_CFG_PHY_GEN_TX_MASK;
	reg |= (tmp << SERDES_CFG_PHY_GEN_TX_OFFSET);
	MV_REG_WRITE(MV_ETHCOMP_SERDESCFG_REG, reg);

	/* Set PHY Gen Tx & Rx to 0xA, Same as in reg MV_ETHCOMP_SERDESCFG_REG
	 ** Bit[9] - Dig_test_bus_en.
	 */
	if (ethCompCfg & ESC_OPT_QSGMII)
		mvEthCompSerdesRegWrite(0x26, 0x3AA);

	if (ethCompCfg & ESC_OPT_SGMII)
		mvEthCompSerdesRegWrite(0x26, 0x144);

	if (ethCompCfg & ESC_OPT_SGMII_2_5)
		mvEthCompSerdesRegWrite(0x26, 0x8166);

	if (ethCompCfg & ESC_OPT_SATA)
		mvEthCompSerdesRegWrite(0x26, 0x111);

	/* 3.8.3.6. Configuring the LP_SERDES to 10 bit interface, by setting
	 * its internal register 0x23[11:10] to 0x1. Access to LP_SERDES
	 * registers is done by accessing Gunit0, base address
	 * (0xE00 + (Serdes Reg Address << 2)) = 0xE00 + 0x23<<2 =  0xE00 + 0x8c = 0xE8c.
	 */
	serdesReg = mvEthCompSerdesRegRead(0x23);
	serdesReg &= ~(0x3 << 10);

	if ((ethCompCfg & ESC_OPT_SATA) || (ethCompCfg & ESC_OPT_QSGMII))
		serdesReg |= (0x1 << 10);

/* 	serdesReg |= (0x1 << 10); */
/* 	serdesReg |= (0x1 << 12); */
/* 	serdesReg |= (0x1 << 13); // Analog loopback. */
	mvEthCompSerdesRegWrite(0x23, serdesReg);

#if 0
	serdesReg = mvEthCompSerdesRegRead(0x51);
	serdesReg |= (0x1 << 9);
	mvEthCompSerdesRegWrite(0x51, serdesReg);
#endif

	/* 3.8.3.7. Wait for LP_SERDES pin "PLL_READY" to be 0x1. This pin is
	 * reflected in Gunit Serdes Status (SERDESSTS) register, bit[2].
	 */
	do {
		reg = MV_REG_READ(MV_ETHCOMP_SERDESSTS_REG);
	} while ((reg & (1 << 2)) == 0);

	/* 3.8.3.8. Set PIN_RX_INIT to 1b1 for at least 16 TXDCLK cycles. Set
	 * Gunit Serdes Configuration (SERDESCFG) register, field "PIN_RX_INIT"
	 * to Enable (0x1).
	 */
	MV_REG_BIT_SET(MV_ETHCOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);
	mvOsSleep(10);

	/* 3.8.3.9. Wait for LP_SERDES pin "PIN_RX_INIT_DONE" to be 0x1. This
	 * pin is reflected in Gunit Serdes Status (SERDESSTS) register, bit[0].
	 */
	do {
		reg = MV_REG_READ(MV_ETHCOMP_SERDESSTS_REG);
	} while ((reg & 0x1) == 0);

	/* 3.8.3.10. Set PIN_RX_INIT back to 0x0. Set Gunit Serdes Configuration
	 * (SERDESCFG) register; field "PIN_RX_INIT" to Enable (0x0).
	 */
	MV_REG_BIT_RESET(MV_ETHCOMP_SERDESCFG_REG, SERDES_CFG_RX_INIT_MASK);

	return MV_OK;
}