diff options
Diffstat (limited to 'drivers/net/npe/IxEthAccMii.c')
| -rw-r--r-- | drivers/net/npe/IxEthAccMii.c | 410 | 
1 files changed, 410 insertions, 0 deletions
| diff --git a/drivers/net/npe/IxEthAccMii.c b/drivers/net/npe/IxEthAccMii.c new file mode 100644 index 000000000..d282aa672 --- /dev/null +++ b/drivers/net/npe/IxEthAccMii.c @@ -0,0 +1,410 @@ +/** + * @file IxEthAccMii.c + * + * @author Intel Corporation + * @date  + * + * @brief  MII control functions + * + * Design Notes: + * + * IXP400 SW Release version 2.0 + *  + * -- Copyright Notice -- + *  + * @par + * Copyright 2001-2005, Intel Corporation. + * All rights reserved. + *  + * @par + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Intel Corporation nor the names of its contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + *  + * @par + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + *  + * @par + * -- End of Copyright Notice -- + */ + +#include "IxOsal.h" +#include "IxEthAcc.h" +#include "IxEthAcc_p.h" +#include "IxEthAccMac_p.h" +#include "IxEthAccMii_p.h" + + +PRIVATE UINT32 miiBaseAddressVirt; +PRIVATE IxOsalMutex miiAccessLock; + +PUBLIC UINT32 ixEthAccMiiRetryCount    = IX_ETH_ACC_MII_TIMEOUT_10TH_SECS; +PUBLIC UINT32 ixEthAccMiiAccessTimeout = IX_ETH_ACC_MII_10TH_SEC_IN_MILLIS; + +/* ----------------------------------- + * private function prototypes + */ +PRIVATE void +ixEthAccMdioCmdWrite(UINT32 mdioCommand); + +PRIVATE void +ixEthAccMdioCmdRead(UINT32 *data); + +PRIVATE void +ixEthAccMdioStatusRead(UINT32 *data); + + +PRIVATE void +ixEthAccMdioCmdWrite(UINT32 mdioCommand) +{ +    REG_WRITE(miiBaseAddressVirt, +	      IX_ETH_ACC_MAC_MDIO_CMD_1, +	      mdioCommand & 0xff); + +    REG_WRITE(miiBaseAddressVirt, +	      IX_ETH_ACC_MAC_MDIO_CMD_2, +	      (mdioCommand >> 8) & 0xff); + +    REG_WRITE(miiBaseAddressVirt, +	      IX_ETH_ACC_MAC_MDIO_CMD_3, +	      (mdioCommand >> 16) & 0xff); + +    REG_WRITE(miiBaseAddressVirt, +	      IX_ETH_ACC_MAC_MDIO_CMD_4, +	      (mdioCommand >> 24) & 0xff); +} + +PRIVATE void +ixEthAccMdioCmdRead(UINT32 *data) +{ +    UINT32 regval; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_CMD_1, +	     regval); + +    *data = regval & 0xff; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_CMD_2, +	     regval); + +    *data |= (regval & 0xff) << 8; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_CMD_3, +	     regval); + +    *data |= (regval & 0xff) << 16; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_CMD_4, +	     regval); + +    *data |= (regval & 0xff) << 24; + +} + +PRIVATE void +ixEthAccMdioStatusRead(UINT32 *data) +{ +    UINT32 regval; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_STS_1, +	     regval); + +    *data = regval & 0xff; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_STS_2, +	     regval); + +    *data |= (regval & 0xff) << 8; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_STS_3, +	     regval); + +    *data |= (regval & 0xff) << 16; + +    REG_READ(miiBaseAddressVirt, +	     IX_ETH_ACC_MAC_MDIO_STS_4, +	     regval); +     +    *data |= (regval & 0xff) << 24; +     +} + + +/******************************************************************** + * ixEthAccMiiInit + */ +IxEthAccStatus +ixEthAccMiiInit() +{ +    if(ixOsalMutexInit(&miiAccessLock)!= IX_SUCCESS) +    { +	return IX_ETH_ACC_FAIL; +    } + +    miiBaseAddressVirt = (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE, IX_OSAL_IXP400_ETHA_MAP_SIZE); +     +    if (miiBaseAddressVirt == 0) +    { +      ixOsalLog(IX_OSAL_LOG_LVL_FATAL,  +		IX_OSAL_LOG_DEV_STDOUT,  +		"EthAcc: Could not map MII I/O mapped memory\n",  +		0, 0, 0, 0, 0, 0); +       +      return IX_ETH_ACC_FAIL; +    } +     +    return IX_ETH_ACC_SUCCESS; +} + +void +ixEthAccMiiUnload(void) +{ +    IX_OSAL_MEM_UNMAP(miiBaseAddressVirt); +   +    miiBaseAddressVirt = 0; +} + +PUBLIC IxEthAccStatus +ixEthAccMiiAccessTimeoutSet(UINT32 timeout, UINT32 retryCount) +{ +    if (retryCount < 1) return IX_ETH_ACC_FAIL; + +    ixEthAccMiiRetryCount    = retryCount; +    ixEthAccMiiAccessTimeout = timeout; + +    return IX_ETH_ACC_SUCCESS; +} + +/********************************************************************* + * ixEthAccMiiReadRtn - read a 16 bit value from a PHY + */ +IxEthAccStatus       +ixEthAccMiiReadRtn (UINT8 phyAddr,  +		    UINT8 phyReg,  +		    UINT16 *value) +{ +    UINT32 mdioCommand; +    UINT32 regval; +    UINT32 miiTimeout; + +    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) +    { +	return (IX_ETH_ACC_FAIL); +    } + +    if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR)  +	|| (phyReg >= IXP425_ETH_ACC_MII_MAX_REG)) +    { +	return (IX_ETH_ACC_FAIL); +    } + +    if (value == NULL) +    { +	return (IX_ETH_ACC_FAIL); +    } + +    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); +    mdioCommand = phyReg <<  IX_ETH_ACC_MII_REG_SHL  +	| phyAddr << IX_ETH_ACC_MII_ADDR_SHL; +    mdioCommand |= IX_ETH_ACC_MII_GO; + +    ixEthAccMdioCmdWrite(mdioCommand); +     +    miiTimeout = ixEthAccMiiRetryCount; + +    while(miiTimeout) +    { +	 +	ixEthAccMdioCmdRead(®val); +      +	if((regval & IX_ETH_ACC_MII_GO) == 0x0) +	{	     +	    break; +	} +	/* Sleep for a while */ +	ixOsalSleep(ixEthAccMiiAccessTimeout); +	miiTimeout--; +    } +     + +     +    if(miiTimeout == 0) +    {	 +	ixOsalMutexUnlock(&miiAccessLock); +	*value = 0xffff; +	return IX_ETH_ACC_FAIL; +    } +     +     +    ixEthAccMdioStatusRead(®val); +    if(regval & IX_ETH_ACC_MII_READ_FAIL) +    { +	ixOsalMutexUnlock(&miiAccessLock); +	*value = 0xffff; +	return IX_ETH_ACC_FAIL; +    } + +    *value = regval & 0xffff; +    ixOsalMutexUnlock(&miiAccessLock); +    return IX_ETH_ACC_SUCCESS; +     +} + + +/********************************************************************* + * ixEthAccMiiWriteRtn - write a 16 bit value to a PHY + */ +IxEthAccStatus +ixEthAccMiiWriteRtn (UINT8 phyAddr,  +		     UINT8 phyReg,  +		     UINT16 value) +{ +    UINT32 mdioCommand; +    UINT32 regval; +    UINT16 readVal; +    UINT32 miiTimeout; + +    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) +    { +	return (IX_ETH_ACC_FAIL); +    } + +    if ((phyAddr >= IXP425_ETH_ACC_MII_MAX_ADDR)  +	|| (phyReg >= IXP425_ETH_ACC_MII_MAX_REG)) +    { +	return (IX_ETH_ACC_FAIL); +    } +    +    /* ensure that a PHY is present at this address */ +    if(ixEthAccMiiReadRtn(phyAddr, +                          IX_ETH_ACC_MII_CTRL_REG, +                          &readVal) != IX_ETH_ACC_SUCCESS) +    { +        return (IX_ETH_ACC_FAIL); +    } + +    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); +    mdioCommand = phyReg << IX_ETH_ACC_MII_REG_SHL +	| phyAddr << IX_ETH_ACC_MII_ADDR_SHL ; +    mdioCommand |= IX_ETH_ACC_MII_GO | IX_ETH_ACC_MII_WRITE | value; + +    ixEthAccMdioCmdWrite(mdioCommand); +     +    miiTimeout = ixEthAccMiiRetryCount; + +    while(miiTimeout) +    { +	 +	ixEthAccMdioCmdRead(®val); + +	/*The "GO" bit is reset to 0 when the write completes*/ +	if((regval & IX_ETH_ACC_MII_GO) == 0x0) +	{		     +	    break; +	} +	/* Sleep for a while */ +	ixOsalSleep(ixEthAccMiiAccessTimeout); +        miiTimeout--; +    } +     +    ixOsalMutexUnlock(&miiAccessLock); +    if(miiTimeout == 0) +    { +	return IX_ETH_ACC_FAIL; +    } +    return IX_ETH_ACC_SUCCESS; +} + + +/***************************************************************** + * + *  Phy query functions + * + */ +IxEthAccStatus +ixEthAccMiiStatsShow (UINT32 phyAddr) +{ +    UINT16 regval; +    printf("Regisers on PHY at address 0x%x\n", phyAddr); +    ixEthAccMiiReadRtn(phyAddr, IX_ETH_ACC_MII_CTRL_REG, ®val); +    printf("    Control Register                  :      0x%4.4x\n", regval); +    ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_STAT_REG, ®val); +    printf("    Status Register                   :      0x%4.4x\n", regval); +    ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_PHY_ID1_REG, ®val); +    printf("    PHY ID1 Register                  :      0x%4.4x\n", regval); +    ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_PHY_ID2_REG, ®val); +    printf("    PHY ID2 Register                  :      0x%4.4x\n", regval); +    ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_ADS_REG, ®val); +    printf("    Auto Neg ADS Register             :      0x%4.4x\n", regval); +    ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_PRTN_REG, ®val); +    printf("    Auto Neg Partner Ability Register :      0x%4.4x\n", regval); +    ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_EXP_REG, ®val); +    printf("    Auto Neg Expansion Register       :      0x%4.4x\n", regval); +    ixEthAccMiiReadRtn(phyAddr,  IX_ETH_ACC_MII_AN_NEXT_REG, ®val); +    printf("    Auto Neg Next Register            :      0x%4.4x\n", regval); + +    return IX_ETH_ACC_SUCCESS; +} + + +/***************************************************************** + * + *  Interface query functions + * + */ +IxEthAccStatus +ixEthAccMdioShow (void) +{ +    UINT32 regval; + +    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) +    { +	return (IX_ETH_ACC_FAIL); +    } + +    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); +    ixEthAccMdioCmdRead(®val); +    ixOsalMutexUnlock(&miiAccessLock); +     +    printf("MDIO command register\n"); +    printf("    Go bit      : 0x%x\n", (regval & BIT(31)) >> 31); +    printf("    MDIO Write  : 0x%x\n", (regval & BIT(26)) >> 26); +    printf("    PHY address : 0x%x\n", (regval >> 21) & 0x1f); +    printf("    Reg address : 0x%x\n", (regval >> 16) & 0x1f); +	 +    ixOsalMutexLock(&miiAccessLock, IX_OSAL_WAIT_FOREVER); +    ixEthAccMdioStatusRead(®val); +    ixOsalMutexUnlock(&miiAccessLock); + +    printf("MDIO status register\n"); +    printf("    Read OK     : 0x%x\n", (regval & BIT(31)) >> 31); +    printf("    Read Data   : 0x%x\n", (regval >> 16) & 0xff); + +    return IX_ETH_ACC_SUCCESS;    +} + |