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.

Linux/AM3358: Changing Ethernet active slave in U-boot



Hi,

We design a board with two ethernet-phy interfaces (eth0: Marvell 88E1518 in RGMII mode and eth1: DP83848 in RMII mode).

For now, I can only change the active slave at compile time in the devicetree.

By default,  I have ethact=ethernet@4a100000 and if I change it to either eth0 or eth1 with setenv it doesn't switch the port.

This is my config for now:

In the dts:

&mac {
  pinctrl-names = "default", "sleep";
  pinctrl-0 = <&cpsw_default>;
  pinctrl-1 = <&cpsw_sleep>;
  dual_emac;
  active_slave = <0>;
  status = "okay";
};

&davinci_mdio {
  pinctrl-names = "default", "sleep";
  pinctrl-0 = <&davinci_mdio_default>;
  pinctrl-1 = <&davinci_mdio_sleep>;
  status = "okay";
};

&cpsw_emac0 {
  phy_id = <&davinci_mdio>, <0>;
  phy-mode = "rgmii-txid";
  dual_emac_res_vlan = <1>;
};

&cpsw_emac1 {
  phy_id = <&davinci_mdio>, <1>;
  phy-mode = "rmii";
  dual_emac_res_vlan = <2>;
};

&phy_sel {
  rmii-clock-ext;
};

cpsw_default: cpsw_default {
    pinctrl-single,pins = <
      /* Slave 1 */
      0x114 (PIN_OUTPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE2) /* (J16) gmii1_txen.rgmii1_tctl */
      0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)                  /* (J17) gmii1_rxdv.rgmii1_rctl */
      0x11c (PIN_OUTPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE2) /* (J18) gmii1_txd3.rgmii1_td3 */
      0x120 (PIN_OUTPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE2) /* (K15) gmii1_txd2.rgmii1_td2 */
      0x124 (PIN_OUTPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE2) /* (K16) gmii1_txd1.rgmii1_td1 */
      0x128 (PIN_OUTPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE2) /* (K17) gmii1_txd0.rgmii1_td0 */
      0x12c (PIN_OUTPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE2) /* (K18) gmii1_txclk.rgmii1_tclk */
      0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)                  /* (L18) gmii1_rxclk.rgmii1_rclk */
      0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)                  /* (L17) gmii1_rxd3.rgmii1_rd3 */
      0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)                  /* (L16) gmii1_rxd2.rgmii1_rd2 */
      0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)                  /* (L15) gmii1_rxd1.rgmii1_rd1 */
      0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)                  /* (M16) gmii1_rxd0.rgmii1_rd0 */
      /* Slave 2 */
      0x64 (PIN_INPUT_PULLUP | MUX_MODE3)       /* (U16) gpmc_a9.rmii2_crs_dv */
      0x74 (PIN_INPUT_PULLUP | MUX_MODE3)       /* (U17) gpmc_wpn.rmii2_rxer */
      0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* (R13) gpmc_a0.rmii2_txen */
      0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* (V15) gpmc_a5.rmii2_txd0 */
      0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* (R14) gpmc_a4.rmii2_txd1 */
      0x6c (PIN_INPUT_PULLUP | MUX_MODE3)       /* (V17) gpmc_a11.rmii2_rxd0 */
      0x68 (PIN_INPUT_PULLUP | MUX_MODE3)       /* (T16) gpmc_a10.rmii2_rxd1 */
      0x108 (PIN_INPUT_PULLUP | MUX_MODE1)      /* (H16) mii1_col.rmii2_refclk */
    >;
  };

  cpsw_sleep: cpsw_sleep {
    pinctrl-single,pins = <
      /* Slave 1 reset value */
      0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      /* Slave 2 reset value */
      0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x74 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x108 (PIN_INPUT_PULLDOWN | MUX_MODE7)
    >;
  };

  davinci_mdio_default: davinci_mdio_default {
    pinctrl-single,pins = <
      /* MDIO */
      0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)  /* (M17) mdio_data.mdio_data */
      0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)                 /* (M18) mdio_clk.mdio_clk */
    >;
  };

  davinci_mdio_sleep: davinci_mdio_sleep {
    pinctrl-single,pins = <
      /* MDIO reset value */
      0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
      0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
    >;
  };

In the board.c:

static struct cpsw_slave_data cpsw_slaves[] = {
    {
        .slave_reg_ofs    = 0x208,
        .sliver_reg_ofs    = 0xd80,
        .phy_addr    = 0,
        .phy_if        = PHY_INTERFACE_MODE_RMII,
    },
    {
        .slave_reg_ofs    = 0x308,
        .sliver_reg_ofs    = 0xdc0,
        .phy_addr    = 1,
        .phy_if        = PHY_INTERFACE_MODE_RGMII,
    },
};

static struct cpsw_platform_data cpsw_data = {
    .mdio_base        = CPSW_MDIO_BASE,
    .cpsw_base        = CPSW_BASE,
    .mdio_div        = 0xff,
    .channels        = 8,
    .cpdma_reg_ofs        = 0x800,
    .slaves            = 2,
    .slave_data        = cpsw_slaves,
    .ale_reg_ofs        = 0xd00,
    .ale_entries        = 1024,
    .host_port_reg_ofs    = 0x108,
    .hw_stats_reg_ofs    = 0x900,
    .bd_ram_ofs        = 0x2000,
    .mac_control        = (1 << 5),
    .control        = cpsw_control,
    .host_port_num        = 0,
    .version        = CPSW_CTRL_VERSION_2,
};

int board_eth_init(bd_t *bis)
{
    int rv, n = 0;

#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
    (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))

#ifdef CONFIG_DRIVER_TI_CPSW
    // set eth0 in rgmii1 with internal delay
    writel((GMII1_SEL_RGMII | RGMII1_IDMODE), &cdev->miisel);
    // set eth1 in rmii2 with refclk2 as input
    writel((GMII2_SEL_RMII | RMII2_IO_CLK_EN), &cdev->miisel);
    }

    rv = cpsw_register(&cpsw_data);
    if (rv < 0)
        printf("Error %d registering CPSW switch\n", rv);
    else
        n += rv;
#endif

#endif
    return n;
}

In U-Boot:

When I compile U-boot with active_slave=<0>

=> mdio list
ethernet@4a100000:
0 - Generic PHY <--> ethernet@4a100000

When I compile U-boot with active_slave=<1>

=> mdio list
ethernet@4a100000:
1 - Generic PHY <--> ethernet@4a100000

=> mii info
PHY 0x00: OUI = 0x5043, Model = 0x1D, Rev = 0x01, 100baseT, HDX
PHY 0x01: OUI = 0x80017, Model = 0x09, Rev = 0x00,  10baseT, HDX

=> ping 192.168.0.1    
link up on port 1, speed 100, full duplex
Using ethernet@4a100000 device
host 192.168.0.1 is alive

Can somebody tell me why I can only change the active_slave at compile time and not with ethact or ethprime at runtime ? Am I missing something ?

I have few other questions since I am beginner for ethernet questions in u-boot:

- Should I be able to see both port when typing "mdio list" ?

- Is it possible to have an ip address for each port or do they share the same ip (ipaddr) ?

- Is it possible to have both port up and working at the same time ?

Thank you !

Loïc

  • Hi,

    The compile time choice of which port is correct, the active slave as you have noticed is the method used to select which port is used for connectivity.

    - Should I be able to see both port when typing "mdio list" ?

    Which TI SDK version are you using?

    - Is it possible to have an ip address for each port or do they share the same ip (ipaddr) ?

    Each port should have it's own MAC address and therefore would get it's own IP address.

    - Is it possible to have both port up and working at the same time ?

    Both ports active at the same time is not possible due to how u-boot is designed. Each driver is designed to be stateless which means for each network transaction the interface is completely initialized each time. There also is not any interrupt processing done in u-boot, it is a single threaded application. 

    Best Regards,

    Schuyler

  • Hi,

    Thank you for your answers !

    - We are not using u-boot from TI SDK, we are using mainline u-boot version 2018.11.

    So only the compile time is working to change the active slave ? I thought it was possible to change the active slave with ethact or ethprime at runtime.

    - I am able to see the 2 MAC address: ethaddr and eth1addr in my environment but I see only one environment variable for the ip address (ipaddr), If each port would get it's own ip shouldn't I get ipaddr1 for eth1addr ?

    Thank you !

    Loïc

    Schuyler Patton said:

    Hi,

    The compile time choice of which port is correct, the active slave as you have noticed is the method used to select which port is used for connectivity.

    - Should I be able to see both port when typing "mdio list" ?

    Which TI SDK version are you using?

    - Is it possible to have an ip address for each port or do they share the same ip (ipaddr) ?

    Each port should have it's own MAC address and therefore would get it's own IP address.

    - Is it possible to have both port up and working at the same time ?

    Both ports active at the same time is not possible due to how u-boot is designed. Each driver is designed to be stateless which means for each network transaction the interface is completely initialized each time. There also is not any interrupt processing done in u-boot, it is a single threaded application. 

    Best Regards,

    Schuyler

  • Hi,

    The only means currently to select the CPSW interface to be used is using the active_slave DT property that you are currently using at compile time. This might be different on other non TI platforms. To implement this feature of ethact or ethprime would require significant re-working of the CPSW u-boot driver to implement each port as a separate Ethernet interface. TI currently does not plan to add this capability.

    To answer your question on ip address, since only one port can be active due to U-Boot stateless design only one ip address is needed. 

    Best Regards,

    Schuyler