diff options
Diffstat (limited to 'arch/arm/cpu/ixp/npe/IxEthAccMii.c')
-rw-r--r-- | arch/arm/cpu/ixp/npe/IxEthAccMii.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/arch/arm/cpu/ixp/npe/IxEthAccMii.c b/arch/arm/cpu/ixp/npe/IxEthAccMii.c new file mode 100644 index 0000000000..d282aa6725 --- /dev/null +++ b/arch/arm/cpu/ixp/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; +} + |