SmartSwitchESP32/src/rtl8370/rtl8370_asicdrv_phy.c

147 lines
4.5 KiB
C

/*
* Copyright (C) 2009 Realtek Semiconductor Corp.
* All Rights Reserved.
*
* This program is the proprietary software of Realtek Semiconductor
* Corporation and/or its licensors, and only be used, duplicated,
* modified or distributed under the authorized license from Realtek.
*
* ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
*
* $Revision: 6927 $
* $Date: 2009-11-10 19:12:30 +0800 (Tue, 10 Nov 2009) $
*
* Purpose : RTL8370 switch high-level API for RTL8367B
* Feature :
*
*/
#include "rtl8370_asicdrv.h"
#include "rtl8370_asicdrv_phy.h"
/*
@func ret_t | rtl8370_setAsicPHYReg | Set PHY registers .
@parm uint32 | phyNo | PHY number (0~7).
@parm uint32 | phyAddr | PHY address (0~31).
@parm uint32 | data | Writing data.
@rvalue RT_ERR_OK |
@rvalue RT_ERR_FAILED | invalid parameter
@rvalue RT_ERR_PHY_REG_ID | invalid PHY address
@rvalue RT_ERR_PORT_ID | invalid port id.
@rvalue RT_ERR_BUSYWAIT_TIMEOUT | PHY access busy
@comm
The API can set internal PHY register 0~31. There are 8 internal PHYs in switch and each PHY can be
accessed by software.
*/
ret_t rtl8370_setAsicPHYReg(int phyNo, int phyAddr, uint16 data)
{
ret_t retVal;
uint16 regData;
uint16 busyFlag;
if (phyNo > RTL8370_PHY_INTERNALNOMAX)
return RT_ERR_PORT_ID;
if (phyAddr > RTL8370_PHY_REGNOMAX)
return RT_ERR_PHY_REG_ID;
/*
word address a[15] a[14] a[13] a[12] a[11] a[10] a[9] a[8] a[7] a[6] a[5] a[4] a[3] a[2] a[1] a[0]
phy0 ~ phy7 [ 3'd1 ] [ 0 0 0 0 0 ] [ PHY No. ] [ reg adr[4:0] ]
*/
/*Check internal phy access busy or not*/
retVal = rtl8370_getAsicRegBit(RTL8370_REG_INDRECT_ACCESS_STATUS, RTL8370_PHY_BUSY_OFFSET, &busyFlag);
if (retVal != RT_ERR_OK)
return retVal;
if (busyFlag)
return RT_ERR_BUSYWAIT_TIMEOUT;
/*prepare access data*/
retVal = rtl8370_setAsicReg(RTL8370_REG_INDRECT_ACCESS_WRITE_DATA, data);
if (retVal != RT_ERR_OK)
return retVal;
/*prepare access address*/
regData = RTL8370_PHY_BASE | (phyNo << RTL8370_PHY_OFFSET) | phyAddr;
retVal = rtl8370_setAsicReg(RTL8370_REG_INDRECT_ACCESS_ADDRESS, regData);
if (retVal != RT_ERR_OK)
return retVal;
/*Set WRITE Command*/
return rtl8370_setAsicReg(RTL8370_REG_INDRECT_ACCESS_CRTL, RTL8370_CMD_MASK | RTL8370_RW_MASK);
}
/*
@func ret_t | rtl8370_getAsicPHYReg | Set PHY registers.
@parm uint32 | phyNo | PHY number (0~7).
@parm uint32 | phyAddr | PHY address (0~31).
@parm uint32* | data | Read data.
@rvalue RT_ERR_OK |
@rvalue RT_ERR_FAILED | invalid parameter
@rvalue RT_ERR_PHY_REG_ID | invalid PHY address
@rvalue RT_ERR_PORT_ID | iinvalid port id
@rvalue RT_ERR_BUSYWAIT_TIMEOUT | PHY access busy
@comm
The API can get internal PHY register 0~31. There are 8 internal PHYs in switch and each PHY can be
accessed by software.
*/
ret_t rtl8370_getAsicPHYReg(int phyNo, int phyAddr, uint16 *data)
{
ret_t retVal;
uint16 regData;
uint16 busyFlag, checkCounter;
if (phyNo > RTL8370_PHY_INTERNALNOMAX)
return RT_ERR_PORT_ID;
if (phyAddr > RTL8370_PHY_REGNOMAX)
return RT_ERR_PHY_REG_ID;
/*Check internal phy access busy or not*/
retVal = rtl8370_getAsicRegBit(RTL8370_REG_INDRECT_ACCESS_STATUS, RTL8370_PHY_BUSY_OFFSET, &busyFlag);
if (retVal != RT_ERR_OK)
return retVal;
if (busyFlag)
return RT_ERR_BUSYWAIT_TIMEOUT;
/*prepare access address*/
regData = RTL8370_PHY_BASE | (phyNo << RTL8370_PHY_OFFSET) | phyAddr;
retVal = rtl8370_setAsicReg(RTL8370_REG_INDRECT_ACCESS_ADDRESS, regData);
if (retVal != RT_ERR_OK)
return retVal;
/*Set READ Command*/
retVal = rtl8370_setAsicReg(RTL8370_REG_INDRECT_ACCESS_CRTL, RTL8370_CMD_MASK);
if (retVal != RT_ERR_OK)
return retVal;
checkCounter = 5;
while (checkCounter)
{
retVal = rtl8370_getAsicRegBit(RTL8370_REG_INDRECT_ACCESS_STATUS, RTL8370_PHY_BUSY_OFFSET, &busyFlag);
if (retVal != RT_ERR_OK)
{
checkCounter--;
if (0 == checkCounter)
return retVal;
}
else
{
checkCounter = 0;
}
}
/*get PHY register*/
retVal = rtl8370_getAsicReg(RTL8370_REG_INDRECT_ACCESS_READ_DATA, &regData);
if (retVal != RT_ERR_OK)
return retVal;
*data = regData;
return RT_ERR_OK;
}