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.

lan8720 PHY on XAM3359 through RMII

Hi,

I'm trying to get a ping out from u-boot on a custom board I'm working on. This board is very similar to the beaglebone, the difference being that our board uses a lan8720 PHY on RMII with PHY_ID 1 while they have a lan8710 on MII with PHY_ID 0.

I adjusted the u-boot-ti/master branch to account for hardware modifications with this set of patches [2]. Basically, I configure the gmii_sel register properly (enable RMII1 and disables the rest, source clock from chip's PLL [I'm aware of Silicon Errata Advisory 1.0.16 and we are working on installing an external oscillator], adjust PHY_ADDR to 1, and adjust the pinmux).

With this setup, I can't see anything coming up on the remote interface. To pinpoint the issue, I added the ethloop command found here[3] to u-boot and tested with both mac (digital loop, bit 1 in the MACCONTROL register) and phy (bit 14 in the MII register 0) loops enabled. The mac loop worked, while the phy loop failed, which seems to point to an issue with the RMII bus. I did some probing on the board, and couldn't observe any signal on any of the TX pins (TXEN, TXD0 or TXD1). I though maybe it could have been a hardware issue, but I was able to configure the pins as GPIOs and toggle them.

Did I miss a configuration step? Is there anything else that could prevent data from being sent on the RMII interface? I understand that the silicon errata influences the RX side and therefore prevent a succesful ping (ARP reply might not be received properly), but still, wireshark on the other end of the cable should see the ARP request coming in.

[1] http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/16382

[2]

--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -42,8 +42,13 @@ static struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE;
 static struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE;
 #endif
 
 /* MII mode defines */
 #define MII_MODE_ENABLE        0x0
+#define RMII_MODE_ENABLE    0x3D
 #define RGMII_MODE_ENABLE    0x3A
 
 /* GPIO that controls power to DDR on EVM-SK */

@@ -409,6 +430,10 @@ int board_eth_init(bd_t *bis)
         writel(MII_MODE_ENABLE, &cdev->miisel);
         cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
                 PHY_INTERFACE_MODE_MII;
+    } else if (board_is_MYBOARD()) {
+        writel(RMII_MODE_ENABLE, &cdev->miisel);
+        cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
+                PHY_INTERFACE_MODE_RMII;
     } else {
         writel(RGMII_MODE_ENABLE, &cdev->miisel);
         cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
--- a/board/ti/am335x/mux.c
+++ b/board/ti/am335x/mux.c
@@ -152,6 +152,20 @@ static struct module_pin_mux rgmii1_pin_mux[] = {
     {-1},
 };
 
+static struct module_pin_mux rmii1_pin_mux[] = {
+    {OFFSET(mii1_rxd0), MODE(1) | RXACTIVE},    /* RMII1_RXD0 */
+    {OFFSET(mii1_rxd1), MODE(1) | RXACTIVE},    /* RMII1_RXD1 */
+    {OFFSET(mii1_rxerr), MODE(1) | RXACTIVE},    /* RMII1_RXERR */
+    {OFFSET(mii1_txen), MODE(1)},            /* RMII1_TXEN */
+    {OFFSET(mii1_txd0), MODE(1)},            /* RMII1_TXD0 */
+    {OFFSET(mii1_txd1), MODE(1)},            /* RMII1_TXD1 */
+    {OFFSET(mii1_crs), MODE(1) | RXACTIVE},        /* RMII1_CRS_DV */
+    {OFFSET(rmii1_refclk), MODE(0)},        /* RMII1_REFCLK */
+    {OFFSET(mdio_data), MODE(0) | RXACTIVE | PULLUP_EN},/* MDIO_DATA */
+    {OFFSET(mdio_clk), MODE(0) | PULLUP_EN},    /* MDIO_CLK */
+    {-1},
+};
+
 static struct module_pin_mux mii1_pin_mux[] = {
     {OFFSET(mii1_rxerr), MODE(0) | RXACTIVE},    /* MII1_RXERR */
     {OFFSET(mii1_txen), MODE(0)},            /* MII1_TXEN */
@@ -303,7 +317,11 @@ void enable_board_pin_mux(struct am335x_baseboard_id *header)
         configure_module_pin_mux(i2c1_pin_mux);
         configure_module_pin_mux(mii1_pin_mux);
         configure_module_pin_mux(mmc0_pin_mux);
-        configure_module_pin_mux(mmc1_pin_mux);
+    } else if (!strncmp(header->name, "MYBOARD", HDR_NAME_LEN)) {
+        configure_module_pin_mux(i2c1_pin_mux);
+        configure_module_pin_mux(rmii1_pin_mux);
+        configure_module_pin_mux(mmc0_pin_mux_sk_evm);
     } else {
         puts("Unknown board, cannot configure pinmux.");
         hang();
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -301,7 +303,7 @@
 #define CONFIG_NET_MULTI
 #define CONFIG_PHY_GIGE
 #define CONFIG_PHYLIB
-#define CONFIG_PHY_ADDR            0
+#define CONFIG_PHY_ADDR            1
 #define CONFIG_PHY_SMSC
 
 #define CONFIG_NAND

[3] http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/16382

Thanks,

--

Nicolas Calderon

  • Just as a follow up, we installed the external oscillator, reconfigured the rmii1_refclk pin as an input and changed the value in gmii_sel to source the rmii clock from the pin rather than the pll

    From the above patch, this was modified:

    #define RMII_MODE_ENABLE    0x3D

    {OFFSET(rmii1_refclk), MODE(0) | RXACTIVE},        /* RMII1_REFCLK */

    I'm still puzzled as to how the rx reference clock interfered with the transmit side of the mac. I took a quick look at the RMII spec and didn't see any mechanism that would do that...

  • Nicholas,

    Can I assume fixing the clock resolved your issue?

    Keep in mind that both the RMII PHY and the AM device share this clock...it's not just used for RMII_RX.

  • Fixing the clock indeed solved my issue.

    I had delayed installing the external clock source as reports here described unstable links, not the complete silence I observed. Anyway, everything is running fine now.

    Are there any updates planned for the documentation? The fact that it is only mentionned in the silicon errata seems like more people will be trying to use this feature in the future.

  • Thanks for the feedback Nicolas.

    RMII_REFCLK is used to synchronize all RMII signals (PHY and EMAC), so how the failure manifests itself can vary.

    As for your comment about updating the documentation, we are actively looking for ways to ease the implementation of our devices for our customers.  Yours is an excellent example and has spurred internal discussions on how we can better balance the information provided across several document formats (TRM, Errata, Datasheet, etc.) without deviating too far from the intended use of the document itself.

  • If you don't mind, I'd like to ask a clarification.  In the original post, the patch shows the following:

    #define RMII_MODE_ENABLE 0x3D

    However, you mentioned that you modified that line, but in fact it was the same.

    I just wanted to verify that 0x3D was indeed the value that worked for you (I am trying to do the same thing as you, but with the 8710 and I'm having repeated "wait_for_user_access Timeout" messages in u-boot).  I do have an external 50MHz oscillator on board.

  • RMII_MODE_ENABLE was indeed modified, and the information I provided is incorrect (paste mistake).

    The correct value is:

    #define RMII_MODE_ENABLE 0xFD

    The documentation of rmii1_io_clk_en is a bit confusing as you have to read it from the perspective of the MAC core. So here, you want to get the clock that comes from the pin, and not the PLL.

    Let me know if that helped.

  • If you use a LAN8710 in RMII mode, you will need to provide a external low jitter 50 MHz RMII LVCMOS reference clock to both LAN8710 and AM335x.

    If you use a LAN8720 which only needs a 25 MHz crystal, it can source the 50 MHz RMII reference clock to AM335x.

    I assume a LAN8720 and crystal will be a lower cost option than a LAN8710 and 50 MHz LVCMOS oscillator.

    Regards,
    Paul

  • FYI, I adjusted our board to LAN8720A recently and now it has intermittent issues using Ethernet.  I scanned through some documents and noted that SMSC says, when using the external crystal, that the output clock is no longer compliant with the RMII specification.

    Has anyone had good success with LAN8720A and external crystal with REFCLK OUT enabled?  I am testing by booting to an NFS RFS, and half the time the kernel crashes when loading udev due to buggy NFS/Ethernet behavior.

    I tried a dirty patch to add some series resistors, but it doesn't seem to resolve the problem.  Do I just need to add some series resistors?  Trying to decide if I need to go back to an RC oscillator just to ensure it works...

  • Several months ago we modified a couple of boards to use LAN8720 in REF_CLK out mode and it worked as expected.  However, we did not test for compliance to the RMII specification.

    I want to make sure I'm clear on your previous comment. Has SMSC stated their device is not compliant to the RMII specification when using the internal oscillator with an external 25MHz crystal?   If so, can you point us to the document from SMSC that describes this issue.

    I also do not understand your reference to RC oscillator.  An RC oscillator circuit which uses an RC network, a combination of resistors and capacitors, will not be able to provide a clock source with the required frequency accuracy/stability.

    You should be able to use an external low jitter 50MHz crystal based clock source to generate the RMII reference clock to both AM335x and LAN8720 devices.

    Regards,
    Paul 

  • Yes, SMSC mentions that the REFCLKO function is not part of the RMII specification and is not compliant with the specification.  Please see their Schematic Checklist LAN8720 QFN Rev. D:

    https://www2.smsc.com/mkt/web_lancheck.nsf/4f053dac450fdcfb85256d4e004d8a2b/65dd662fd7c9c80785257738006950ac/$FILE/Schematic%20Checklist%20LAN8720%20QFN%20Rev%20D.pdf

    When I say RC oscillator, I meant ceramic (non-crystal) oscillator.  This is the required option to get 50MHz clock to both CPU and LAN8710, since it can't take a 50MHz crystal.

  • The RMII specification says the minimum setup time should be 4ns and the minimum hold time should be 2ns.

    When operating in REF_CLK out mode, the LAN8720 source can change the RXD[1:0], RXER, and CRS_DV signals going to the AM335x as early as 1.4ns after the rising edge of clock and as late as 5.0ns after the rising edge of clock.  If you route these signals to AM335x such they are the same length as REF_CLK, the LAN8720 would violate the AM335x input hold time by 0.6ns since AM335x meets the RMII specification with a min hold time of 2ns.

    The note in the SMSC document is highlighting this issue and suggest one solution is adjusting trace lengths on the board to resolve this hold time violation.  This can be done by making the RXD[1:0], RXER, and CRS_DV signals 0.6ns longer than the REF_CLK.  I would design the PCB with these signals being about 5.33 inches longer than REF_CLK which provides about 0.8ns of delay so there is an additional 200ps of margin.  This assumes 150ps per inch as the fastest propagation speed for these signals.  This PCB delay of 0.8ns still provides plenty of margin for the AM335x setup time.

    However, the LAN8720 has another issue that will not be easy to resolve with PCB trace delay when operating in REF_CLK out mode.  The LAN8720 has a min setup requirement of 7ns rather than the 4ns as defined in the RMII specification.

    AM335x assumed it would be connected to a RMII compliant PHY so the max output delay of the TXD[1:0] and TXEN signals is 13ns.  If you subtract this max delay of 13ns and the RMII defined setup requirement of 4ns from the clock period of 20ns, there would be about 3ns of margin that could be consumed by the round trip PCB delay of the REF_CLK going from the LAN8720 to AM335x and the TXD[1:0] and TXEN signals going from AM335x to the LAN8720.  This would allow the round trip etch length to be a maximum length of 17.5 inches, assuming 170ps per inch as the slowest propagation speed for these signals.

    Since the LAN8720 has a min setup of 7ns rather than 4ns, this consumes all of the margin allowed for signal trace delays.  To meet the LAN8720 setup time, the round trip signal delays would need to be zero inches which is not possible.  Therefore, it is not possible to use the LAN8720 in REF_CLK out mode and meet the RMII timing requirements.

    You can make this work by using an external 50MHz low jitter oscillator that sources a LVCMOS digital reference clock to both AM335x and LAN8720.  In this case the LAN8720 would be operating in REF_CLK in mode which has different timing requirements/characteristics.  Assuming you design the PCB with equal length signal traces for each of the REF_CLK signal paths to each device as shown in the SMSC document you referenced, both AM335x and LAN8720 would receive the reference clock at the same time.  This would allow the RXD[1:0], RXER, and CRS_DV signals to have up to 2ns of PCB delay (about 11 inches) and the TXD[1:0] and TXEN signals to have up to 3ns of PCB delay (about 17 inches).

    I'm still confused by your comment about a ceramic (non-crystal) oscillator.  An oscillator is an active circuit packaged with a internal crystal where the circuit excites the internal crystal and buffers the output to a valid LVCMOS digital signal.  I assume this is what you are calling a ceramic (non-crystal) oscillator.  Note: Some oscillators may also contain an internal PLL programmed to produce a synthesized frequency output.  This type of oscillator may produce too much jitter for RMII.  Make sure you purchase an oscillator that does not have an internal PLL.

    Regards,
    Paul