diff options
Diffstat (limited to 'target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c')
-rw-r--r-- | target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c b/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c new file mode 100644 index 0000000000..fb4db113a9 --- /dev/null +++ b/target/linux/mediatek/files-5.10/drivers/net/phy/rtk/rtl8367c/rtl8367c_asicdrv_phy.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2013 Realtek Semiconductor Corp. + * All Rights Reserved. + * + * Unless you and Realtek execute a separate written software license + * agreement governing use of this software, this software is licensed + * to you under the terms of the GNU General Public License version 2, + * available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + * + * $Revision: 76306 $ + * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $ + * + * Purpose : RTL8367C switch high-level API for RTL8367C + * Feature : PHY related functions + * + */ +#include <rtl8367c_asicdrv_phy.h> + +#if defined(MDC_MDIO_OPERATION) +/* Function Name: + * rtl8367c_setAsicPHYOCPReg + * Description: + * Set PHY OCP registers + * Input: + * phyNo - Physical port number (0~7) + * ocpAddr - OCP address + * ocpData - Writing data + * Output: + * None + * Return: + * RT_ERR_OK - Success + * RT_ERR_SMI - SMI access error + * RT_ERR_PHY_REG_ID - invalid PHY address + * RT_ERR_PHY_ID - invalid PHY no + * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy + * Note: + * None + */ +ret_t rtl8367c_setAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 ocpData ) +{ + ret_t retVal; + rtk_uint32 regAddr; + rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1; + + /* OCP prefix */ + ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10); + if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK) + return retVal; + + /*prepare access address*/ + ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F); + ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F); + regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1; + if((retVal = rtl8367c_setAsicReg(regAddr, ocpData)) != RT_ERR_OK) + return retVal; + + return RT_ERR_OK; +} + +/* Function Name: + * rtl8367c_getAsicPHYOCPReg + * Description: + * Get PHY OCP registers + * Input: + * phyNo - Physical port number (0~7) + * ocpAddr - PHY address + * pRegData - read data + * Output: + * None + * Return: + * RT_ERR_OK - Success + * RT_ERR_SMI - SMI access error + * RT_ERR_PHY_REG_ID - invalid PHY address + * RT_ERR_PHY_ID - invalid PHY no + * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy + * Note: + * None + */ +ret_t rtl8367c_getAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 *pRegData ) +{ + ret_t retVal; + rtk_uint32 regAddr; + rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1; + /* OCP prefix */ + ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10); + if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK) + return retVal; + + /*prepare access address*/ + ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F); + ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F); + regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1; + if((retVal = rtl8367c_getAsicReg(regAddr, pRegData)) != RT_ERR_OK) + return retVal; + + return RT_ERR_OK; +} + +#else + +/* Function Name: + * rtl8367c_setAsicPHYOCPReg + * Description: + * Set PHY OCP registers + * Input: + * phyNo - Physical port number (0~7) + * ocpAddr - OCP address + * ocpData - Writing data + * Output: + * None + * Return: + * RT_ERR_OK - Success + * RT_ERR_SMI - SMI access error + * RT_ERR_PHY_REG_ID - invalid PHY address + * RT_ERR_PHY_ID - invalid PHY no + * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy + * Note: + * None + */ +ret_t rtl8367c_setAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 ocpData ) +{ + ret_t retVal; + rtk_uint32 regData; + rtk_uint32 busyFlag, checkCounter; + rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1; + + /*Check internal phy access busy or not*/ + /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/ + retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag); + if(retVal != RT_ERR_OK) + return retVal; + + if(busyFlag) + return RT_ERR_BUSYWAIT_TIMEOUT; + + /* OCP prefix */ + ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10); + if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK) + return retVal; + + /*prepare access data*/ + retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_WRITE_DATA, ocpData); + if(retVal != RT_ERR_OK) + return retVal; + + /*prepare access address*/ + ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F); + ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F); + regData = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1; + retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData); + if(retVal != RT_ERR_OK) + return retVal; + + /*Set WRITE Command*/ + retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK | RTL8367C_RW_MASK); + + checkCounter = 100; + while(checkCounter) + { + retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag); + if((retVal != RT_ERR_OK) || busyFlag) + { + checkCounter --; + if(0 == checkCounter) + return RT_ERR_BUSYWAIT_TIMEOUT; + } + else + { + checkCounter = 0; + } + } + + return retVal; +} +/* Function Name: + * rtl8367c_getAsicPHYOCPReg + * Description: + * Get PHY OCP registers + * Input: + * phyNo - Physical port number (0~7) + * ocpAddr - PHY address + * pRegData - read data + * Output: + * None + * Return: + * RT_ERR_OK - Success + * RT_ERR_SMI - SMI access error + * RT_ERR_PHY_REG_ID - invalid PHY address + * RT_ERR_PHY_ID - invalid PHY no + * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy + * Note: + * None + */ +ret_t rtl8367c_getAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 *pRegData ) +{ + ret_t retVal; + rtk_uint32 regData; + rtk_uint32 busyFlag,checkCounter; + rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1; + /*Check internal phy access busy or not*/ + /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/ + retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag); + if(retVal != RT_ERR_OK) + return retVal; + + if(busyFlag) + return RT_ERR_BUSYWAIT_TIMEOUT; + + /* OCP prefix */ + ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10); + if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK) + return retVal; + + /*prepare access address*/ + ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F); + ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F); + regData = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1; + retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData); + if(retVal != RT_ERR_OK) + return retVal; + + /*Set READ Command*/ + retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK ); + if(retVal != RT_ERR_OK) + return retVal; + + checkCounter = 100; + while(checkCounter) + { + retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag); + if((retVal != RT_ERR_OK) || busyFlag) + { + checkCounter --; + if(0 == checkCounter) + return RT_ERR_FAILED; + } + else + { + checkCounter = 0; + } + } + + /*get PHY register*/ + retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_READ_DATA, ®Data); + if(retVal != RT_ERR_OK) + return retVal; + + *pRegData = regData; + + return RT_ERR_OK; +} + +#endif + +/* Function Name: + * rtl8367c_setAsicPHYReg + * Description: + * Set PHY registers + * Input: + * phyNo - Physical port number (0~7) + * phyAddr - PHY address (0~31) + * phyData - Writing data + * Output: + * None + * Return: + * RT_ERR_OK - Success + * RT_ERR_SMI - SMI access error + * RT_ERR_PHY_REG_ID - invalid PHY address + * RT_ERR_PHY_ID - invalid PHY no + * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy + * Note: + * None + */ +ret_t rtl8367c_setAsicPHYReg(rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 phyData ) +{ + rtk_uint32 ocp_addr; + + if(phyAddr > RTL8367C_PHY_REGNOMAX) + return RT_ERR_PHY_REG_ID; + + ocp_addr = 0xa400 + phyAddr*2; + + return rtl8367c_setAsicPHYOCPReg(phyNo, ocp_addr, phyData); +} +/* Function Name: + * rtl8367c_getAsicPHYReg + * Description: + * Get PHY registers + * Input: + * phyNo - Physical port number (0~7) + * phyAddr - PHY address (0~31) + * pRegData - Writing data + * Output: + * None + * Return: + * RT_ERR_OK - Success + * RT_ERR_SMI - SMI access error + * RT_ERR_PHY_REG_ID - invalid PHY address + * RT_ERR_PHY_ID - invalid PHY no + * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy + * Note: + * None + */ +ret_t rtl8367c_getAsicPHYReg(rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 *pRegData ) +{ + rtk_uint32 ocp_addr; + + if(phyAddr > RTL8367C_PHY_REGNOMAX) + return RT_ERR_PHY_REG_ID; + + ocp_addr = 0xa400 + phyAddr*2; + + return rtl8367c_getAsicPHYOCPReg(phyNo, ocp_addr, pRegData); +} + + +/* Function Name: + * rtl8367c_setAsicSdsReg + * Description: + * Set Serdes registers + * Input: + * sdsId - sdsid (0~1) + * sdsReg - reg address (0~31) + * sdsPage - Writing data + * Output: + * None + * Return: + * RT_ERR_OK - Success + + * Note: + * None + */ + +ret_t rtl8367c_setAsicSdsReg(rtk_uint32 sdsId, rtk_uint32 sdsReg, rtk_uint32 sdsPage, rtk_uint32 value) +{ + rtk_uint32 retVal; + + if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_DATA, value)) != RT_ERR_OK) + return retVal; + + if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_ADR, (sdsPage<<5) | sdsReg)) != RT_ERR_OK) + return retVal; + + if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_CMD, 0x00C0|sdsId)) != RT_ERR_OK) + return retVal; + + return RT_ERR_OK; + +} + +/* Function Name: + * rtl8367c_getAiscSdsReg + * Description: + * Get Serdes registers + * Input: + * sdsId - sdsid (0~1) + * sdsReg - reg address (0~31) + * sdsPage - Writing data + * Output: + * None + * Return: + * RT_ERR_OK - Success + + * Note: + * None + */ +ret_t rtl8367c_getAsicSdsReg(rtk_uint32 sdsId, rtk_uint32 sdsReg, rtk_uint32 sdsPage, rtk_uint32 *value) +{ + rtk_uint32 retVal, busy; + + if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_ADR, (sdsPage<<5) | sdsReg)) != RT_ERR_OK) + return retVal; + + if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_CMD, 0x0080|sdsId)) != RT_ERR_OK) + return retVal; + + while(1) + { + if ((retVal = rtl8367c_getAsicReg(RTL8367C_REG_SDS_INDACS_CMD, &busy))!=RT_ERR_OK) + return retVal; + + if ((busy & 0x100) == 0) + break; + } + + if ((retVal = rtl8367c_getAsicReg(RTL8367C_REG_SDS_INDACS_DATA, value))!=RT_ERR_OK) + return retVal; + + return RT_ERR_OK; +} + + + + |