/*
 *  Copyright (C) 2024 Texas Instruments Incorporated
 *
 *  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 Files                                  */
/* ========================================================================== */

#include <tiescsoc.h>
#include <drivers/hw_include/hw_types.h>
#include <drivers/hw_include/cslr_spinlock.h>
#include <drivers/hw_include/am64x_am243x/cslr_intr_timesync_event_introuter0.h>
#include <drivers/sciclient.h>
#include <drivers/mdio.h>
#include <kernel/dpl/DebugP.h>
#include "ti_board_open_close.h"
#include "ti_drivers_config.h"
#include <industrial_comms/ethercat_slave/beckhoff_stack/stack_hal/tieschw.h>
#include "tiesc_eeprom.h" /* header equivalent of ESI bin file */
#ifdef  MDIO_MANUAL_MODE_ENABLED
#include <industrial_comms/ethercat_slave/icss_fwhal/firmware/g_v1.3/mdio_fw_bin.h>  /* > Contains MDIO firmware */
#endif
#ifdef ICSSG0_INSTANCE
#include <ethphy_dp83826e.h>
#endif


#include "ethphy_dp83822.h"
#include    "EepromAccessExtern.h"
#include <inttypes.h>
#include "SharedMemoryExterns.h"
/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/* EEPROM data offset in I2C EEPROM Flash */
#define I2C_EEPROM_DATA_OFFSET      (0x8000)

/* For ICSSG0 SEM daughter card, link polarity is inverted*/
#ifdef ICSSG0_INSTANCE
#define TIESC_LINK0_POL             TIESC_LINK_POL_ACTIVE_LOW
#define TIESC_LINK1_POL             TIESC_LINK_POL_ACTIVE_LOW
#else
#define TIESC_LINK0_POL             TIESC_LINK_POL_ACTIVE_LOW       //ORG -TIESC_LINK_POL_ACTIVE_HIGH
#define TIESC_LINK1_POL             TIESC_LINK_POL_ACTIVE_LOW       //ORG -TIESC_LINK_POL_ACTIVE_HIGH
#endif

/* SPI Flash offset at which application binary downloaded over FOE will be stored*/
#define FOE_APPL_BIN_OFFSET         (0x80000)

/* Macros for timesync router configuration*/

/* Address for mux control of event 8(PRG0_IEP0_EDC_LATCH_IN0). 4 + (4*8) = 36 = 0x24*/
#define TIMESYNC_EVENT_INTROUTER0_MUXCNTL_8     (0x24)

/* Address for mux control of event 9(PRG0_IEP0_EDC_LATCH_IN1). 4 + (4*9) = 40 = 0x28*/
#define TIMESYNC_EVENT_INTROUTER0_MUXCNTL_9     (0x28)

/* Address for mux control of event 12(PRG1_IEP0_EDC_LATCH_IN0). 4 + (4*12) = 52 = 0x34*/
#define TIMESYNC_EVENT_INTROUTER0_MUXCNTL_12    (0x34)

/* Address for mux control of event 13(PRG1_IEP0_EDC_LATCH_IN1). 4 + (4*13) = 56 = 0x38*/
#define TIMESYNC_EVENT_INTROUTER0_MUXCNTL_13    (0x38)

/* MDIO Clock Divider Value */
#define MDIO_CLK_DIV_CFG                        (0x1A9U)

#define DP83869_RX_ERR_CNT_REG_ADDRESS          (0x15)

#define PRUICSS_PRUx                            PRUICSS_TX_PRU0
#define PRU_REG_10                              (4*10)
#define PRU_REG_12                              (4*12)

#ifdef ICSSG0_INSTANCE
/* Macro for phy register address to fix strapping issue*/
#define DP83826E_AUTO_NEGOTIATION_ADVERTISEMENT_REG_ADDRESS          (0x04)
#endif

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

extern PRUICSS_Handle pruIcss1Handle;

extern const unsigned char tiesc_eeprom[];  /* EEPROM array corresponding to XML */

extern uint8_t *pEEPROM;                    /* EEPROM array used by the stack */
/* ========================================================================== */
/*                       Function Declarations                                */
/* ========================================================================== */

int32_t tiesc_getArmInterruptOffset();

int32_t tiesc_eepromRead(uint8_t *buf, uint32_t len);

int32_t tiesc_eepromWrite(uint8_t *buf,uint32_t len);

/**
*  @brief    This API configures port0 and port1 phys for enhanced link detection, enable RXERR detection during IDLE,
*   disable detection of transmit error in odd-nibble boundary (for odd nibble insertion) and fast RXDV detection.
*   This is called only during initialization.
*
*   @param pruIcssHandle PRUSS Handle
*   @param phy0addr Phy address of port0
*   @param phy1addr Phy address of port1
*   @param enhancedlink_enable Fast link detect (enhanced link detection) enable/disable flag
*/
void tiesc_ethphyInit(PRUICSS_Handle pruIcssHandle, uint8_t phy0addr,
                      uint8_t phy1addr, uint8_t enhancedlink_enable);

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

#ifdef MDIO_MANUAL_MODE_ENABLED
void tiesc_mdioManualModeSetup()
{
    int32_t status;
    PRUICSS_HwAttrs const   *pruicssHwAttrs = (PRUICSS_HwAttrs const *)(pruIcss1Handle->hwAttrs);
    /* ----------------------------------------------------------------- */
    /* Load the MDIO firmware binary on PRU Core;                        */
    /* ----------------------------------------------------------------- */
    /* Reset Core */
    status = PRUICSS_resetCore(pruIcss1Handle, PRUICSS_PRUx);
    DebugP_assert(SystemP_SUCCESS == status);
    /* Disabe Core */
    status = PRUICSS_disableCore(pruIcss1Handle, PRUICSS_PRUx);
    DebugP_assert(SystemP_SUCCESS == status);

    /* Load firmware. Set buffer = write to PRU memory */
    status = PRUICSS_writeMemory(pruIcss1Handle, PRUICSS_IRAM_TX_PRU(0), 0,
                       (uint32_t *) PRUFirmware, sizeof(PRUFirmware));
    DebugP_assert(status != 0);

    /* Pass value to R10 of TX_PRU core for MDIO FW WA Configuration */
    CSL_REG32_WR(pruicssHwAttrs->pru0DramBase + CSL_ICSS_G_PR1_PDSP_TX0_IRAM_DEBUG_REGS_BASE + PRU_REG_10, MDIO_MANUAL_MODE_FW_CONFIG_VALUE);
    /* Pass value to R12 of TX_PRU core for emulated MDIO Base Address */
    CSL_REG32_WR(pruicssHwAttrs->pru0DramBase + CSL_ICSS_G_PR1_PDSP_TX0_IRAM_DEBUG_REGS_BASE + PRU_REG_12, MDIO_MANUAL_MODE_BASE_ADDRESS);

    /* Run firmware */
    status = PRUICSS_enableCore(pruIcss1Handle, PRUICSS_PRUx);
    DebugP_assert(SystemP_SUCCESS == status);
}
#endif

uint8_t tiesc_isEthercatDevice(void)
{
    uint8_t data;

    PRUICSS_readEfuse(pruIcss1Handle, &data);

    data = (data && 0x01);
    if(0x00 == data)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void tiesc_bspSoftReset()
{
    Sciclient_pmDeviceReset(0xFFFFFFFFU);
    return;
}

void tiesc_socEvmInit()
{
#ifdef ICSSG0_INSTANCE
    tiesc_addOnBoardResetSequence();
#endif
    const PRUICSS_HwAttrs *pruicssHwAttrs;
    uint32_t inEventLatch0, inEventLatch1, outEventLatch0, outEventLatch1;

    pruIcss1Handle = PRUICSS_open(CONFIG_PRU_ICSS1);
    pruicssHwAttrs = PRUICSS_getAttrs(CONFIG_PRU_ICSS1);

    /* Selecting MII-RT mode in GPCFG mux */
    PRUICSS_setGpMuxSelect(pruIcss1Handle, PRUICSS_PRU0, PRUICSS_GP_MUX_SEL_MODE_MII);
    PRUICSS_setGpMuxSelect(pruIcss1Handle, PRUICSS_PRU1, PRUICSS_GP_MUX_SEL_MODE_MII);

    PRUICSS_setGpiMode(pruIcss1Handle, PRUICSS_PRU0, PRUICSS_GPI_MODE_MII_RT);
    PRUICSS_setGpiMode(pruIcss1Handle, PRUICSS_PRU1, PRUICSS_GPI_MODE_MII_RT);

    PRUICSS_setIcssCfgMiiMode(pruIcss1Handle, 0, PRUICSS_ICSS_CFG_MII_MODE_MII);
    PRUICSS_setIcssCfgMiiMode(pruIcss1Handle, 1, PRUICSS_ICSS_CFG_MII_MODE_MII);

    PRUICSS_setIcssCfgTxFifo(pruIcss1Handle, PRUICSS_TX_L1_FIFO, 1);
    PRUICSS_setIcssCfgTxFifo(pruIcss1Handle, PRUICSS_TX_L2_FIFO, 0);

    /* Making the clock for ICSSG core and IEP same */
    PRUICSS_setIepClkSrc(pruIcss1Handle, 1U);

    /* Disable PRUs. This is to ensure PRUs are not running when application is not initialized */
    PRUICSS_disableCore(pruIcss1Handle, PRUICSS_PRU0);
    PRUICSS_disableCore(pruIcss1Handle, PRUICSS_PRU1);

    /* TimeSync Router configuration for latch pins */
    if(pruicssHwAttrs->instance == 0)
    {
        inEventLatch0 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG0_IEP0_EDC_LATCH_IN0IN_PRG0_IEP0_EDC_LATCH_IN0_0;
        inEventLatch1 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG0_IEP0_EDC_LATCH_IN1IN_PRG0_IEP0_EDC_LATCH_IN1_0;
        outEventLatch0 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_8;
        outEventLatch1 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_9;
    }
    else
    {
        inEventLatch0 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG1_IEP0_EDC_LATCH_IN0IN_PRG1_IEP0_EDC_LATCH_IN0_0;
        inEventLatch1 = CSLR_TIMESYNC_EVENT_INTROUTER0_IN_PINFUNCTION_PRG1_IEP0_EDC_LATCH_IN1IN_PRG1_IEP0_EDC_LATCH_IN1_0;
        outEventLatch0 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_12;
        outEventLatch1 = TIMESYNC_EVENT_INTROUTER0_MUXCNTL_13;
    }

    HW_WR_REG32((CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + outEventLatch0), (inEventLatch0 | 0x10000));
    HW_WR_REG32((CSL_TIMESYNC_EVENT_INTROUTER0_CFG_BASE + outEventLatch1), (inEventLatch1 | 0x10000));
}

void tiesc_socParamsInit(bsp_params *bspInitParams)
{
    bsp_params_init(bspInitParams);
    bspInitParams->pruicss_handle = pruIcss1Handle;
    bspInitParams->interrupt_offset = tiesc_getArmInterruptOffset();
    bspInitParams->eeprom_read = tiesc_eepromRead;
    bspInitParams->eeprom_write = tiesc_eepromWrite;
    bspInitParams->spinlock_base_address = CSL_SPINLOCK0_BASE;
    bspInitParams->ethphy_init = tiesc_ethphyInit;
    /* For EtherCAT, Fast link detection using MLINK mode is required to support complete functionality */
    /* Check example documentation for more details */
#ifdef ENHANCED_LINK_ENABLED
    bspInitParams->enhancedlink_enable = TIESC_MDIO_RX_LINK_ENABLE;
#else
    bspInitParams->enhancedlink_enable = TIESC_MDIO_RX_LINK_DISABLE;
#endif
    bspInitParams->link0_polarity = TIESC_LINK0_POL;
    bspInitParams->link1_polarity = TIESC_LINK1_POL;
    bspInitParams->phy0_address = ((const ETHPHY_Attrs *)ETHPHY_getAttrs(CONFIG_ETHPHY0))->phyAddress;
    bspInitParams->phy1_address = ((const ETHPHY_Attrs *)ETHPHY_getAttrs(CONFIG_ETHPHY1))->phyAddress;
    bspInitParams->default_tiesc_eeprom = (const unsigned char *)(&(tiesc_eeprom));
    bspInitParams->eeprom_pointer_for_stack = &(pEEPROM);
#if CONFIG_PRU_ICSS1_CORE_CLK_FREQ_HZ == (333333333U)
    bspInitParams->pruicssClkFreq = TIESC_PRUICSS_CLOCK_FREQUENCY_333_MHZ;
#elif CONFIG_PRU_ICSS1_CORE_CLK_FREQ_HZ == (200000000U)
    bspInitParams->pruicssClkFreq = TIESC_PRUICSS_CLOCK_FREQUENCY_200_MHZ;
#endif
#ifdef  MDIO_MANUAL_MODE_ENABLED
    bspInitParams->mdioManualMode = TIESC_MDIO_MANUAL_MODE_FW;
#else
    bspInitParams->mdioManualMode = TIESC_MDIO_HW_MODE;
#endif
#ifndef ENABLE_PDI_TASK
    bspInitParams->pdi_isr = PDI_Isr;
#endif
#ifndef ENABLE_SYNC_TASK
    bspInitParams->sync0_isr = Sync0_Isr;
    bspInitParams->sync1_isr = Sync1_Isr;
#endif
}

void tiesc_displayEscVersion(uint16_t revision, uint16_t build)
{
    DebugP_log("Revision/Type : x%04X Build : x%04X\n\r", revision, build);
    DebugP_log("Firmware Version : %d.%d.%d\n\r", (revision >> 8), (build >> 8), (build & 0xFF));
}

void tiesc_setOutputLed(uint8_t mask)
{
    //LED_setMask(gLedHandle[CONFIG_LED_DIGITAL_OUTPUT], (uint32_t)(0xFFFF & mask));
}

void tiesc_setRunLed(uint8_t value)
{
    //ethercat_appindicatortate.RunLedState = value;   // curecatstate.RunLedState = value;

    /*if(value == 0U)
        LED_off(gLedHandle[CONFIG_LED_RUN], 0);
    if(value == 1U)
        LED_on(gLedHandle[CONFIG_LED_RUN], 0);*/
}

void tiesc_setErrorLed(uint8_t value)
{
   // ethercat_appindicatortate.ErrLedState = value;   // curecatstate.ErrLedState = value;

    /*if(value == 0U)
        LED_off(gLedHandle[CONFIG_LED_ERROR], 0);
    if(value == 1U)
        LED_on(gLedHandle[CONFIG_LED_ERROR], 0);*/
}

void tiesc_getFoeFlashOffset(uint32_t *offset)
{
    *offset = (uint32_t)FOE_APPL_BIN_OFFSET;
}

int32_t tiesc_getArmInterruptOffset()
{
    PRUICSS_HwAttrs const *pruicssHwAttrs = PRUICSS_getAttrs(CONFIG_PRU_ICSS1);
    int32_t interruptOffset = 0;

    if(pruicssHwAttrs->instance == 0)
        interruptOffset = CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG0_PR1_HOST_INTR_PEND_0;
    else if(pruicssHwAttrs->instance == 1)
        interruptOffset = CSLR_R5FSS0_CORE0_INTR_PRU_ICSSG1_PR1_HOST_INTR_PEND_0;

    return interruptOffset;
}

int32_t tiesc_eepromRead(uint8_t *buf, uint32_t len)
{
    DebugP_log("%s Addr[%#x] len[%d] gEepromHandle[CONFIG_EEPROM0] [%#x] %" PRId64 " ms\r\n",__func__,I2C_EEPROM_DATA_OFFSET,len,gEepromHandle[CONFIG_EEPROM0],ClockP_getTimeUsec()/1000);

    if(Get_EepromAccess() != AppRET_OK) {
           return EepromReadError;
    }

    int32_t retVal;
    retVal = EEPROM_read(gEepromHandle[CONFIG_EEPROM0], I2C_EEPROM_DATA_OFFSET, buf, len);

    //custom code added
    Release_EepromAccess();

    DebugP_log("%sExit %" PRId64 " ms\r\n",__func__,ClockP_getTimeUsec()/1000);
    return retVal;
}

int32_t tiesc_eepromWrite(uint8_t *buf,uint32_t len)
{
    DebugP_log("%s\r\n",__func__);

    if(Get_EepromAccess() != AppRET_OK) {
              return EepromReadError;
    }

    int32_t retVal;
    retVal = EEPROM_write(gEepromHandle[CONFIG_EEPROM0], I2C_EEPROM_DATA_OFFSET, buf, len);

    //custom code added
    Release_EepromAccess();

    return retVal;
}

void tiesc_ethphyInit(PRUICSS_Handle pruIcssHandle, uint8_t phy0addr,
                     uint8_t phy1addr, uint8_t enhancedlink_enable)
{
    DebugP_log("%s: phy0addr[%d] phy1addr[%d] enhancedlink_enable[%d]\r\n",__func__,phy0addr,phy1addr,enhancedlink_enable);

    uint32_t mdioBaseAddress = ((const ETHPHY_Attrs *)ETHPHY_getAttrs(CONFIG_ETHPHY0))->mdioBaseAddress;

    //ETHPHY_DP83822_LedSourceConfig ledConfig;
    //ETHPHY_DP83822_LedBlinkRateConfig ledBlinkConfig;
    //ETHPHY_DP83822_FastLinkDownDetectionConfig fastLinkDownDetConfig;

    //ETHPHY_DP83822_Ecat_init();


    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_ENABLE_AUTO_MDIX, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_ENABLE_AUTO_MDIX, NULL, 0);


    if(enhancedlink_enable == 0)
    {
        MDIO_enableLinkInterrupt(mdioBaseAddress, 0, phy0addr, MDIO_LINKSEL_MDIO_MODE);
        MDIO_enableLinkInterrupt(mdioBaseAddress, 1, phy1addr, MDIO_LINKSEL_MDIO_MODE);
    }
    else
    {
        MDIO_enableLinkInterrupt(mdioBaseAddress, 0, phy0addr, MDIO_LINKSEL_MLINK_MODE);
        MDIO_enableLinkInterrupt(mdioBaseAddress, 1, phy1addr, MDIO_LINKSEL_MLINK_MODE);
    }

    /* Select MII mode */
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_ENABLE_MII, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_ENABLE_MII, NULL, 0);

    /* Disable 1G advertisement */
    //ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_DISABLE_1000M_ADVERTISEMENT, NULL, 0);
    //ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_DISABLE_1000M_ADVERTISEMENT, NULL, 0);

    /* Soft-reset PHY */
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_SOFT_RESTART, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_SOFT_RESTART, NULL, 0);

    ClockP_usleep(100000);

    //ONLY FOR TESTING DUMP
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_SET_TX_HALF_FULL_THRESHOLD_RGMII, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_SET_TX_HALF_FULL_THRESHOLD_RGMII, NULL, 0);

    ClockP_usleep(100000);

    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_GET_LINK_STATUS, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_GET_LINK_STATUS, NULL, 0);

}



void checkphylink(void)
{
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_GET_LINK_STATUS, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_GET_LINK_STATUS, NULL, 0);
}


#ifdef ICSSG0_INSTANCE
void tiesc_addOnBoardResetSequence()
{
    GPIO_setDirMode(CONFIG_GPIO_31_BASE_ADDR, CONFIG_GPIO_31_PIN, GPIO_DIRECTION_OUTPUT);
    GPIO_pinWriteHigh(CONFIG_GPIO_31_BASE_ADDR, CONFIG_GPIO_31_PIN);
    GPIO_setDirMode(CONFIG_GPIO_32_BASE_ADDR, CONFIG_GPIO_32_PIN, GPIO_DIRECTION_OUTPUT);
    GPIO_pinWriteHigh(CONFIG_GPIO_32_BASE_ADDR, CONFIG_GPIO_32_PIN);
    ClockP_usleep(1000);
    GPIO_pinWriteLow(CONFIG_GPIO_31_BASE_ADDR, CONFIG_GPIO_31_PIN);
    GPIO_pinWriteLow(CONFIG_GPIO_32_BASE_ADDR, CONFIG_GPIO_32_PIN);
    ClockP_usleep(1000);
    GPIO_pinWriteHigh(CONFIG_GPIO_31_BASE_ADDR, CONFIG_GPIO_31_PIN);
    GPIO_pinWriteHigh(CONFIG_GPIO_32_BASE_ADDR, CONFIG_GPIO_32_PIN);
    ClockP_usleep(1000);
}
#endif

void tiesc_ethphyEnablePowerDown()
{
#if CONFIG_PRU_ICSS1_CORE_CLK_FREQ_HZ == (333333333U)
    /*Update clock divider for MDIO according to 333 MHz PRU Core Clock*/
    /*FIXME: Fix cleanly by updating the MDIO_initClock API*/
    uint32_t mdioBaseAddress = ((const ETHPHY_Attrs *)ETHPHY_getAttrs(CONFIG_ETHPHY0))->mdioBaseAddress;
    HW_WR_REG32((mdioBaseAddress + CSL_MDIO_CONTROL_REG), (CSL_FMKT(MDIO_CONTROL_REG_ENABLE, YES) | CSL_FMK(MDIO_CONTROL_REG_CLKDIV, MDIO_CLK_DIV_CFG)));
#endif
    /* Ensure that PHY register access is working by checking the Identifier register */
    while(SystemP_SUCCESS != ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_VERIFY_IDENTIFIER_REGISTER, NULL, 0));
    while(SystemP_SUCCESS != ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_VERIFY_IDENTIFIER_REGISTER, NULL, 0));

#ifdef ICSSG0_INSTANCE
    /* Set Bit6 and Bit8 of DP83826E Auto-Negotiation Advertisemenmt register for PORT0 manually*/
    uint32_t mdioBaseAddress = ((const ETHPHY_Attrs *)ETHPHY_getAttrs(CONFIG_ETHPHY0))->mdioBaseAddress;
    int32_t status;
    uint16_t phyRegVal = 0;
    status = MDIO_phyRegRead(
                        mdioBaseAddress, 
                        NULL, 
                        ((const ETHPHY_Attrs *)ETHPHY_getAttrs(CONFIG_ETHPHY0))->phyAddress,  
                        DP83826E_AUTO_NEGOTIATION_ADVERTISEMENT_REG_ADDRESS, 
                        &phyRegVal);
    if(status == SystemP_SUCCESS)
    {
        status = MDIO_phyRegWrite(
                            mdioBaseAddress, 
                            NULL, 
                            ((const ETHPHY_Attrs *)ETHPHY_getAttrs(CONFIG_ETHPHY0))->phyAddress, 
                            DP83826E_AUTO_NEGOTIATION_ADVERTISEMENT_REG_ADDRESS, 
                            phyRegVal | 1<<6 | 1<<8);
    }
#endif
    /* Enable IEEE Power Down mode so that PHY does not establish any link */
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_ENABLE_IEEE_POWER_DOWN, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_ENABLE_IEEE_POWER_DOWN, NULL, 0);
}

void tiesc_ethphyDisablePowerDown()
{
    /* Disable IEEE Power Down mode so that PHY does not establish any link */
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY0], ETHPHY_CMD_DISABLE_IEEE_POWER_DOWN, NULL, 0);
    ETHPHY_command(gEthPhyHandle[CONFIG_ETHPHY1], ETHPHY_CMD_DISABLE_IEEE_POWER_DOWN, NULL, 0);
}
