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.

TDA4VM: How to configure the rgmii port of the mcu on the linux side and set it to the non-auto-negotiation mode of mac to mac?

Part Number: TDA4VM

1. This is the block diagram of TDA4 and RTL9068 connection.

2.The sdk version is 8.6

3.  Modify the code as follows:

--- a/board-support/u-boot/arch/arm/dts/k3-j721s2-common-proc-board.dts

+++ b/board-support/u-boot/arch/arm/dts/k3-j721s2-common-proc-board.dts

@@ -363,20 +363,27 @@

 &mcu_cpsw {

        pinctrl-names = "default";

        pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;

 };

 

-&davinci_mdio {

-       phy0: ethernet-phy@0 {

-               reg = <0>;

-               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;

-               ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;

-               ti,min-output-impedance;

-       };

-};

+//&davinci_mdio {

+//     phy0: ethernet-phy@0 {

+//             reg = <0>;

+//             ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;

+//             ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;

+//             ti,min-output-impedance;

+//     };

+//};

 

 &cpsw_port1 {

        phy-mode = "rgmii-rxid";

-       phy-handle = <&phy0>;

+        fixed-link {

+             speed = <1000>;

+             full-duplex;

+        };

+//     phy-handle = <&phy0>;

 };

 

diff --git a/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts b/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts

index f0f475ea0..3ee13c666 100644

--- a/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts

+++ b/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts

@@ -609,20 +609,27 @@

 &mcu_cpsw {

        pinctrl-names = "default";

        pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;

 };

 

-&davinci_mdio {

-       phy0: ethernet-phy@0 {

-               reg = <0>;

-               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;

-               ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;

-               ti,min-output-impedance;

-       };

-};

+//&davinci_mdio {

+//     phy0: ethernet-phy@0 {

+//             reg = <0>;

+//             ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;

+//             ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;

+//             ti,min-output-impedance;

+//     };

+//};

 

 &cpsw_port1 {

        phy-mode = "rgmii-rxid";

-       phy-handle = <&phy0>;

+        fixed-link {

+              speed = <1000>;

+              full-duplex;

+        };

+//     phy-handle = <&phy0>;

 };

4.

Rtl9068 status:

GPIOA0~3 connected to the 9068 through the usbio adapter board has burned the 9068 firmware to the flash.

The 9068 uses the automatic startup scheme. The firmware driver is downloaded to the spi flash and starts by itself after being powered on. No need to write driver files.

5. Test situation:

Now 9068 and tda4 are connected in MAC-to-Mac mode. It is connected to the mcu rgmii1 port of tda4. At present, the txc of 9068 and the txc of tda4 are both 125M clocks.

In addition, rgmii adopts the non-auto-negotiation mode. However, what we see through ethtool is auto-negotiation mode, and it is not clear how to change it. As shown below:

6.How to configure the rgmii port of the mcu on the linux side and set it to the non-auto-negotiation mode of mac to mac?

  • Hi,

    currently modify the code as follows :

    Could you  help to check it ? Thank you very much

    --- a/board-support/u-boot/arch/arm/dts/k3-j721s2-common-proc-board.dts
    +++ b/board-support/u-boot/arch/arm/dts/k3-j721s2-common-proc-board.dts
    @@ -363,20 +363,27 @@
     &mcu_cpsw {
            pinctrl-names = "default";
            pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
     };
     
    -&davinci_mdio {
    -       phy0: ethernet-phy@0 {
    -               reg = <0>;
    -               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
    -               ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
    -               ti,min-output-impedance;
    -       };
    -};
    +//&davinci_mdio {
    +//     phy0: ethernet-phy@0 {
    +//             reg = <0>;
    +//             ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
    +//             ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
    +//             ti,min-output-impedance;
    +//     };
    +//};
     
     &cpsw_port1 {
            phy-mode = "rgmii-rxid";
    -       phy-handle = <&phy0>;
    +        fixed-link {
    +             speed = <1000>;
    +             full-duplex;
    +        };
    +//     phy-handle = <&phy0>;
     };
     
    diff --git a/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts b/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
    index f0f475ea0..3ee13c666 100644
    --- a/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
    +++ b/board-support/linux/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
    @@ -609,20 +609,27 @@
     &mcu_cpsw {
            pinctrl-names = "default";
            pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
     };
     
    -&davinci_mdio {
    -       phy0: ethernet-phy@0 {
    -               reg = <0>;
    -               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
    -               ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
    -               ti,min-output-impedance;
    -       };
    -};
    +//&davinci_mdio {
    +//     phy0: ethernet-phy@0 {
    +//             reg = <0>;
    +//             ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
    +//             ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
    +//             ti,min-output-impedance;
    +//     };
    +//};
     
     &cpsw_port1 {
            phy-mode = "rgmii-rxid";
    -       phy-handle = <&phy0>;
    +        fixed-link {
    +              speed = <1000>;
    +              full-duplex;
    +        };
    +//     phy-handle = <&phy0>;
     };
    

  • Hi,

    Could you  help to check it ? Thank you very much

    Above configuration is fine to keep PHY in Fixed Link mode.

    Can you run the same ethtool command on link partner side and share the output once.

    Best Regards,
    Sudheer

  • I tried to use phytool to read reg of rtl9068 but can not get out val.

    I found it can not call  davinci_mdio_read in davinci_mdio.c.

    Is there any problem with k3-j721s2-common-proc-board.dts  about mdio config  ?

    mdio bus  can be found in sys/bus 

    I also tried to use uboot mdio to read reg but failed.

    Is there anyother scheme to use mdio to read reg?

    The log 

    [    1.188612] deng davinci_mdio_probe
    [    1.188629] davinci_mdio 46000f00.mdio: Configuring MDIO in manual mode
    [    1.237605] davinci_mdio 46000f00.mdio: davinci mdio revision 9.7, bus freq 1000000
    [    1.246096] deng mdio probe mdiobus register and no phy
    [    1.246102] davinci_mdio 46000f00.mdio: phy[0]: device 46000f00.mdio:00, driver unknown
    [    1.259365] am65-cpsw-nuss 46000000.ethernet: initializing am65 cpsw nuss version 0x6BA02102, cpsw version 0x6BA82102 Ports: 2 quirks:00000000
    [    1.272248] am65-cpsw-nuss 46000000.ethernet: initialized cpsw ale version 1.4
    [    1.279459] am65-cpsw-nuss 46000000.ethernet: ALE Table size 64
    [    1.285799] am65-cpsw-nuss 46000000.ethernet: CPTS ver 0x4e8a010b, freq:500000000, add_val:1 pps:0
    [    1.296302] am65-cpts 310d0000.cpts: CPTS ver 0x4e8a010c, freq:200000000, add_val:4 pps:0
    [    1.406200] mmc0: CQHCI version 5.10

  • Hi,

    It is expected you can't read PHY registers via MDIO, as phy is in fixed link.
    MDIO is not having the PHY address to read/write via MDIO. Observe below prints.

    [ 1.246096] deng mdio probe mdiobus register and no phy
    [ 1.246102] davinci_mdio 46000f00.mdio: phy[0]: device 46000f00.mdio:00, driver unknown

    I think it will be default value showing as Auto-negotiation is enabled, But Auto-negotiation can't be triggered from SW as PHY is connected on Fixed Link mode.

    Best Regards,
    Sudheer

  • Please check the code above ,it is fixed link ,not Auto-negotiation. And Now tda4 switch and 9068 switch can ping each other .So the RGMII works well.

    Now we only want to use mdio bus  down load firmware for 9068.

    How can we read/write RTL9068 reg throw mdio?

    I think mac to mac mode has fixed phy to W/R reg.

    Can we abstracting the RTL9068 chip as fixed phy to w/r reg of RTL9068 throw mdio.

    Or there is other scheme to w/r RTL9068 throw mdio in mac to mac mode?

  • We have also try mdio-tool to read 9068 throw mdio ,but the tool can not install successfully.

    This tool can only be used in linux kernel version at last 5.6

  • Hi,

    Can we abstracting the RTL9068 chip as fixed phy to w/r reg of RTL9068 throw mdio.

    Yes, PHY is configured in Fixed-Link mode without PHY address. MDIO driver can't bind to PHY.

    We may not be able to read PHY registers in Fixed-link mode, until you register PHY with valid address.

    Best Regards,
    Sudheer

  • We have try to config fixed-link like this ,but can not work too.

    Can you show the example code to add phy in fixed-link mode?

  • We found fixed-link node can not use with  phy dev together.Is there any patch to fix this cpsw driver problem?

  • Hi,Doredla Sudheer Kumar

    Is there any guidance? thanks

  • Hi,

    Can the mdio module run independently from enet on the MCU side?

    How to achieve it?

  • Hi Liu,

    Sorry for the delay.

    It should be possible to run the MDIO module independently from MCU side, but do not have any reference example for this.

    It seems that you want to load the firmware for the phy from MDIO. Can you confirm this?

    Where is this firmware located, is it located inside the linux filesystem, or is it stored at some fixed memory location in some memory.

    Regards,
    Tanmay

    • #include "mdio_module.h"
      #include <app.h>
      #include <utils/console_io/include/app_log.h>
      
      #define CPSW_MDIO_OFFSET (0x00000f00U)
      
      #define CSL_MCU_CPSW0_NUSS_BASE (0x46000000U)
      
      #define CPSW_RD(offset) (*(uint32_t *)(CSL_MCU_CPSW0_NUSS_BASE + offset))
      
      void dump_regs(){
      appLogPrintf("MDIO_VERSION_REG = %x\n",CPSW_RD(0xf00));
      appLogPrintf("CONTROL_REG = %x\n",CPSW_RD(0xf04));
      appLogPrintf("ALIVE_REG = %x\n",CPSW_RD(0xf08));
      appLogPrintf("LINK_REG = %x\n",CPSW_RD(0xf0c));
      appLogPrintf("LINK_INT_RAW_REG = %x\n",CPSW_RD(0xf10));
      appLogPrintf("LINK_INT_MASKED_REG = %x\n",CPSW_RD(0xf14));
      appLogPrintf("LINK_INT_MASK_SET_REG = %x\n",CPSW_RD(0xf18));
      appLogPrintf("LINK_INT_MASK_CLEAR_REG = %x\n",CPSW_RD(0xf1c));
      appLogPrintf("USER_INT_RAW_REG = %x\n",CPSW_RD(0xf20));
      appLogPrintf("USER_INT_MASKED_REG = %x\n",CPSW_RD(0xf24));
      appLogPrintf("USER_INT_MASK_SET_REG = %x\n",CPSW_RD(0xf28));
      appLogPrintf("USER_INT_MASK_CLEAR_REG = %x\n",CPSW_RD(0xf2c));
      appLogPrintf("MANUAL_IF_REG = %x\n",CPSW_RD(0xf30));
      appLogPrintf("POLL_REG = %x\n",CPSW_RD(0xf34));
      appLogPrintf("POLL_EN_REG = %x\n",CPSW_RD(0xf38));
      appLogPrintf("CLAUS45_REG = %x\n",CPSW_RD(0xf3c));
      appLogPrintf("USER_ADDR0_REG = %x\n",CPSW_RD(0xf40));
      appLogPrintf("USER_ADDR1_REG = %x\n",CPSW_RD(0xf44));
      appLogPrintf("USER_ACCESS_REG_0 = %x\n",CPSW_RD(0xf80));
      appLogPrintf("USER_PHY_SEL_REG_0 = %x\n",CPSW_RD(0xf84));
      }
      
      
      
      Mdio_Cfg g_Mdio_Cfg;
      EnetMod_Obj g_mdio_obj = {
      .name = "cpsw2g.mdio",
      .physAddr = 0x46000f00U,
      .features = (ENET_FEAT_BASE |
      MDIO_FEATURE_CLAUSE45),
      .errata = ENET_ERRATA_NONE,
      .open = &Mdio_open,
      .rejoin = &Mdio_rejoin,
      .ioctl = &Mdio_ioctl,
      .close = &Mdio_close,
      };
      EnetMod_Handle g_h_mdio_mod = &g_mdio_obj;
      
      EnetOsal_Cfg g_osalCfg;
      
      EnetUtils_Cfg g_utilsCfg;
      
      Enet_IoctlPrms g_prms;
      
      
      void scan_phy(){
      int32_t status = 0;
      uint16_t val;
      EnetMdio_C22ReadInArgs inArgs;
      
      inArgs.group = 0;
      
      inArgs.reg = 0x01;
      appLogPrintf("wang Mdio_ioctl begin to read reg\n");
      
      for(uint32_t phyaddr=0;phyaddr<32;phyaddr ++){
      
      val = 0;
      inArgs.phyAddr=phyaddr;
      ENET_IOCTL_SET_INOUT_ARGS(&g_prms, &inArgs, &val);
      
      status = Mdio_ioctl(g_h_mdio_mod,ENET_MDIO_IOCTL_C22_READ,&g_prms);
      
      if(status != 0){
      appLogPrintf("wang Mdio_ioctl read reg failed,can not find phy at addr 0x%x\n",phyaddr);
      }
      else{
      appLogPrintf("wang Mdio_ioctl read 0x01 reg success,val is 0x%x, phyaddr is 0x%x\n",val,phyaddr);
      }
      appLogWaitMsecs(200U);
      
      }
      }
      
      void mdio_init_t()
      {
      
      Enet_initOsalCfg(&g_osalCfg);
      appLogPrintf("wang Enet_initUtilsCfg\n");
      
      Enet_initUtilsCfg(&g_utilsCfg);
      appLogPrintf("wang Enet_init\n");
      
      Enet_init(&g_osalCfg, &g_utilsCfg);
      
      appLogPrintf("wang Mdio_initCfg begin !!!!!!!\n");
      
      Mdio_initCfg(&g_Mdio_Cfg);
      
      g_Mdio_Cfg.mode = MDIO_MODE_NORMAL;
      
      
      appLogWaitMsecs(100u);
      
      appLogPrintf("wang Mdio begin to init physAddr 0x%x,CSL_MCU_CPSW0_NUSS_BASE_s is 0x%x,CPSW_MDIO_OFFSET_s is 0x%x \n",g_mdio_obj.physAddr,CSL_MCU_CPSW0_NUSS_BASE,CPSW_MDIO_OFFSET);
      
      appLogWaitMsecs(100u);
      
      g_h_mdio_mod->virtAddr = ((void *)(g_h_mdio_mod->physAddr));
      
      appLogWaitMsecs(100u);
      appLogPrintf("wang Mdio_init success,physAddr is 0x%x \n",g_h_mdio_mod->physAddr);
      }
      void mdio_open_t()
      {
      appLogPrintf("wang Mdio_open begin\n");
      
      int32_t status =0;
      status = Mdio_open(g_h_mdio_mod,ENET_CPSW_2G,0u,&g_Mdio_Cfg,sizeof(g_Mdio_Cfg));
      
      if(status != 0){
      appLogPrintf("wang Mdio_open return failed with status %d\n",status);
      }
      else
      {
      appLogPrintf("wang Mdio_open success end\n");
      }
      
      appLogWaitMsecs(100u);
      
      dump_regs();
      
      appLogWaitMsecs(100U);
      
      scan_phy();
      
      
      }
      void mdio_ioctl_t()
      {
      
      
      uint32_t phyAddr=0x18;
      bool isAlive=0;
      
      ENET_IOCTL_SET_INOUT_ARGS(&g_prms, &phyAddr, &isAlive);
      int32_t status = 0;
      status = Mdio_ioctl(g_h_mdio_mod,ENET_MDIO_IOCTL_IS_ALIVE, &g_prms);
      appLogPrintf("wang Mdio virt addr to phyaddr is 0x%x,virt addr is 0x%x,physAddr is 0x%x\n",(uint32_t*)(g_h_mdio_mod->virtAddr),*((uint32_t*)(g_h_mdio_mod->virtAddr)),g_h_mdio_mod->physAddr);
      
      if(status != 0){
      appLogPrintf("wang Mdio_ioctl failed with return %d\n",status);
      }
      else{
      appLogPrintf("wang Mdio_ioctl success,phyAddr=%x,isAlive=%d\n",phyAddr,isAlive);
      }
      
      
      appLogWaitMsecs(100u);
      
      bool islinked = 0;
      
      ENET_IOCTL_SET_INOUT_ARGS(&g_prms, &phyAddr, &islinked);
      
      status = Mdio_ioctl(g_h_mdio_mod,ENET_MDIO_IOCTL_IS_LINKED,&g_prms);
      
      if(status != 0){
      appLogPrintf("wang Mdio_ioctl failed with return %d\n",status);
      }
      else{
      appLogPrintf("wang Mdio_ioctl success,phyAddr=%x,islinked=%d\n",phyAddr,islinked);
      }
      
      
    • 171  uint32_t  CSL_MDIO_phyRegRead2(CSL_mdioHandle hMdioRegs,
      172                      uint32_t userGroup,
      173                      uint32_t phyAddr,
      174                      uint32_t regNum,
      175                      uint16_t *pData)
      176  {
      177      uint32_t regVal = 0U;
      178      uint32_t ret_val = 0U;
      179  
      180      /* Wait till transaction completion if any */
      181      while(CSL_MDIO_USER_GROUP_USER_ACCESS_REG_GO_EN_0x1 ==
      182  		  CSL_FEXT(hMdioRegs->USER_GROUP[userGroup].USER_ACCESS_REG,
      183                   MDIO_USER_GROUP_USER_ACCESS_REG_GO))
      184      {}
      185      CSL_FINS(regVal, MDIO_USER_GROUP_USER_ACCESS_REG_GO, CSL_MDIO_USER_GROUP_USER_ACCESS_REG_GO_EN_0x1);
      186      CSL_FINS(regVal, MDIO_USER_GROUP_USER_ACCESS_REG_WRITE, CSL_MDIO_USER_GROUP_USER_ACCESS_REG_READ);
      187      CSL_FINS(regVal, MDIO_USER_GROUP_USER_ACCESS_REG_PHYADR, phyAddr);
      188      CSL_FINS(regVal, MDIO_USER_GROUP_USER_ACCESS_REG_REGADR, regNum);
      189      CSL_REG_WR(&hMdioRegs->USER_GROUP[userGroup].USER_ACCESS_REG, regVal);
      190  
      191      /* wait for command completion */
      192      while(CSL_MDIO_USER_GROUP_USER_ACCESS_REG_GO_EN_0x1 ==
      193  		  CSL_FEXT(hMdioRegs->USER_GROUP[userGroup].USER_ACCESS_REG,
      194                   MDIO_USER_GROUP_USER_ACCESS_REG_GO))
      195      {}
      196  
      197      /* Store the data if the read is acknowledged */
      198      if(CSL_MDIO_USER_GROUP_USER_ACCESS_REG_ACK_PASS ==
      199          CSL_FEXT(hMdioRegs->USER_GROUP[userGroup].USER_ACCESS_REG,
      200          MDIO_USER_GROUP_USER_ACCESS_REG_ACK))
      201      {
      202          *pData = (uint16_t)(CSL_FEXT(hMdioRegs->USER_GROUP[userGroup].USER_ACCESS_REG,
      203              MDIO_USER_GROUP_USER_ACCESS_REG_DATA));
      204          ret_val = (uint32_t)TRUE;
      205      }
      206      else
      207      {
      208          ret_val = (uint32_t)FALSE;
      209      }
      210  
      211      return(ret_val);
      212  }
    • I try to use mdio like this,mdio_init  mdio_open and dump_reg is ok ,but ioctl  stuck in scan phy ,I find  cmds of ioctl is ok  except  cmd about c22 and c45  .And I find the link_reg and alive reg is 0. Is there something wrong with my code? any config is wrong with mdio or need any other config of mdio?

    for the firmware ,i plan to use linux filesystem and throw ipc to control mcu to control mdio to w/r, is there any better plan to do this?

    the reg dump result:

  • Hi,

    You won't be able use MDIO module (MDIO_USER_GROUP_USER_ACCESS_REG) to read/write on MDIO. This is beacuase, the MDIO is being configured in manual mode by linux MDIO driver, which uses bit-banging for MDIO read/write instead of the MDIO_USER_GROUP_USER_ACCESS_REG register.

    The manual mode is used in linux driver because of the errata i2329. So if you want to hack MDIO from mcu cores, you can see the function "Mdio_manualModePhyRegRead22" in pdk/packages/ti/drv/enet/src/mod/mdio.c as a reference.

    Regards,
    Tanmay

  • we have try this mode also ,it will call Mdio_manualModePhyRegRead22/Mdio_manualModePhyRegWrite22 func ,but still stuck.Is any code of my demo wrong?

    logs:

  • Hi,

    I am not getting where is the code stuck? Is it able to read at least the phy id registers (0x2, 0x3)?

    Also, I discussed this with my colleagues and they presented an idea to do this in the u-boot Let me know if you are interested in this solution. This has been tried before with different phy. You can see the patches for this here : 

    We can also do something similar.

    Let me know which way do you prefer.

    Regards,
    Tanmay

  • it stuck in this:    

     status = Mdio_ioctlManualMode(g_h_mdio_mod,ENET_MDIO_IOCTL_IS_ALIVE, &g_prms); 

    and this will call Mdio_manualModePhyRegRead22  and stuck in it.

    by the way,i think the patches is useless because we need to implement mdio_read/mdio_write func  of rtl sdk to flush firmware.The flush logic is controled by sdk and it contains parse binary file logic we can not modify it.

  • Hi,

    status = Mdio_ioctlManualMode(g_h_mdio_mod,ENET_MDIO_IOCTL_IS_ALIVE, &g_prms); 

    Are you sure that the phy is out of reset for this?

    by the way,i think the patches is useless because we need to implement mdio_read/mdio_write func  of rtl sdk to flash firmware.The flash logic is controled by sdk.

    So this will use the read/write functioned implemented by the mdio driver in the u-boot (you will be using the normal phy mode in u-boot). You can use the phy-driver in uboot to write the firmware to the phy. Then when you boot into the linux kernel, you can configure the link in fixed link and use the ethernet interface normally.

    By the way, does Realtek have a suggestion on how to flash the firmware with linux? like a driver? They might also have solution available for this. So please check with them if you haven't already.

    Regards,
    Tanmay