This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DP83TC814S-Q1: Standby and Normal Mode configurations for ETH

Part Number: DP83TC814S-Q1

Hello, I was working on the configurations for standby and normal mode.

Whenever I try to configure the device into standby mode I follow these steps:

// Write to register 0x1F bit[7] -> 1. (direct access)
// Write LPS_CFG3 register 0x18C to 0x0010 which is equals to '10000b'. (MMD1F access)
// Read LPS_STATUS register 0x18E to check the status of ETH PHY (MMD1F access)
// Untill the readback operation is successfull, try to set the configuration registers.
At the code snippet below you can find the operations. I believe the register read and write operations are working pretty well
void BusSleepMode::ConfigureETHPhytoStandbyMode(void)
{
    uint16_t registerData = 1U;
    registerData = registerData<<7U;
    if(WRITE_STATUS_OK == Phy_write_register(0x1FU, registerData))
    {
        // Readback the register to check operation is successful or not.
        if(READ_STATUS_OK == Phy_read_register(0x1FU, &registerData))
        {
            if(1U == ((registerData>>7U) & 0x0001U ))
            {
                LOGI(&gETHNM_Log_ctx, "Write operation is successful for 0x1F");
                while(contextInstanceSM.getETHPhyResetStatus() == false)
                {
                    // Write to 0x18C '10000b' which is equal to 0x10
                    static_cast<void>(MMD1F_write_register(0x18CU, 0x0010U));
                    uint16_t readBack;

                    static_cast<void>(MMD1F_read_register(0x18EU, &readBack));

                    LOGD(&gETHNM_Log_ctx, "READBACK FOR STANDBY: ", readBack);
                    if(1U == ((readBack>>1U) & 0x0001U))
                    {
                        contextInstanceSM.setETHPhyResetConfigurationFlag();
                        LOGI(&gETHNM_Log_ctx, "Standby configuration is made. PHY is running in reset mode now.");
                        break;
                    }
                    else
                    {
                        LOGE(&gETHNM_Log_ctx, "Standby configuration is failed.");
                    }
                    std::this_thread::sleep_for(std::chrono::milliseconds(10));
                }
            }
        }
    }
    else
    {
        LOGE(&gETHNM_Log_ctx, "Write register to 0x1F returned fail.");
    }
    

}
For the normal mode configuration I follow these steps basically:
// Write to register 0x1F bit[7] -> 0.
// Write LPS_CFG3 register 0x18C to 0x0001 which is equals to '1b'.
// Read LPS_STATUS register 0x18E to check the status of ETH PHY
// Untill the status is expected, try to set.
void NetworkMode::ConfigureETHPhytoNormalMode(void)
{
    uint16_t registerData = 0U;
    registerData = registerData<<7U;
    if(true == contextInstanceSM.getETHPhyResetStatus())
    {
        // Clear out the register data.
        if( WRITE_STATUS_OK == Phy_write_register(0x1FU, registerData))
        {
            if(READ_STATUS_OK == Phy_read_register(0x1FU, &registerData))
            {
                if(0U == ((registerData>>7U) & 0x0001U ))
                {
                    LOGI(&gETHNM_Log_ctx, "Read operation is successful for 0x1F. Bit is cleared.");
                    while(contextInstanceSM.getETHPhyResetStatus() == true)
                    {
                        // Write 0x18C to '1b' to set the normal mode.
                        static_cast<void>(MMD1F_write_register(0x18CU, 0x0001U));

                        uint16_t readBack;
                        static_cast<void>(MMD1F_read_register(0x18EU, &readBack));
                        
                        LOGD(&gETHNM_Log_ctx, "READBACK FOR NORMAL: ", readBack);
                        
                        if(1U == ((readBack>>2U) & 0x0001U))
                        {
                            contextInstanceSM.clearETHPhyResetConfigurationFlag();
                            LOGI(&gETHNM_Log_ctx, "Reset configuration is cleared. PHY is running in normal mode.");
                            break;
                        }
                        else
                        {
                            LOGE(&gETHNM_Log_ctx, "Reset configuration is failed.");
                        }
                        std::this_thread::sleep_for(std::chrono::milliseconds(10));
                    }
                }
            }
        }
        else
        {
            LOGE(&gETHNM_Log_ctx, "Write register to 0x1F returned fail.");
        }
        // Set the link status up by using ioctl functions
        changeLinkStatus("eth0");
        changeLinkStatus("vlan1");
    }
}
After these configurations, whenever I switched into the normal mode, I cannot send the data for 2 seconds.
Are these configurations correct or should I have to check somewhere else?
BR,
Alpay
  • Hi Alpay,

    Please let me review your comments and update you.

    Regards,
    Rahul

  • Thank you Rahul,

    I have also tried to set it for reset mode by setting the pin 14 and 15 as the seperate trials but the state didnt change. It still sends frame after 2 seconds from configuration.

  • Hi Alpay,

    If the PHY is in normal mode and in autonomous operation, the PHY will automatically try to establish a link with a valid Link Partner once POR is complete.

    Are you noticing link drop or link establishment after changing from Standby to Normal mode ?

    After these configurations, whenever I switched into the normal mode, I cannot send the data for 2 seconds.

    Are you changing from Standby mode to Normal mode ?

    Regards,
    Rahul

  • Hi Rahul,

    After going into standby mode, I have observed that link status has been changed as not active and all the sending operations are suspended on the physical interface and for the normal mode configuration it has been changed to link up status and after 2 seconds by going into normal it starts to send frames. Taking 2 seconds for every time is strange case. Also I should have inform you about this, currently I am using vlan interface. I am not sure using vlan is effecting something.

    I am observing this situation after changing the mode from standby to normal mode.

  • Also I forgot to say that, when I read the 0x18B register via the MMD1F method, the output of this register is 0. I think this indicates the autonomous operation is not enabled since there is no explanation for the register. 

  • Hi Alpay,

    Please let me check with my team on more details and get back to you.

    Can you try to check this by disabling VLAN tag and any improvements are noticed ?

    Regards,
    Rahul

  • static bool checkMediaStatus(void)
    {
        const char *ifName = "fec0";
        int sockFd = socket(AF_INET, SOCK_DGRAM, 0);
        bool retVal = false;  
        if( sockFd != -1)
        {
            struct ifmediareq ifmr;
            strncpy(ifmr.ifm_name, ifName, sizeof(ifName));
            if( -1 == ioctl(sockFd, SIOCGIFMEDIA, &ifmr))
            {
                LOGE(&gETHNM_Log_ctx, "Failed to get media status");
            }
            else
            {
                if(ifmr.ifm_status & IFM_ACTIVE)
                {
                    LOGI(&gETHNM_Log_ctx, "Link is established. Checked by media status");
                    retVal = true;
                }
                else
                {
                    LOGE(&gETHNM_Log_ctx, "Link is not established. Checked by media status.");
                }
                close(sockFd);
            }
        }
        else
        {
            LOGE(&gETHNM_Log_ctx, "Failed to open socket");
        }
        return retVal;
    }

    I also tried the check method for gathering the media status after changing link status. 

    Also if you want to look to change link status part I am adding that part too.

    static void changeLinkStatus(void)
    {
        int sockfd;
        
        // Ethernet interface name
        std::string interfaceName = "fec0";
    
        // Socket creation
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0) {
            LOGE(&gETHNM_Log_ctx, "Socket is not created", static_cast<const char *>(strerror(errno)));
        }
        else
        {
            struct ifreq ifr;
    
            // Copy the interface name
            static_cast<void>(strncpy(ifr.ifr_name, interfaceName.c_str(), sizeof(interfaceName.c_str())));
    
            // Get the link status 
            if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1) {
                LOGE(&gETHNM_Log_ctx, "ioctl error", static_cast<const char *>(strerror(errno)));
                // In case of error close the socket
                static_cast<void>(close(sockfd));
            }
            else
            {
                // Set the interface link status to UP
                ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
                
                // Set the new interface link status by ioctl
                if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1) {
                    LOGE(&gETHNM_Log_ctx, "ioctl error", static_cast<const char *>(strerror(errno)));
                    // In case of error close the socket
                    static_cast<void>(close(sockfd));
                }
                else
                {
                    LOGI(&gETHNM_Log_ctx, "Link status is set to UP");
                    // Close socket after successfull operation
                    static_cast<void>(close(sockfd));
                }
            }
        }
    }

    After configuring the normal mode checkMediaStatus function returns false for 2 seconds. Also I have tried the disable the vlan interface and sending frames from physical interface but that situation did not change anything.

  • Thank you Alpay, for testing it and sharing your feedback. Please give me time till end of this week to check with my colleagues and update you.

    Regards,
    Rahul

  • Hi Alpay,

    What is the PHY in when powered on is it in Master/ slave mode ?

    If the PHY is in Master mode, the PHY should automatically enter into standby mode post power-up and reset so long that all supplies are available and the device is bootstrapped for managed operation.

    What mode is the PHY bootstrapped in by default autonomous or managed mode ?

    I am trying to understand how you device state is when powering up and what is the test case being evaluated here.

    Regards,
    Rahul

  • Hi Rahul,

    I have tried to read the configuration for the master slave options by checking 2 registers below:

    static void checkMasterSlaveConfiguration(void)
    {
        uint16_t masterSlaveData;
    
        MMD1F_read_register(0x0834U, &masterSlaveData);
        if(masterSlaveData & 0x4000)
        {
            LOGI(&gETHNM_Log_ctx,"Master configuration bit is set.");
        }
        else
        {
            LOGI(&gETHNM_Log_ctx,"Slave configuration bit is set.");
        }
    }
    
    static void checkLED0Configuration(void)
    {
        uint16_t led0Data;
        // Read the data at 0x450h
        MMD1F_read_register(0x450U, &led0Data);
        // Condition 0100b
        if( led0Data & 0x0004U)
        {
            LOGI(&gETHNM_Log_ctx,"LED_0 Status: link OK + 100Base-T1 Master");
        }
        // Condition 0101b
        else if( led0Data & 0x0005U)
        {
            LOGI(&gETHNM_Log_ctx,"LED_0 Status: link OK + 100Base-T1 Slave");
        }
    }

    checkMasterSlaveConfiguration function output is printed out and it says it is configured as slave. I have checked to datasheet chapter 8.4.5.1 It says MMD1_PMA_CTRL_2 Register (Address 0x1834) bit [14] indicates the master or slave mode configuration and LED_0 controls the bootstrap configuration. LED_0 else case is printed out as 9744 which means bits [3-0] are zero and it indicates that link OK situation. 

    I have performed these operations before going into standby mode and before configuring it to normal mode.

    Also I have checked mode before configuring the standby and normal mode by the code snippet below.

    static void checkMode(void)
    {
        uint16_t readMode;
    
        MMD1F_read_register(0x18EU, &readMode);
        // Standby 10b -> 0x0002
        if( readMode & 0x0002U)
        {
            LOGI(&gETHNM_Log_ctx,"Mode is set to standby.");
        }
        else if( readMode & 0x0004U)
        {
            LOGI(&gETHNM_Log_ctx,"Mode is set to normal.");
        }
    }

    Before going into standby mode is set to normal. After configuring it to standby it can be seen as standby mode. It double checks the situation about 100Base-T1 slave configuration. 

  • Hi Alpay,

    I hope this software implementation guide will help:

    https://www.ti.com/lit/an/snla404/snla404.pdf?ts=1691170196909

    The flowcharts in this appnote should help with your code implementation.

    Regards,
    Rahul

  • I have performed the steps which they are described in the Software Implementation Guide, but unfortunately it didnt have effect. 

    Code snippet is down below:

    // Trials for speed up.
    struct dp83812_init_reg {
    	int	reg;
    	int	val;
    };
    // Init optimization configuration for DP83TC814 which are taken from the linux driver of TI.
    static const struct dp83812_init_reg dp83812_slave_cs2_0_init[] = {
        {0x523, 0x0001}, // Disable link up
        {0x834, 0x0001}, // Configure to slave mode
    	{0x873, 0x0821}, // Configuration to enable shorter linkup time
    	{0x896, 0x22ff}, // Configuration to enable shorter linkup time
    	{0x89E, 0x0000}, // Configuration to enable shorter linkup time
    	{0x523, 0x0000}, // Enable Link up
    };
    
    /**
     * Initialization of TI DP83TC811 BroadR-Reach PHY.
     *
     * @param   mx6q   Pointer to device data structure.
     * @return  Execution status.
     */
    static int mx6q_ti_dp83tc811_phy_init(mx6q_dev_t *mx6q)
    {
        int phy_addr;
        int timeout;
        uint16_t phy_data;
    
        if (mx6q->cfg.verbose > 3) {
            log(LOG_INFO, "%s()...", __FUNCTION__);
            /* Read strap configuration */
            phy_data = mmd_read_reg(mx6q, 0x1F, 0x45D);
            log(LOG_ERR, " CHIP_SOR_1(0x45D) = 0x%X", phy_data);
        }
    
        phy_addr = mx6q->cfg.phy_addr;
        // Go into managed mode.
        mmd_write_reg(mx6q, 0x1F, 0x18B, 0x0000);
    
        // Calculate the size of the array
        size_t sizeOfSlaveConfig = sizeof(dp83812_slave_cs2_0_init) / sizeof(dp83812_slave_cs2_0_init[0]);
        // Write the optimization parameters to the slave config
        for(int i = 0; i < sizeOfSlaveConfig; i++)
        {
            mmd_write_reg(mx6q, 0x1F, dp83812_slave_cs2_0_init[i].reg, dp83812_slave_cs2_0_init[i].val);
            log(LOG_ERR,">>>> WRITING TO 0x%X VAL 0x%X\n", dp83812_slave_cs2_0_init[i].reg, dp83812_slave_cs2_0_init[i].val);
        }
    
        /* Autonomous mode */
        mmd_write_reg(mx6q, 0x1F, 0x18B, 0x0040);
        /* 10ms delay inspired by TI DP83TC81x linux driver */
        nic_delay(10);
        /* Soft reset */
        mx6q_mii_write(mx6q, phy_addr, 0x1F, 0x4000);
    	/* Read BMSR Register 0x0001 – Basic Mode Status Register */
    	phy_data = mx6q_mii_read(mx6q, phy_addr, 0x1);
        if ((phy_data & BMSR_LINK_STATUS) != BMSR_LINK_STATUS) {
            log(LOG_ERR, "%s(): PHY link not established", __FUNCTION__);
            return -1;
        }
        
        return 0;
    
    }

    I have checked out the linux driver code which I downloaded from here. According to snla389a I had these configurations as slave mode configuration. They were convenient for each other. After the necessary configurations I have set it to autonomous mode and soft resetted at the initialization phase of the phy.

    Now I wonder that the carrier status of this chip is coming 2 seconds after changing it to normal mode even though the link status is set to up. 

  • Hi Alpay,

    I would recommend to use the attached Linux driver for 814:
    dp83tc812.c

    Which xMII interface are you using ? The MDI side of the PHY determines the link status, the carrier status (on the SoC side) can be determined by MII.

    As PHY supports only 100mbps, may be it is taking time for the SoC to configure ? The attached driver forces the speed of the PHY to 100mbps.

    Regards,
    Rahul

  • Whenever I tried to switch mode to master mode, the ethernet phy did not send any message. Is this related with the SoC configuration? I assume it is but I am not pretty sure. As at the below I have summarized up what I have been done totally. 

  • Please ignore the note which is written for master slave configuration, I have resolved that issue.

  • Thank you Alpay for sharing the summary, please let me go over it and update you.

    Regards,
    Rahul