| /* |
| * Copyright 2017, Data61 |
| * Commonwealth Scientific and Industrial Research Organisation (CSIRO) |
| * ABN 41 687 119 230. |
| * |
| * This software may be distributed and modified according to the terms of |
| * the BSD 2-Clause license. Note that NO WARRANTY is provided. |
| * See "LICENSE_BSD2.txt" for details. |
| * |
| * @TAG(DATA61_BSD) |
| */ |
| |
| /** |
| * \file mdio.c |
| * |
| * \brief MDIO APIs. |
| * |
| * This file contains the device abstraction layer APIs for MDIO. |
| */ |
| |
| /* |
| * 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. |
| * |
| */ |
| |
| /* HW Macros and Peripheral Defines */ |
| #include <ethdrivers/plat/hw/hw_types.h> |
| #include <ethdrivers/plat/hw/hw_mdio.h> |
| |
| /* Driver APIs */ |
| #include <ethdrivers/plat/mdio.h> |
| |
| /******************************************************************************* |
| * INTERNAL MACRO DEFINITIONS |
| *******************************************************************************/ |
| #define PHY_REG_MASK (0x1Fu) |
| #define PHY_ADDR_MASK (0x1Fu) |
| #define PHY_DATA_MASK (0xFFFFu) |
| #define PHY_REG_SHIFT (21u) |
| #define PHY_ADDR_SHIFT (16u) |
| |
| /******************************************************************************* |
| * API FUNCTION DEFINITIONS |
| *******************************************************************************/ |
| |
| /** |
| * \brief Reads a PHY register using MDIO. |
| * |
| * \param baseAddr Base Address of the MDIO Module Registers. |
| * \param phyAddr PHY Adress. |
| * \param regNum Register Number to be read. |
| * \param dataPtr Pointer where the read value shall be written. |
| * |
| * \return status of the read \n |
| * TRUE - read is successful.\n |
| * FALSE - read is not acknowledged properly. |
| * |
| **/ |
| unsigned int MDIOPhyRegRead(unsigned int baseAddr, unsigned int phyAddr, |
| unsigned int regNum, volatile unsigned short *dataPtr) |
| { |
| /* Wait till transaction completion if any */ |
| while (HWREG(baseAddr + MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); |
| |
| HWREG(baseAddr + MDIO_USERACCESS0) |
| = (MDIO_USERACCESS0_READ | MDIO_USERACCESS0_GO |
| | ((regNum & PHY_REG_MASK) << PHY_REG_SHIFT) |
| | ((phyAddr & PHY_ADDR_MASK) << PHY_ADDR_SHIFT)); |
| |
| /* wait for command completion */ |
| while (HWREG(baseAddr + MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); |
| |
| /* Store the data if the read is acknowledged */ |
| if ((HWREG(baseAddr + MDIO_USERACCESS0)) & MDIO_USERACCESS0_ACK) { |
| *dataPtr = (unsigned short)((HWREG(baseAddr + MDIO_USERACCESS0)) |
| & PHY_DATA_MASK); |
| return TRUE; |
| } |
| |
| return FALSE; |
| } |
| |
| /** |
| * \brief Writes a PHY register using MDIO. |
| * |
| * \param baseAddr Base Address of the MDIO Module Registers. |
| * \param phyAddr PHY Adress. |
| * \param regNum Register Number to be read. |
| * \param RegVal Value to be written. |
| * |
| * \return None |
| * |
| **/ |
| void MDIOPhyRegWrite(unsigned int baseAddr, unsigned int phyAddr, |
| unsigned int regNum, unsigned short RegVal) |
| { |
| /* Wait till transaction completion if any */ |
| while (HWREG(baseAddr + MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); |
| |
| HWREG(baseAddr + MDIO_USERACCESS0) |
| = (MDIO_USERACCESS0_WRITE | MDIO_USERACCESS0_GO |
| | ((regNum & PHY_REG_MASK) << PHY_REG_SHIFT) |
| | ((phyAddr & PHY_ADDR_MASK) << PHY_ADDR_SHIFT) |
| | RegVal); |
| |
| /* wait for command completion*/ |
| while (HWREG(baseAddr + MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); |
| } |
| /** |
| * \brief Reads the alive status of all PHY connected to this MDIO. |
| * The bit correponding to the PHY address will be set if the PHY |
| * is alive. |
| * |
| * \param baseAddr Base Address of the MDIO Module Registers. |
| * |
| * \return MDIO alive register state |
| * |
| **/ |
| unsigned int MDIOPhyAliveStatusGet(unsigned int baseAddr) |
| { |
| return (HWREG(baseAddr + MDIO_ALIVE)); |
| } |
| |
| /** |
| * \brief Reads the link status of all PHY connected to this MDIO. |
| * The bit correponding to the PHY address will be set if the PHY |
| * link is active. |
| * |
| * \param baseAddr Base Address of the MDIO Module Registers. |
| * |
| * \return MDIO link register state |
| * |
| **/ |
| unsigned int MDIOPhyLinkStatusGet(unsigned int baseAddr) |
| { |
| return (HWREG(baseAddr + MDIO_LINK)); |
| } |
| |
| /** |
| * \brief Initializes the MDIO peripheral. This enables the MDIO state |
| * machine, uses standard pre-amble and set the clock divider value. |
| * |
| * \param baseAddr Base Address of the MDIO Module Registers. |
| * \param mdioInputFreq The clock input to the MDIO module |
| * \param mdioOutputFreq The clock output required on the MDIO bus |
| * \return None |
| * |
| **/ |
| void MDIOInit(unsigned int baseAddr, unsigned int mdioInputFreq, |
| unsigned int mdioOutputFreq) |
| { |
| unsigned int clkDiv = (mdioInputFreq / mdioOutputFreq) - 1; |
| |
| HWREG(baseAddr + MDIO_CONTROL) = ((clkDiv & MDIO_CONTROL_CLKDIV) |
| | MDIO_CONTROL_ENABLE |
| | MDIO_CONTROL_PREAMBLE |
| | MDIO_CONTROL_FAULTENB); |
| } |
| |
| /** |
| * \brief Saves the MDIO register context. Note that only MDIO control |
| * register context is saved here. |
| * |
| * \param baseAddr Base Address of the MDIO Module Registers. |
| * \param contextPtr Pointer to the structure where MDIO context |
| * needs to be saved. |
| * \return None |
| * |
| **/ |
| void MDIOContextSave(unsigned int baseAddr, MDIOCONTEXT *contextPtr) |
| { |
| contextPtr->mdioCtrl = HWREG(baseAddr + MDIO_CONTROL); |
| } |
| |
| /** |
| * \brief Restores the MDIO register context. Note that only MDIO control |
| * register context is restored here. Hence enough delay shall be |
| * given after this API |
| * |
| * \param baseAddr Base Address of the MDIO Module Registers. |
| * \param contextPtr Pointer to the structure where MDIO context |
| * needs to be restored from |
| * \return None |
| * |
| **/ |
| void MDIOContextRestore(unsigned int baseAddr, MDIOCONTEXT *contextPtr) |
| { |
| HWREG(baseAddr + MDIO_CONTROL) = contextPtr->mdioCtrl; |
| } |
| |
| /***************************** End Of File ***********************************/ |