MV_STATUS   mvPp2PlcrHwTxqThreshSet(int txq, int idx)
{
	mvPp2WrReg(MV_PP2_PLCR_EDROP_TXQ_REG, txq);
	mvPp2WrReg(MV_PP2_PLCR_EDROP_TXQ_TR_REG, idx);

	return MV_OK;
}
MV_STATUS   mvPp2PlcrHwBucketSizeSet(int plcr, int commit, int excess)
{
	MV_U32 regVal;

	mvPp2WrReg(MV_PP2_PLCR_TABLE_INDEX_REG, plcr);
	regVal = MV_PP2_PLCR_EXCESS_SIZE_MASK(excess) | MV_PP2_PLCR_COMMIT_SIZE_MASK(commit);
	mvPp2WrReg(MV_PP2_PLCR_BUCKET_SIZE_REG, regVal);

	return MV_OK;
}
MV_STATUS   mvPp2PlcrHwTokenValue(int plcr, int value)
{
	MV_U32 regVal;

	mvPp2WrReg(MV_PP2_PLCR_TABLE_INDEX_REG, plcr);
	regVal = mvPp2RdReg(MV_PP2_PLCR_TOKEN_CFG_REG);

	regVal &= ~MV_PP2_PLCR_TOKEN_VALUE_ALL_MASK;
	regVal |= MV_PP2_PLCR_TOKEN_VALUE_MASK(value);
	mvPp2WrReg(MV_PP2_PLCR_TOKEN_CFG_REG, regVal);

	return MV_OK;
}
MV_STATUS   mvPp2PlcrHwColorModeSet(int plcr, int enable)
{
	MV_U32 regVal;

	mvPp2WrReg(MV_PP2_PLCR_TABLE_INDEX_REG, plcr);
	regVal = mvPp2RdReg(MV_PP2_PLCR_TOKEN_CFG_REG);
	if (enable)
		regVal |= MV_PP2_PLCR_COLOR_MODE_MASK;
	else
		regVal &= ~MV_PP2_PLCR_COLOR_MODE_MASK;

	mvPp2WrReg(MV_PP2_PLCR_TOKEN_CFG_REG, regVal);

	return MV_OK;
}
static void        mvPp2PlcrHwDump(int plcr)
{
	int units, type, tokens;
	MV_U32 regVal;

	mvPp2WrReg(MV_PP2_PLCR_TABLE_INDEX_REG, plcr);
	mvOsPrintf("%3d:  ", plcr);
	regVal = mvPp2RdReg(MV_PP2_PLCR_ENABLE_REG);
	mvOsPrintf("%4s", MV_BIT_CHECK(regVal, plcr) ? "Yes" : "No");

	regVal = mvPp2RdReg(MV_PP2_PLCR_BASE_PERIOD_REG);
	mvOsPrintf("  %6d", regVal & MV_PP2_PLCR_BASE_PERIOD_ALL_MASK);

	regVal = mvPp2RdReg(MV_PP2_PLCR_TOKEN_CFG_REG);
	units = regVal & MV_PP2_PLCR_TOKEN_UNIT_MASK;
	type = (regVal & MV_PP2_PLCR_TOKEN_TYPE_ALL_MASK) >> MV_PP2_PLCR_TOKEN_TYPE_OFFS;
	tokens =  (regVal & MV_PP2_PLCR_TOKEN_VALUE_ALL_MASK) >> MV_PP2_PLCR_TOKEN_VALUE_OFFS;
	mvOsPrintf("   %5s  %2d   %5d", units ? "pkts" : "bytes", type, tokens);

	regVal = mvPp2RdReg(MV_PP2_PLCR_BUCKET_SIZE_REG);
	mvOsPrintf("    %04x    %04x",
			(regVal & MV_PP2_PLCR_COMMIT_SIZE_ALL_MASK) >> MV_PP2_PLCR_COMMIT_SIZE_OFFS,
			(regVal & MV_PP2_PLCR_EXCESS_SIZE_ALL_MASK) >> MV_PP2_PLCR_EXCESS_SIZE_OFFS);

	regVal = mvPp2RdReg(MV_PP2_PLCR_COMMIT_TOKENS_REG);
	mvOsPrintf("    %08x", regVal);

	regVal = mvPp2RdReg(MV_PP2_PLCR_EXCESS_TOKENS_REG);
	mvOsPrintf("  %08x", regVal);

	mvOsPrintf("\n");
}
/*******************************************************************************
* mvPp2WinInit
*
* DESCRIPTION:
*	This function initialize ETH window decode unit. It set the default
*	address decode windows of the unit.
*
* INPUT:
*	addWinMap: An array holding the address decoding information for the
*		    system.
*
* OUTPUT:
*       None.
*
* RETURN:
*       MV_ERROR if setting fail.
*******************************************************************************/
MV_STATUS mvPp2WinInit(MV_U32 dummy/*backward compability*/, MV_UNIT_WIN_INFO *addrWinMap)
{
	MV_U32 winNum, winPrioIndex = 0, regVal = 0;
	MV_UNIT_WIN_INFO *addrDecWin;

	/* Initiate Ethernet address decode */
	/* First disable all address decode windows */
	for (winNum = 0; winNum < ETH_MAX_DECODE_WIN; winNum++)
		regVal |= MV_BIT_MASK(winNum);

	mvPp2WrReg(ETH_BASE_ADDR_ENABLE_REG, regVal);

	/* Go through all windows in user table until table terminator      */
	for (winNum = 0; ((ethAddrDecPrioTab[winPrioIndex] != TBL_TERM) && (winNum < ETH_MAX_DECODE_WIN));) {
		addrDecWin = &addrWinMap[ethAddrDecPrioTab[winPrioIndex]];

		if (addrDecWin->enable == MV_TRUE) {
			if (MV_OK != mvPp2WinWrite(0, winNum, addrDecWin)) {
				mvOsPrintf("mvPp2WinInit failed: winNum=%d (%d, %d)\n",
					   winNum, winPrioIndex, ethAddrDecPrioTab[winPrioIndex]);
				return MV_ERROR;
			}
			winNum++;
		}
		winPrioIndex++;
	}

	return MV_OK;
}
/***********************************************************
 * mv_eth_bm_init --                                       *
 *   initialize BM pool to bu used by all ports            *
 ***********************************************************/
static int mv_eth_bm_init(MV_VOID)
{
	MV_STATUS status;
	unsigned char *pool_addr, *pool_addr_phys;

	mvBmInit();

	pool_addr = mvOsIoUncachedMalloc(NULL,
		(sizeof(MV_U32) * EGIGA_BM_SIZE) + MV_BM_POOL_PTR_ALIGN, (MV_ULONG *)&pool_addr_phys, NULL);
	if (!pool_addr) {
		printf("Can't alloc %d bytes for pool #%d\n", sizeof(MV_U32) * EGIGA_BM_SIZE, EGIGA_BM_POOL);
		return -1;
	}
	if (MV_IS_NOT_ALIGN((MV_ULONG)pool_addr_phys, MV_BM_POOL_PTR_ALIGN))
		pool_addr_phys = (unsigned char *)MV_ALIGN_UP((MV_ULONG)pool_addr_phys, MV_BM_POOL_PTR_ALIGN);

	status = mvBmPoolInit(EGIGA_BM_POOL, (MV_U32 *)pool_addr, (MV_ULONG)pool_addr_phys, EGIGA_BM_SIZE);
	if (status != MV_OK) {
		printf("Can't init #%d BM pool. status=%d\n", EGIGA_BM_POOL, status);
		return -1;
	}

#ifdef CONFIG_MV_ETH_PP2_1
	/* Disable BM priority */
	mvPp2WrReg(MV_BM_PRIO_CTRL_REG, 0);
#endif

	mvBmPoolControl(EGIGA_BM_POOL, MV_START);
	mvPp2BmPoolBufSizeSet(EGIGA_BM_POOL, RX_BUFFER_SIZE);

	return 0;
}
void        mvPp2WolRegs(void)
{
	int    i, reg;

	mvOsPrintf("\n[WoL registers]\n");

	mvPp2PrintReg(MV_PP2_WOL_MODE_REG,       "MV_PP2_WOL_MODE_REG");
	mvPp2PrintReg(MV_PP2_WOL_MAC_HIGH_REG,   "MV_PP2_WOL_MAC_HIGH_REG");
	mvPp2PrintReg(MV_PP2_WOL_MAC_LOW_REG,    "MV_PP2_WOL_MAC_LOW_REG");
	mvPp2PrintReg(MV_PP2_WOL_ARP_IP0_REG,    "MV_PP2_WOL_ARP_IP0_REG");
	mvPp2PrintReg(MV_PP2_WOL_ARP_IP1_REG,    "MV_PP2_WOL_ARP_IP1_REG");
	mvPp2PrintReg(MV_PP2_WOL_WAKEUP_EN_REG,  "MV_PP2_WOL_WAKEUP_EN_REG");
	mvPp2PrintReg(MV_PP2_WOL_INTR_CAUSE_REG, "MV_PP2_WOL_INTR_CAUSE_REG");
	mvPp2PrintReg(MV_PP2_WOL_INTR_MASK_REG,  "MV_PP2_WOL_INTR_MASK_REG");
	mvPp2PrintReg(MV_PP2_WOL_PTRN_SIZE_REG,  "MV_PP2_WOL_PTRN_SIZE_REG");


	for (i = 0; i < MV_PP2_WOL_PTRN_NUM; i++) {
		mvOsPrintf("\nWoL Wakeup Frame pattern #%d\n", i);

		mvPp2WrReg(MV_PP2_WOL_PTRN_IDX_REG, i);
		for (reg = 0; reg < MV_PP2_WOL_PTRN_REGS; reg++) {
			mvPp2RegPrintNonZero2(MV_PP2_WOL_PTRN_DATA_REG(reg), "MV_PP2_WOL_PTRN_DATA_REG", reg);
			mvPp2RegPrintNonZero2(MV_PP2_WOL_PTRN_MASK_REG(reg), "MV_PP2_WOL_PTRN_MASK_REG", reg);
		}
	}
}
void mvEthPortDisable(int port)
{
	MV_U32 regVal;

	regVal = MV_REG_READ(ETH_GMAC_CTRL_0_REG(port));
	regVal &= ~(ETH_GMAC_PORT_EN_MASK);
	mvPp2WrReg(ETH_GMAC_CTRL_0_REG(port), regVal);
}
/*******************************************************************************
* mvEthSpeedDuplexSet -
*
* DESCRIPTION:
*       Sets port speed to Auto Negotiation / 1000 / 100 / 10 Mbps.
*	Sets port duplex to Auto Negotiation / Full / Half Duplex.
*
* INPUT:
* 	int portNo - port number
* 	MV_ETH_PORT_SPEED speed - port speed
*	MV_ETH_PORT_DUPLEX duplex - port duplex mode
*
* RETURN:
*******************************************************************************/
MV_STATUS mvEthSpeedDuplexSet(int portNo, MV_ETH_PORT_SPEED speed, MV_ETH_PORT_DUPLEX duplex)
{
	MV_U32 regVal;

	/* Check validity */
	if ((speed == MV_ETH_SPEED_1000) && (duplex == MV_ETH_DUPLEX_HALF))
		return MV_BAD_PARAM;

	regVal = MV_REG_READ(ETH_GMAC_AN_CTRL_REG(portNo));

	switch (speed) {
	case MV_ETH_SPEED_AN:
		regVal |= ETH_ENABLE_SPEED_AUTO_NEG_MASK;
		/* the other bits don't matter in this case */
		break;
	case MV_ETH_SPEED_1000:
		regVal &= ~ETH_ENABLE_SPEED_AUTO_NEG_MASK;
		regVal |= ETH_SET_GMII_SPEED_1000_MASK;
		regVal &= ~ETH_SET_MII_SPEED_100_MASK;
		/* the 100/10 bit doesn't matter in this case */
		break;
	case MV_ETH_SPEED_100:
		regVal &= ~ETH_ENABLE_SPEED_AUTO_NEG_MASK;
		regVal &= ~ETH_SET_GMII_SPEED_1000_MASK;
		regVal |= ETH_SET_MII_SPEED_100_MASK;
		break;
	case MV_ETH_SPEED_10:
		regVal &= ~ETH_ENABLE_SPEED_AUTO_NEG_MASK;
		regVal &= ~ETH_SET_GMII_SPEED_1000_MASK;
		regVal &= ~ETH_SET_MII_SPEED_100_MASK;
		break;
	default:
		mvOsPrintf("Unexpected Speed value %d\n", speed);
		return MV_BAD_PARAM;
	}

	switch (duplex) {
	case MV_ETH_DUPLEX_AN:
		regVal  |= ETH_ENABLE_DUPLEX_AUTO_NEG_MASK;
		/* the other bits don't matter in this case */
		break;
	case MV_ETH_DUPLEX_HALF:
		regVal &= ~ETH_ENABLE_DUPLEX_AUTO_NEG_MASK;
		regVal &= ~ETH_SET_FULL_DUPLEX_MASK;
		break;
	case MV_ETH_DUPLEX_FULL:
		regVal &= ~ETH_ENABLE_DUPLEX_AUTO_NEG_MASK;
		regVal |= ETH_SET_FULL_DUPLEX_MASK;
		break;
	default:
		mvOsPrintf("Unexpected Duplex value %d\n", duplex);
		return MV_BAD_PARAM;
	}

	mvPp2WrReg(ETH_GMAC_AN_CTRL_REG(portNo), regVal);
	return MV_OK;
}
MV_STATUS mvPp2WolSleep(int port)
{
	MV_U32 regVal;

	if (mvPp2PortCheck(port))
		return MV_BAD_PARAM;

	/* Clear cause register and unmask enabled WoL events */
	mvPp2WrReg(MV_PP2_WOL_INTR_CAUSE_REG, 0);
	regVal = mvPp2RdReg(MV_PP2_WOL_WAKEUP_EN_REG);
	mvPp2WrReg(MV_PP2_WOL_INTR_MASK_REG, regVal);

	regVal = mvPp2RdReg(MV_PP2_WOL_MODE_REG);
	if (regVal & MV_PP2_WOL_IS_SLEEP_MASK) {
		mvOsPrintf("WoL is already activated on port #%d\n",
			(regVal >> MV_PP2_WOL_SLEEP_PORT_OFFS) & MV_PP2_WOL_SLEEP_PORT_MAX);
		return MV_BUSY;
	}
MV_STATUS   mvPp2PlcrHwTokenConfig(int plcr, int unit, int type)
{
	MV_U32 regVal;

	mvPp2WrReg(MV_PP2_PLCR_TABLE_INDEX_REG, plcr);
	regVal = mvPp2RdReg(MV_PP2_PLCR_TOKEN_CFG_REG);
	if (unit)
		regVal |= MV_PP2_PLCR_TOKEN_UNIT_MASK;
	else
		regVal &= ~MV_PP2_PLCR_TOKEN_UNIT_MASK;

	regVal &= ~MV_PP2_PLCR_TOKEN_TYPE_ALL_MASK;
	regVal |= MV_PP2_PLCR_TOKEN_TYPE_MASK(type);

	mvPp2WrReg(MV_PP2_PLCR_TOKEN_CFG_REG, regVal);

	return MV_OK;
}
void        mvPp2PlcrHwRegs(void)
{
	int    i;
	MV_U32 regVal;

	mvOsPrintf("\n[PLCR registers: %d policers]\n", MV_PP2_PLCR_NUM);

	mvEthRegPrint(MV_PP2_PLCR_ENABLE_REG,      "MV_PP2_PLCR_ENABLE_REG");
	mvEthRegPrint(MV_PP2_PLCR_BASE_PERIOD_REG, "MV_PP2_PLCR_BASE_PERIOD_REG");
	mvEthRegPrint(MV_PP2_PLCR_MIN_PKT_LEN_REG,   "MV_PP2_PLCR_MIN_PKT_LEN_REG");
	mvEthRegPrint(MV_PP2_PLCR_EDROP_EN_REG,      "MV_PP2_PLCR_EDROP_EN_REG");

	for (i = 0; i < MV_PP2_PLCR_NUM; i++) {
		mvOsPrintf("\n[Policer %d registers]\n", i);

		mvPp2WrReg(MV_PP2_PLCR_TABLE_INDEX_REG, i);
		mvEthRegPrint(MV_PP2_PLCR_COMMIT_TOKENS_REG, "MV_PP2_PLCR_COMMIT_TOKENS_REG");
		mvEthRegPrint(MV_PP2_PLCR_EXCESS_TOKENS_REG, "MV_PP2_PLCR_EXCESS_TOKENS_REG");
		mvEthRegPrint(MV_PP2_PLCR_BUCKET_SIZE_REG,   "MV_PP2_PLCR_BUCKET_SIZE_REG");
		mvEthRegPrint(MV_PP2_PLCR_TOKEN_CFG_REG,     "MV_PP2_PLCR_TOKEN_CFG_REG");
	}

	mvOsPrintf("\nEarly Drop Thresholds for SW and HW forwarding\n");
	for (i = 0; i < MV_PP2_PLCR_EDROP_THRESH_NUM; i += 2) {
		mvEthRegPrint2(MV_PP2_PLCR_EDROP_CPU_TR_REG(i),   "MV_PP2_PLCR_EDROP_CPU_TR_REG", i);
		mvEthRegPrint2(MV_PP2_PLCR_EDROP_HWF_TR_REG(i),   "MV_PP2_PLCR_EDROP_HWF_TR_REG", i);
	}
	mvOsPrintf("\nPer RXQ: Non zero early drop thresholds\n");
	for (i = 0; i < MV_ETH_RXQ_TOTAL_NUM; i++) {
		mvPp2WrReg(MV_PP2_PLCR_EDROP_RXQ_REG, i);
		regVal = mvPp2RdReg(MV_PP2_PLCR_EDROP_RXQ_TR_REG);
		if (regVal != 0)
			mvOsPrintf("  %-32s: 0x%x = 0x%08x\n", "MV_PP2_PLCR_EDROP_RXQ_TR_REG", MV_PP2_PLCR_EDROP_RXQ_TR_REG, regVal);
	}
	mvOsPrintf("\nPer TXQ: Non zero Early Drop Thresholds\n");
	for (i = 0; i < MV_PP2_TXQ_TOTAL_NUM; i++) {
		mvPp2WrReg(MV_PP2_PLCR_EDROP_TXQ_REG, i);
		regVal = mvPp2RdReg(MV_PP2_PLCR_EDROP_TXQ_TR_REG);
		if (regVal != 0)
			mvOsPrintf("  %-32s: 0x%x = 0x%08x\n", "MV_PP2_PLCR_EDROP_TXQ_TR_REG", MV_PP2_PLCR_EDROP_TXQ_TR_REG, regVal);
	}
}
MV_STATUS   mvPp2PlcrHwBasePeriodSet(int period)
{
	MV_U32 regVal;

	regVal = mvPp2RdReg(MV_PP2_PLCR_BASE_PERIOD_REG);
	regVal &= ~MV_PP2_PLCR_BASE_PERIOD_ALL_MASK;
	regVal |= MV_PP2_PLCR_BASE_PERIOD_MASK(period);
	mvPp2WrReg(MV_PP2_PLCR_BASE_PERIOD_REG, regVal);

	return MV_OK;
}
MV_STATUS   mvPp2PlcrHwMinPktLen(int bytes)
{
	MV_U32 regVal;

	regVal = mvPp2RdReg(MV_PP2_PLCR_MIN_PKT_LEN_REG);
	regVal &= ~MV_PP2_PLCR_MIN_PKT_LEN_ALL_MASK;
	regVal |= MV_PP2_PLCR_MIN_PKT_LEN_MASK(bytes);
	mvPp2WrReg(MV_PP2_PLCR_MIN_PKT_LEN_REG, regVal);

	return MV_OK;
}
MV_STATUS   mvPp2PlcrHwHwfThreshSet(int idx, int threshold)
{
	MV_U32 regVal;

	regVal = mvPp2RdReg(MV_PP2_PLCR_EDROP_HWF_TR_REG(idx));
	regVal &= ~MV_PP2_PLCR_EDROP_TR_ALL_MASK(idx);
	regVal |= MV_PP2_PLCR_EDROP_TR_MASK(idx, threshold);
	mvPp2WrReg(MV_PP2_PLCR_EDROP_HWF_TR_REG(idx), regVal);

	return MV_OK;
}
static void mvEthPortSgmiiSet(int port, int enable)
{
	MV_U32 regVal;

	regVal = MV_REG_READ(ETH_GMAC_CTRL_2_REG(port));
	if (enable)
		regVal |= ETH_GMAC_PCS_ENABLE_MASK;
	else
		regVal &= ~ETH_GMAC_PCS_ENABLE_MASK;

	mvPp2WrReg(ETH_GMAC_CTRL_2_REG(port), regVal);
}
void mvEthPhyAddrSet(int port, int phyAddr)
{
	unsigned int regData;

	regData = MV_REG_READ(ETH_PHY_ADDR_REG);

	regData &= ~ETH_PHY_ADDR_MASK(port);
	regData |= (phyAddr << ETH_PHY_ADDR_OFFS(port));

	mvPp2WrReg(ETH_PHY_ADDR_REG, regData);

	return;
}
MV_STATUS   mvPp2PlcrHwBaseRateGenEnable(int enable)
{
	MV_U32 regVal;

	regVal = mvPp2RdReg(MV_PP2_PLCR_BASE_PERIOD_REG);
	if (enable)
		regVal |= MV_PP2_PLCR_ADD_TOKENS_EN_MASK;
	else
		regVal &= ~MV_PP2_PLCR_ADD_TOKENS_EN_MASK;

	mvPp2WrReg(MV_PP2_PLCR_BASE_PERIOD_REG, regVal);

	return MV_OK;
}
MV_STATUS   mvPp2PlcrHwEnable(int plcr, int enable)
{
	MV_U32 regVal;

	regVal = mvPp2RdReg(MV_PP2_PLCR_ENABLE_REG);
	if (enable)
		regVal |= MV_PP2_PLCR_EN_MASK(plcr);
	else
		regVal &= ~MV_PP2_PLCR_EN_MASK(plcr);

	mvPp2WrReg(MV_PP2_PLCR_ENABLE_REG, regVal);

	return MV_OK;
}
void mvEthPortPowerUp(int port, MV_BOOL isSgmii, MV_BOOL isRgmii)
{
	MV_U32 regVal;

	mvEthPortSgmiiSet(port, isSgmii);
	mvEthPortRgmiiSet(port, isRgmii);

	/* Cancel Port Reset */
	regVal = MV_REG_READ(ETH_GMAC_CTRL_2_REG(port));
	regVal &= (~ETH_GMAC_PORT_RESET_MASK);
	mvPp2WrReg(ETH_GMAC_CTRL_2_REG(port), regVal);
	while ((MV_REG_READ(ETH_GMAC_CTRL_2_REG(port)) & ETH_GMAC_PORT_RESET_MASK) != 0)
		continue;
}
MV_STATUS   mvPp2PlcrHwEarlyDropSet(int enable)
{
	MV_U32 regVal;

	regVal = mvPp2RdReg(MV_PP2_PLCR_EDROP_EN_REG);
	if (enable)
		regVal |= MV_PP2_PLCR_EDROP_EN_MASK;
	else
		regVal &= ~MV_PP2_PLCR_EDROP_EN_MASK;

	mvPp2WrReg(MV_PP2_PLCR_EDROP_EN_REG, regVal);

	return MV_OK;
}
/*******************************************************************************
* mvNetaMaxRxSizeSet -
*
* DESCRIPTION:
*       Change maximum receive size of the port. This configuration will take place
*       imidiately.
*
* INPUT:
*
* RETURN:
*******************************************************************************/
void mvEthMaxRxSizeSet(int port, int maxRxSize)
{
    MV_U32		regVal;

	if (!MV_PON_PORT(port)) {

		regVal =  MV_REG_READ(ETH_GMAC_CTRL_0_REG(port));
		regVal &= ~ETH_GMAC_MAX_RX_SIZE_MASK;
		regVal |= (((maxRxSize - MV_ETH_MH_SIZE) / 2) << ETH_GMAC_MAX_RX_SIZE_OFFS);
		mvPp2WrReg(ETH_GMAC_CTRL_0_REG(port), regVal);
/*
		mvOsPrintf("%s: port=%d, maxRxSize=%d, regAddr=0x%x, regVal=0x%x\n",
			__func__, port, maxRxSize, ETH_GMAC_CTRL_0_REG(port), regVal);
*/
	}
}
void mvEthPortLbSet(int port, int isGmii, int isPcsEn)
{
	MV_U32 regVal;

	regVal = MV_REG_READ(ETH_GMAC_CTRL_1_REG(port));

	if (isGmii)
		regVal |= ETH_GMAC_GMII_LB_EN_MASK;
	else
		regVal &= ~ETH_GMAC_GMII_LB_EN_MASK;

	if (isPcsEn)
		regVal |= ETH_GMAC_PCS_LB_EN_MASK;
	else
		regVal &= ~ETH_GMAC_PCS_LB_EN_MASK;

	mvPp2WrReg(ETH_GMAC_CTRL_1_REG(port), regVal);
}
/*******************************************************************************
* mvEthFlowCtrlSet - Set Flow Control of the port.
*
* DESCRIPTION:
*       This function configures the port's Flow Control properties.
*
* INPUT:
*       int				port		- Port number
*       MV_ETH_PORT_FC  flowControl - Flow control of the port.
*
* RETURN:   MV_STATUS
*       MV_OK           - Success
*       MV_OUT_OF_RANGE - Failed. Port is out of valid range
*       MV_BAD_VALUE    - Value flowControl parameters is not valid
*
*******************************************************************************/
MV_STATUS mvEthFlowCtrlSet(int port, MV_ETH_PORT_FC flowControl)
{
	MV_U32 regVal;

	regVal = MV_REG_READ(ETH_GMAC_AN_CTRL_REG(port));

	switch (flowControl) {
	case MV_ETH_FC_AN_NO:
		regVal |= ETH_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
		regVal &= ~ETH_FLOW_CONTROL_ADVERTISE_MASK;
		regVal &= ~ETH_FLOW_CONTROL_ASYMETRIC_MASK;
		break;

	case MV_ETH_FC_AN_SYM:
		regVal |= ETH_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
		regVal |= ETH_FLOW_CONTROL_ADVERTISE_MASK;
		regVal &= ~ETH_FLOW_CONTROL_ASYMETRIC_MASK;
		break;

	case MV_ETH_FC_AN_ASYM:
		regVal |= ETH_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
		regVal |= ETH_FLOW_CONTROL_ADVERTISE_MASK;
		regVal |= ETH_FLOW_CONTROL_ASYMETRIC_MASK;
		break;

	case MV_ETH_FC_DISABLE:
		regVal &= ~ETH_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
		regVal &= ~ETH_SET_FLOW_CONTROL_MASK;
		break;

	case MV_ETH_FC_ENABLE:
		regVal &= ~ETH_ENABLE_FLOW_CONTROL_AUTO_NEG_MASK;
		regVal |= ETH_SET_FLOW_CONTROL_MASK;
		break;

	default:
		mvOsPrintf("ethDrv: Unexpected FlowControl value %d\n", flowControl);
		return MV_BAD_VALUE;
	}

	mvPp2WrReg(ETH_GMAC_AN_CTRL_REG(port), regVal);

	return MV_OK;
}
/*******************************************************************************
* mvEthForceLinkModeSet -
*
* DESCRIPTION:
*       Sets "Force Link Pass" and "Do Not Force Link Fail" bits.
* 	Note: This function should only be called when the port is disabled.
*
* INPUT:
* 	int		portNo			- port number
* 	MV_BOOL force_link_pass	- Force Link Pass
* 	MV_BOOL force_link_fail - Force Link Failure
*		0, 0 - normal state: detect link via PHY and connector
*		1, 1 - prohibited state.
*
* RETURN:
*******************************************************************************/
MV_STATUS mvEthForceLinkModeSet(int portNo, MV_BOOL force_link_up, MV_BOOL force_link_down)
{
	MV_U32	regVal;

	/* Can't force link pass and link fail at the same time */
	if ((force_link_up) && (force_link_down))
		return MV_BAD_PARAM;

	regVal = MV_REG_READ(ETH_GMAC_AN_CTRL_REG(portNo));

	if (force_link_up)
		regVal |= ETH_FORCE_LINK_PASS_MASK;
	else
		regVal &= ~ETH_FORCE_LINK_PASS_MASK;

	if (force_link_down)
		regVal |= ETH_FORCE_LINK_FAIL_MASK;
	else
		regVal &= ~ETH_FORCE_LINK_FAIL_MASK;

	mvPp2WrReg(ETH_GMAC_AN_CTRL_REG(portNo), regVal);

    return MV_OK;
}
/*******************************************************************************
* mvPp2WinWrite
*
* DESCRIPTION:
*	This function writes the address decoding registers according to the
*	given window configuration.
*
* INPUT:
*	unit	    - The Ethernet unit number to configure.
*       winNum	    - ETH target address decode window number.
*       pAddrDecWin - ETH target window data structure.
*
* OUTPUT:
*       None.
*
* RETURN:
*       MV_OK on success,
*	MV_BAD_PARAM if winNum is invalid.
*	MV_ERROR otherwise.
*
*******************************************************************************/
MV_STATUS mvPp2WinWrite(MV_U32 dummy/*backward compability*/, MV_U32 winNum, MV_UNIT_WIN_INFO *pAddrDecWin)
{
	MV_U32 size, alignment;
	MV_U32 baseReg, sizeReg;

	/* Parameter checking   */
	if (winNum >= ETH_MAX_DECODE_WIN) {
		mvOsPrintf("mvPp2WinSet: ERR. Invalid win num %d\n", winNum);
		return MV_BAD_PARAM;
	}

	/* Check if the requested window overlapps with current windows     */
	if (MV_TRUE == ethWinOverlapDetect(winNum, &pAddrDecWin->addrWin)) {
		mvOsPrintf("mvPp2WinWrite: ERR. Window %d overlap\n", winNum);
		return MV_ERROR;
	}

	/* check if address is aligned to the size */
	if (MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size)) {
		mvOsPrintf("mvPp2WinSet: Error setting Ethernet window %d.\n"
			   "Address 0x%08x is unaligned to size 0x%x.\n",
			   winNum, pAddrDecWin->addrWin.baseLow, (MV_U32)pAddrDecWin->addrWin.size);
		return MV_ERROR;
	}

	size = pAddrDecWin->addrWin.size;
	if (!MV_IS_POWER_OF_2(size)) {
		mvOsPrintf("mvPp2WinWrite: Error setting AUDIO window %d. "
			   "Window size is not a power to 2.", winNum);
		return MV_BAD_PARAM;
	}

	baseReg = (pAddrDecWin->addrWin.baseLow & ETH_WIN_BASE_MASK);
	sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(winNum));

	/* set size */
	alignment = 1 << ETH_WIN_SIZE_OFFS;
	sizeReg &= ~ETH_WIN_SIZE_MASK;
	sizeReg |= (((size / alignment) - 1) << ETH_WIN_SIZE_OFFS);

	/* set attributes */
	baseReg &= ~ETH_WIN_ATTR_MASK;
	baseReg |= pAddrDecWin->attrib << ETH_WIN_ATTR_OFFS;

	/* set target ID */
	baseReg &= ~ETH_WIN_TARGET_MASK;
	baseReg |= pAddrDecWin->targetId << ETH_WIN_TARGET_OFFS;

	/* for the safe side we disable the window before writing the new
	   values */
	mvPp2WinEnable(0, winNum, MV_FALSE);
	mvPp2WrReg(ETH_WIN_BASE_REG(winNum), baseReg);

	/* Write to address decode Size Register                            */
	mvPp2WrReg(ETH_WIN_SIZE_REG(winNum), sizeReg);

	/* Enable address decode target window                              */
	if (pAddrDecWin->enable == MV_TRUE)
		mvPp2WinEnable(0, winNum, MV_TRUE);

	return MV_OK;
}