/** * \file phy_dp83640.c * * \brief APIs for configuring DP83640. * * This file contains the device abstraction APIs for PHY DP83640. */ /* * Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * 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. * */ /* USER CODE BEGIN (0) */ /* USER CODE END */ #include "sys_common.h" #include "mdio.h" #include "phy_dp83640.h" /* USER CODE BEGIN (1) */ /* USER CODE END */ /******************************************************************************* * API FUNCTION DEFINITIONS *******************************************************************************/ /** * \brief Reads the PHY ID. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * * \return 32 bit PHY ID (ID1:ID2) * **/ /* SourceId : ETH_SourceId_063 */ /* DesignId : ETH_DesignId_063*/ /* Requirements : HL_ETH_SR49 */ uint32 Dp83640IDGet(uint32 mdioBaseAddr, uint32 phyAddr) { uint32 id = 0U; uint16 data = 0U; /* read the ID1 register */ (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_ID1, &data); /* update the ID1 value */ id = (uint32)data; id = (uint32)((uint32)id << PHY_ID_SHIFT); /* read the ID2 register */ (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_ID2, &data); /* update the ID2 value */ id |= data; /* return the ID in ID1:ID2 format */ return id; } /** * \brief Reads the link status of the PHY. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * \param retries The number of retries before indicating down status * * \return link status after reading \n * TRUE if link is up * FALSE if link is down \n * * \note This reads both the basic status register of the PHY and the * link register of MDIO for double check **/ /* SourceId : ETH_SourceId_067 */ /* DesignId : ETH_DesignId_067*/ /* Requirements : HL_ETH_SR47 */ boolean Dp83640LinkStatusGet(uint32 mdioBaseAddr, uint32 phyAddr, volatile uint32 retries) { volatile uint16 linkStatus = 0U; boolean retVal = TRUE; while (retVal == TRUE) { /* First read the BSR of the PHY */ (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_BSR, &linkStatus); /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ if((linkStatus & PHY_LINK_STATUS) != 0U) { /* Check if MDIO LINK register is updated */ linkStatus = (uint16)MDIOPhyLinkStatusGet(mdioBaseAddr); /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ if((linkStatus & (uint16)((uint16)1U << phyAddr)) != 0U) { break; } else { /*SAFETYMCUSW 9 S MR:12.2 "Ternary Operator Expression" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ if(retries != 0U) { retries--; } else { retVal = FALSE; } } } else { /*SAFETYMCUSW 9 S MR:12.2 "Ternary Operator Expression" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ if(retries != 0U) { retries--; } else { retVal = FALSE; } } } return retVal; } /** * \brief This function does Autonegotiates with the EMAC device connected * to the PHY. It will wait till the autonegotiation completes. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * \param advVal Autonegotiation advertisement value * advVal can take the following any OR combination of the values \n * DP83640_100BTX - 100BaseTX * DP83640_100BTX_FD - Full duplex capabilty for 100BaseTX * DP83640_10BT - 10BaseT * DP83640_10BT_FD - Full duplex capability for 10BaseT * * \return status after autonegotiation \n * TRUE if autonegotiation successful * FALSE if autonegotiation failed * **/ /* SourceId : ETH_SourceId_065 */ /* DesignId : ETH_DesignId_065*/ /* Requirements : HL_ETH_SR46 */ boolean Dp83640AutoNegotiate(uint32 mdioBaseAddr, uint32 phyAddr, uint16 advVal) { volatile uint16 data = 0U, anar = 0U; boolean retVal = TRUE; uint32 phyNegTries = 0xFFFFU; if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, &data) != TRUE ) { retVal = FALSE; } data |= PHY_AUTONEG_ENABLE; /* Enable Auto Negotiation */ MDIOPhyRegWrite(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, data); if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, &data) != TRUE ) { retVal = FALSE; } /* Write Auto Negotiation capabilities */ (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_AUTONEG_ADV, &anar); anar &= (uint16)(~0xff10U); /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ MDIOPhyRegWrite(mdioBaseAddr, phyAddr, (uint32)PHY_AUTONEG_ADV, (anar |advVal)); data |= PHY_AUTONEG_RESTART; /* Start Auto Negotiation */ MDIOPhyRegWrite(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, data); /* Get the auto negotiation status*/ if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_BSR, &data) != TRUE) { retVal = FALSE; } /* Wait till auto negotiation is complete */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ /*SAFETYMCUSW 28 D MR:NA "Hardware status bit read check" */ while((((uint16)(PHY_AUTONEG_INCOMPLETE)) == (data & (uint16)(PHY_AUTONEG_STATUS))) && (retVal == TRUE) && (phyNegTries > 0U)) { (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_BSR, &data); phyNegTries--; } /* Check if the PHY is able to perform auto negotiation */ /*SAFETYMCUSW 134 S MR:12.2 "LDRA Tool issue" */ if((data & PHY_AUTONEG_ABLE) != 0U) { retVal = TRUE; } else { retVal = FALSE; } return retVal; } /** * \brief Reads the Link Partner Ability register of the PHY. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * \param ptnerAblty The partner abilities of the EMAC * * \return status after reading \n * TRUE if reading successful * FALSE if reading failed **/ /* SourceId : ETH_SourceId_066 */ /* DesignId : ETH_DesignId_066*/ /* Requirements : HL_ETH_SR48 */ boolean Dp83640PartnerAbilityGet(uint32 mdioBaseAddr, uint32 phyAddr, uint16 *ptnerAblty) { return (MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_LINK_PARTNER_ABLTY, ptnerAblty)); } /** * \brief Resets the PHY. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * * \return No return value. **/ /* SourceId : ETH_SourceId_064 */ /* DesignId : ETH_DesignId_064*/ /* Requirements : HL_ETH_SR44 */ void Dp83640Reset(uint32 mdioBaseAddr, uint32 phyAddr) { uint16 regVal = 0U; MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, PHY_SOFTRESET); (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, ®Val); /* : This bit is self-clearing and returns 1 until the reset process is complete. */ while((regVal & PHY_SOFTRESET) != 0U) { (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, ®Val); } } /** * \brief Enables PHY Loopback. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * * \return No return value. **/ /* SourceId : ETH_SourceId_069 */ /* DesignId : ETH_DesignId_069*/ /* Requirements : HL_ETH_SR51 */ void Dp83640EnableLoopback(uint32 mdioBaseAddr, uint32 phyAddr) { uint32 delay = 0x1FFFU; uint16 regVal = 0x0000U; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, ®Val); /* Disabling Auto Negotiate. */ /*SAFETYMCUSW 334 S MR:10.5 "Only unsigned short values are used." */ regVal &= (uint16)(~((uint16)PHY_AUTONEG_ENABLE)); /* Enabling Loopback. */ regVal |= PHY_LPBK_ENABLE; MDIOPhyRegWrite(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, regVal); while(delay > 0U) { delay--; } } /** * \brief Disable PHY Loopback. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * * \return No return value. **/ /* SourceId : ETH_SourceId_070 */ /* DesignId : ETH_DesignId_070*/ /* Requirements : HL_ETH_SR51 */ void Dp83640DisableLoopback(uint32 mdioBaseAddr, uint32 phyAddr) { uint32 delay = 0x1FFFU; uint16 regVal = 0x0000U; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, ®Val); /* Enabling Loopback. */ /*SAFETYMCUSW 334 S MR:10.5 "Only unsigned short values are used." */ regVal &= (uint16)(~((uint16)PHY_LPBK_ENABLE)); MDIOPhyRegWrite(mdioBaseAddr, phyAddr, (uint32)PHY_BCR, regVal); while(delay > 0U) { delay--; } } /** * \brief Reads the Transmit/Receive Timestamp * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * \param type 1- Transmit Timetamp * 2- Receive Timestamp * \param timestamp The read value that is returned to the user. * * \return The timestamp is returned in 4 16-bit reads. They are stored in the following order: * Timestamp_ns [63:49] * Overflow_cnt[48:47], Timestamp_ns[46:33] * Timestamp_sec[32:16] * Timestamp_sec[15:0] * This is returned as a 64 bit value. * **/ /* SourceId : ETH_SourceId_068 */ /* DesignId : ETH_DesignId_068*/ /* Requirements : HL_ETH_SR53 */ uint64 Dp83640GetTimeStamp(uint32 mdioBaseAddr, uint32 phyAddr, phyTimeStamp_t type) { uint16 ts = 0U; /* (MISRA-C:2004 10.1/R) MISRA error reported with Code Composer Studio MISRA checker (due to use of & ?) */ uint16 *tsptr = &ts; uint64 timeStamp = 0u; if(type == 1U) { (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_TXTS, tsptr); timeStamp |= (uint64)ts; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_TXTS, tsptr); timeStamp = timeStamp << 16U ; timeStamp |= (uint64)ts; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_TXTS, tsptr); timeStamp = timeStamp << 16U ; timeStamp |= (uint64)ts; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_TXTS, tsptr); timeStamp = timeStamp << 16U ; timeStamp |= (uint64)ts; } else { (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_RXTS, tsptr); timeStamp |= (uint64)ts; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_RXTS, tsptr); timeStamp = timeStamp << 16U ; timeStamp |= (uint64)ts; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_RXTS, tsptr); timeStamp = timeStamp << 16U ; timeStamp |= (uint64)ts; (void)MDIOPhyRegRead(mdioBaseAddr, phyAddr, (uint32)PHY_RXTS, tsptr); timeStamp = timeStamp << 16U ; timeStamp |= (uint64)ts; } return timeStamp; } /** * \brief Reads the Speed info from Status register of the PHY. * * \param mdioBaseAddr Base Address of the MDIO Module Registers. * \param phyAddr PHY Adress. * \param ptnerAblty The partner abilities of the EMAC * * \return status after reading \n * TRUE if reading successful * FALSE if reading failed **/ boolean Dp83640PartnerSpdGet(uint32 mdioBaseAddr, uint32 phyAddr, uint16 *ptnerAblty) { return (MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_LINK_PARTNER_SPD, ptnerAblty)); } /* USER CODE BEGIN (2) */ /* USER CODE END */ /**************************** End Of File ***********************************/