diff options
Diffstat (limited to 'cpsw/src/netif/phy.c')
-rwxr-xr-x | cpsw/src/netif/phy.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/cpsw/src/netif/phy.c b/cpsw/src/netif/phy.c new file mode 100755 index 0000000..1ce9494 --- /dev/null +++ b/cpsw/src/netif/phy.c @@ -0,0 +1,402 @@ +/** + * \file phy.c + * + * \brief APIs for configuring ethernet PHYs + * + * This file contains the device abstraction APIs for ethernet PHYs. + */ + +/* +* Copyright (C) 2010 Texas Instruments Incorporated - http://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. +* +*/ + +#include "hw_types.h" +#include "mdio.h" +#include "phy.h" + +#define PHY_ADV_VAL_MASK (0x01e0) +#define PHY_GIG_ADV_VAL_MASK (0x0300) + +/******************************************************************************* +* 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) + * + **/ +unsigned int PhyIDGet(unsigned int mdioBaseAddr, unsigned int phyAddr) +{ + unsigned int id = 0; + unsigned short data; + + /* read the ID1 register */ + MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_ID1, &data); + + /* update the ID1 value */ + id = data << PHY_ID_SHIFT; + + /* read the ID2 register */ + MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_ID2, &data); + + /* update the ID2 value */ + id |= data; + + /* return the ID in ID1:ID2 format */ + return id; +} + +/** + * \brief Reads a register from the the PHY + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * \param regIdx Index of the register to be read + * \param regValAdr address where value of the register will be written + * + * \return status of the read + * + **/ +unsigned int PhyRegRead(unsigned int mdioBaseAddr, unsigned int phyAddr, + unsigned int regIdx, unsigned short *regValAdr) +{ + return (MDIOPhyRegRead(mdioBaseAddr, phyAddr, regIdx, regValAdr)); +} + +/** + * \brief Writes a register with the input + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * \param regIdx Index of the register to be read + * \param regValAdr value to be written + * + * \return None + * + **/ +void PhyRegWrite(unsigned int mdioBaseAddr, unsigned int phyAddr, + unsigned int regIdx, unsigned short regVal) +{ + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, regIdx, regVal); +} + +/** + * \brief Enables Loop Back mode + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * + * \return status after enabling. \n + * TRUE if loop back is enabled \n + * FALSE if not able to enable + * + **/ +unsigned int PhyLoopBackEnable(unsigned int mdioBaseAddr, unsigned int phyAddr) +{ + unsigned short data; + + if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE ) + { + return FALSE; + } + + data |= PHY_LPBK_ENABLE; + + /* Enable loop back */ + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data); + + return TRUE; +} + +/** + * \brief Disables Loop Back mode + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * + * \return status after enabling. \n + * TRUE if loop back is disabled \n + * FALSE if not able to disable + * + **/ +unsigned int PhyLoopBackDisable(unsigned int mdioBaseAddr, unsigned int phyAddr) +{ + unsigned short data; + + if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE ) + { + return FALSE; + } + + data &= ~(PHY_LPBK_ENABLE); + + /* Disable loop back */ + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data); + + return TRUE; +} + +/** + * \brief Resets the PHY + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * \param speed Speed to be enabled + * \param duplexMode Duplex Mode + * + * \return status after configuring \n + * TRUE if configuration successful + * FALSE if configuration failed + * + **/ +unsigned int PhyReset(unsigned int mdioBaseAddr, unsigned int phyAddr) +{ + unsigned short data; + + data = PHY_SOFTRESET; + + /* Reset the phy */ + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data); + + /* wait till the reset bit is auto cleared */ + while(data & PHY_SOFTRESET) + { + /* Read the reset */ + if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE) + { + return FALSE; + } + } + + return TRUE; +} + +/** + * \brief Configures the PHY for a given speed and duplex mode. + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * \param speed Speed to be enabled + * \param duplexMode Duplex Mode + * + * \return status after configuring \n + * TRUE if configuration successful + * FALSE if configuration failed + * + **/ +unsigned int PhyConfigure(unsigned int mdioBaseAddr, unsigned int phyAddr, + unsigned short speed, unsigned short duplexMode) +{ + /* Set the configurations */ + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, (speed | duplexMode)); + + return TRUE; +} + +/** + * \brief This function ask the phy device to start auto negotiation. + * + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * \param advVal Autonegotiation advertisement value + * \param gigAdvVal Gigabit capability advertisement value + * advVal can take the following any OR combination of the values \n + * PHY_100BTX - 100BaseTX \n + * PHY_100BTX_FD - Full duplex capabilty for 100BaseTX \n + * PHY_10BT - 10BaseT \n + * PHY_10BT_FD - Full duplex capability for 10BaseT \n + * gigAdvVal can take one of the following values \n + * PHY_NO_1000BT - No 1000Base-T capability\n + * PHY_1000BT_FD - Full duplex capabilty for 1000 Base-T \n + * PHY_1000BT_HD - Half duplex capabilty for 1000 Base-T \n + * FALSE - It is passed as an argument if phy dosen't support + * Giga bit capability + * + * \return status after autonegotiation \n + * TRUE if autonegotiation started + * FALSE if autonegotiation not started + * + **/ +unsigned int PhyAutoNegotiate(unsigned int mdioBaseAddr, unsigned int phyAddr, + unsigned short *advPtr, unsigned short *gigAdvPtr) +{ + volatile unsigned short data; + volatile unsigned short anar; + + if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE ) + { + return FALSE; + } + + data |= PHY_AUTONEG_ENABLE; + + if (*gigAdvPtr != 0) + { + /* Set phy for gigabit speed */ + data &= PHY_SPEED_MASK; + data |= PHY_SPEED_1000MBPS; + } + + /* Enable Auto Negotiation */ + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data); + + if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE ) + { + return FALSE; + } + + /* Write Auto Negotiation capabilities */ + MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_AUTONEG_ADV, &anar); + anar &= ~PHY_ADV_VAL_MASK; + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_AUTONEG_ADV, (anar |(*advPtr))); + + /* Write Auto Negotiation Gigabyte capabilities */ + anar = 0; + MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_1000BT_CONTROL, &anar); + anar &= ~PHY_GIG_ADV_VAL_MASK; + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_1000BT_CONTROL, + (anar |(*gigAdvPtr))); + + data |= PHY_AUTONEG_RESTART; + + /* Start Auto Negotiation */ + MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data); + + return TRUE; +} + +/** + * \brief Returns the status of Auto Negotiation completion. + * + * \param mdioBaseAddr Base Address of the MDIO Module Registers. + * \param phyAddr PHY Adress. + * + * \return Auto negotiation completion status \n + * TRUE if auto negotiation is completed + * FALSE if auto negotiation is not completed + **/ +unsigned int PhyAutoNegStatusGet(unsigned int mdioBaseAddr, unsigned int phyAddr) +{ + volatile unsigned short data; + + MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BSR, &data); + + /* Auto negotiation completion status */ + if(PHY_AUTONEG_COMPLETE == (data & (PHY_AUTONEG_STATUS))) + { + return TRUE; + } + + return FALSE; +} + +/** + * \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 Pointer to which partner ability will be written. + * \param gbpsPtnerAblty Pointer to which Giga bit capability will be written. + * + * gbpsPtnerAblty can take following Macros.\n + * + * TRUE - It is passed as argument if phy supports Giga bit capability.\n + * FALSE - It is passed as argument if phy dosen't supports Giga bit + * capability.\n + * + * \return status after reading \n + * TRUE if reading successful + * FALSE if reading failed + **/ +unsigned int PhyPartnerAbilityGet(unsigned int mdioBaseAddr, + unsigned int phyAddr, + unsigned short *ptnerAblty, + unsigned short *gbpsPtnerAblty) +{ + unsigned int status; + + status = MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_LINK_PARTNER_ABLTY, + ptnerAblty); + + if (*gbpsPtnerAblty != 0) + { + status = status | MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_1000BT_STATUS, + gbpsPtnerAblty); + } + + return status; +} + +/** + * \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 + **/ +unsigned int PhyLinkStatusGet(unsigned int mdioBaseAddr, + unsigned int phyAddr, + volatile unsigned int retries) +{ + volatile unsigned short linkStatus; + + retries++; + while (retries) + { + /* First read the BSR of the PHY */ + MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BSR, &linkStatus); + + if(linkStatus & PHY_LINK_STATUS) + { + return TRUE; + } + + retries--; + } + + return FALSE; +} + +/**************************** End Of File ***********************************/ |