mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-17 18:28:55 +00:00
411 lines
10 KiB
C
411 lines
10 KiB
C
|
/**
|
||
|
* @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;
|
||
|
}
|
||
|
|