RMII interface on i.MX6SX

cancel
Showing results for 
Search instead for 
Did you mean: 

RMII interface on i.MX6SX

3,670 Views
Richard1z
Contributor II

I wish to use a LAN8720 (RMII) with the iMX6SX.

The IMX6SXHDG does not cover the Ethernet Interface at all.

The SX Reference Manual covers it very badly:

http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6SXRM.pdf?fasp=1

1) My main problem is how to generate the RMII clock for the LAN8720.

The IMX6DQ6SDLHDG outlines how it is done for  S/D/L processors (see below), by using GPIO_16.

Does this apply to iMX6SX devices too ?

pastedImage_1.png

2) The following screenshots show my connections between LAN8720 and iMX6SX.

Do they seem correct ?

pastedImage_2.png

pastedImage_3.png

Labels (1)
Tags (1)
15 Replies

648 Views
Richard1z
Contributor II

Hi Martin,

getting back to the SX + LAN8720 circuit after a _long_ absence......

Did your second PCB version work ?

I ask because our 1st one has a fatal clock problem, and I am about to spin a 2nd revision in the hope that correcting the clock error will allow it to work.

I'd be obliged if you could review my circuit above and compare it to yours or if you could share the relevant parts of your schematic. I'd hate to build a second set of board that still didn't work!

BTW: For those in Freescale/NXP, the IMX6SXHDG has recently been revised - but it _still_ doesn't mention the RMII interface !

0 Kudos

648 Views
BiyongSUN
NXP Employee
NXP Employee

1. change the device tree to set the pin ctrl  correctly . Especially loop back the clock.

    #define MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1                    0x0090 0x03D8 0x0760 0x11 0x1

     Untitled.png

2. change the device tree to set the fec correctly.  using rmii

3. Using 50M for RMII

    arch/arm/mach-imx/clk-imx6sx.c

    imx_clk_set_rate(clks[IMX6SX_CLK_ENET_REF], 50000000);

4.   Add phy fix up for LAN8720 as ar8031 does

193 #define PHY_ID_AR8031   0x004dd074

194 static void __init imx6sx_enet_phy_init(void)

195 {

196         if (IS_BUILTIN(CONFIG_PHYLIB))

197                 phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,

198                         ar8031_phy_fixup);

199 }

200

648 Views
robyf
Contributor IV

Hi Sun,

can you please note that the reference clock is connected to ENET2_RX_CLK, do you think looks ok?

Currently I'm going to patch our custom board under uboot-imx with this pinmux.

/* mx6sx_pins.h */

MX6SX_PAD_ENET2_RX_CLK__ENET2_RX_CLK                     = IOMUX_PAD(0x03E4, 0x009C, 0 | IOMUX_CONFIG_SION, 0x0000, 0, NO_PAD_CTRL)

/* board pinmux */

#define GPIO_FEC1_PHY_RESET IMX_GPIO_NR(2, 7)

static iomux_v3_cfg_t const fec1_pads[] = {

        MX6SX_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 | MUX_PAD_CTRL(NO_PAD_CTRL),

        MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET2_RX_CLK__ENET2_RX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9 | MUX_PAD_CTRL(ENET_PAD_CTRL),

};

Thanks in advance,

Roberto Fichera.

0 Kudos

648 Views
BiyongSUN
NXP Employee
NXP Employee

Which BSP you are using?

i.MXSX is L3.10.53_1.1.0 and later.

0 Kudos

648 Views
robyf
Contributor IV

I'm using yocto fido fully updated. u-boot is imx version.

0 Kudos

648 Views
BiyongSUN
NXP Employee
NXP Employee

If you use the freescale release. Now the pin is handled by device tree.

Could not have the following array to configure the iomux.

Please use the freescale BSP.

static iomux_v3_cfg_t const fec1_pads[] = {

        MX6SX_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 | MUX_PAD_CTRL(NO_PAD_CTRL),

        MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET2_RX_CLK__ENET2_RX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),

        MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9 | MUX_PAD_CTRL(ENET_PAD_CTRL),

};

0 Kudos

648 Views
robyf
Contributor IV

Sorry but I guess you are referring to the linux kernel and not regarding u-boot. I'm currently using the last u-boot-imx version you will find in L3.14.28_1.0.0_ga release. Here the my git log:

* 88123ea - (HEAD, tag: rel_imx_3.14.28_1.0.0_ga) MLK-10215 Add elan init in i.MX6SL-EVK board (5 months ago) <Haibo Chen>

* 1d4e7b2 - MLK-10134 imx: mx6dqarm2: Add MX6DQ PoP validation board support (6 months ago) <Ye.Li>

* cd67d51 - MA-6048 Correct word in uboot log for android recovery mode (7 months ago) <guoyin.chen>

* 9045626 - MLK-10035-2: supports NAND chips with oob size up to 744 byte (7 months ago) <Allen Xu>

[...]

The changes you are talking above seems related to the linux kernel not u-boot as I've requested. By the way my current pinmux settings is:

static iomux_v3_cfg_t const fec1_pads[] = {

  MX6SX_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 | MUX_PAD_CTRL(NO_PAD_CTRL),

  MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET1_RX_CLK__ENET1_RX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET2_RX_CLK__ENET2_RX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 | MUX_PAD_CTRL(ENET_PAD_CTRL),

};

we are actually fixing the RX_CLK vs TX_CLK issue by a patch but we want to enable both ENET1/2

ref clocks in order to feed the clock to LAN8720 pin, so I've this fec initialization code:

static int setup_fec(int fec_id)

{

  struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs  = (struct iomuxc_gpr_base_regs *) IOMUXC_GPR_BASE_ADDR;

  int ret;

   /* Use 50MHz anatop REF_CLK1/2 for both ENET1/2, clear gpr1[13:14], gpr1[17:18]*/

  clrsetbits_le32(&iomuxc_gpr_regs->gpr[1], IOMUX_GPR1_FEC1_MASK, 0);

  clrsetbits_le32(&iomuxc_gpr_regs->gpr[1], IOMUX_GPR1_FEC2_MASK, 0);

  ret  = enable_fec_anatop_clock(0, ENET_50MHz);

  ret |= enable_fec_anatop_clock(1, ENET_50MHz);

  if (ret)

    return ret;

  return 0;

}

But we don't see anything on the ENET2_TX_CLK pin right now. Any idea how to get both clocks up and running?

Cheers,

Roberto Fichera.

0 Kudos

648 Views
BiyongSUN
NXP Employee
NXP Employee

In the referece design, the hardware is shared MDIO/MDC.

Could you please check you hardware and also read the phy id to confirm which phy you are controlling?

0 Kudos

648 Views
robyf
Contributor IV

Currently I'm not able to read the phy id. The RX/TX_CLK is not present, hence the MDIO is transmitting all "1"s.

0 Kudos

648 Views
BiyongSUN
NXP Employee
NXP Employee


for the  RMII, the clock should be provided by the transmit side.

And please make sure, the pad configure as SION to loop back.  

The RX side clock should provide by the phy.

0 Kudos

648 Views
robyf
Contributor IV

My code actually is the following:

arch/arm/include/include/asm/arch-mx6/mx6sx_pins.h has the following changes:

MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1                   = IOMUX_PAD(0x03D8, 0x0090, 1 | IOMUX_CONFIG_SION, 0x0760, 1, 0),

MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2                   = IOMUX_PAD(0x03E8, 0x00A0, 1 | IOMUX_CONFIG_SION, 0x076C, 1, 0),

board specific code looks:

#define ENET_PAD_CTRL  (PAD_CTL_PUS_100K_UP | PAD_CTL_PUE |     \

  PAD_CTL_SPEED_HIGH   |                                   \

  PAD_CTL_DSE_48ohm   | PAD_CTL_SRE_FAST)

#define ENET_CLK_PAD_CTRL  (PAD_CTL_SPEED_MED | \

  PAD_CTL_DSE_120ohm   | PAD_CTL_SRE_FAST)

#define ENET_RX_PAD_CTRL  (PAD_CTL_PKE | PAD_CTL_PUE |          \

  PAD_CTL_SPEED_HIGH   | PAD_CTL_SRE_FAST)

#define GPIO_FEC1_PHY_RESET IMX_GPIO_NR(2, 7)

static iomux_v3_cfg_t const fec1_pads[] = {

  MX6SX_PAD_ENET1_MDC__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET1_MDIO__ENET1_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),

  MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),

  MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN | MUX_PAD_CTRL(ENET_RX_PAD_CTRL),

  MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET1_RX_CLK__ENET1_REF_CLK_25M | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M | MUX_PAD_CTRL(ENET_PAD_CTRL),

  MX6SX_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 | MUX_PAD_CTRL(ENET_PAD_CTRL),

  /* ENET PHY Reset */

  MX6SX_PAD_ENET2_CRS__GPIO2_IO_7 | MUX_PAD_CTRL(NO_PAD_CTRL),

};

....

static int voneus_enable_fec_anatop_clock(enum enet_freq freq)

{

extern struct mxc_ccm_reg *imx_ccm;

  u32 reg = 0;

  s32 timeout = 100000;

  if (freq < ENET_25MHz || freq > ENET_125MHz)

  return -EINVAL;

  reg = readl(&imx_ccm->analog_pll_enet);

  reg &= ~(BM_ANADIG_PLL_ENET_DIV_SELECT|BM_ANADIG_PLL_ENET2_DIV_SELECT);

  reg |= BF_ANADIG_PLL_ENET_DIV_SELECT(freq) | BF_ANADIG_PLL_ENET2_DIV_SELECT(freq);

  if ((reg & BM_ANADIG_PLL_ENET_POWERDOWN) ||

     (!(reg & BM_ANADIG_PLL_ENET_LOCK))) {

  reg &= ~BM_ANADIG_PLL_ENET_POWERDOWN;

  writel(reg, &imx_ccm->analog_pll_enet);

  while (timeout--) {

  if (readl(&imx_ccm->analog_pll_enet) & BM_ANADIG_PLL_ENET_LOCK)

  break;

  }

  if (timeout < 0) {

                    printf("FEC MXC: %s:timeout\n", __func__);

     return -ETIMEDOUT;

                }

  }

  /* Enable FEC clock */

  reg |= BM_ANADIG_PLL_ENET_ENABLE|BM_ANADIG_PLL_ENET2_ENABLE;

  reg &= ~BM_ANADIG_PLL_ENET_BYPASS;

#ifdef CONFIG_FEC_MXC_25M_REF_CLK

  reg |= BM_ANADIG_PLL_ENET_REF_25M_ENABLE;

#endif

  writel(reg, &imx_ccm->analog_pll_enet);

  return 0;

}

static int probe_lan8720(bd_t *bd, int dev_id, int phy_id, uint32_t addr)

{

  uint32_t base_mii;

  struct mii_dev *bus = NULL;

#ifdef CONFIG_PHYLIB

  struct phy_device *phydev = NULL;

#endif

  int ret;

  base_mii = addr;

  printf("eth_init: fec_probe(bd, %i, %i) @ %08x\n", dev_id, phy_id, addr);

  bus = fec_get_miibus(base_mii, dev_id);

  if (!bus)

  return -ENOMEM;

#ifdef CONFIG_PHYLIB

  phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RMII);

  if (!phydev) {

  free(bus);

  return -ENOMEM;

  }

  ret = fec_probe(bd, dev_id, addr, bus, phydev);

#else

  ret = fec_probe(bd, dev_id, addr, bus, phy_id);

#endif

  if (ret) {

#ifdef CONFIG_PHYLIB

  free(phydev);

#endif

  free(bus);

  }

  return ret;

}

int board_eth_init(bd_t *bis)

{

  struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs = (struct iomuxc_gpr_base_regs *) IOMUXC_GPR_BASE_ADDR;

  int ret;

  int reg;

  imx_iomux_v3_setup_multiple_pads(fec1_pads, ARRAY_SIZE(fec1_pads));

   gpio_direction_output(GPIO_FEC1_PHY_RESET, 0);

   reg = readl(&iomuxc_gpr_regs->gpr[1]);

    /* reset ENET1/2_TX_CLK_DIR gpr1[14:13] to set reference clock driven by ref_enetpll0/1

     * Clock is output to pins via IOMUX ENET_REF_CLK1/2

     */

  reg &= ~(IOMUX_GPR1_FEC1_CLOCK_MUX2_SEL_MASK|IOMUX_GPR1_FEC2_CLOCK_MUX2_SEL_MASK);

  /* set ENET1/2_TX_CLK_DIR gpr1[18:17] to enable output driver when ENET1/2_TX_CLK when in ALT1 */

  reg |= IOMUX_GPR1_FEC1_CLOCK_MUX1_SEL_MASK|IOMUX_GPR1_FEC2_CLOCK_MUX1_SEL_MASK;

  writel(reg, &iomuxc_gpr_regs->gpr[1]);

  ret  = voneus_enable_fec_anatop_clock(ENET_50MHz);

  enable_enet_clock();

  mdelay(30);

  gpio_set_value(GPIO_FEC1_PHY_RESET, 1);

  mdelay(100);

  ret = probe_lan8720(bis, CONFIG_FEC_ENET_DEV, CONFIG_FEC_MXC_PHYADDR, IMX_FEC_BASE);

  if (ret)

     printf("FEC MXC: %s:failed (%0x)\n",  __func__, ret);

  return ret;

}

int board_phy_config(struct phy_device *phydev)

{

  if (phydev->drv->config)

  phydev->drv->config(phydev);

  return 0;

}

648 Views
robyf
Contributor IV

I want to reply myself because finally I've got it working and now the PHY is finally recognized correctly!

U-Boot 2014.04-imx_v2014.04_3.14.28_1.0.0_ga+g88123ea (Aug 05 2015 - 16:44:08)

CPU:   Freescale i.MX6SX rev1.2 at 792 MHz

CPU:   Temperature 35 C, calibration data: 0x5c553569

Reset cause: POR

Board: Domus iMX6SX (ID:e301dab51823b1d4)

I2C:   ready

DRAM:  512 MiB

MMC:   FSL_SDHC: 0, FSL_SDHC: 1

*** Warning - bad CRC, using default environment

In:    serial

Out:   serial

Err:   serial

Found PFUZE200! deviceid 0x1, revid 0x21

mmc0 is current device

FEC0 connected to SMSC LAN8710/LAN8720

FEC0

Warning: failed to set MAC address

Normal Boot

Hit any key to stop autoboot:  0

=>

0 Kudos

648 Views
mchaplet
Contributor II

Hi Roberto,

I've exactly the same config as you apparently.

Did you make it works finally ? (with 50MHz generation and internal loopack)

Can you explain me U-Boot and linux configurations ?

I actually can generate 50MHz on Ref_clk and so the MDIO is OK but the RMII (ping/data) seems KO.

I think it's only a loopback issue but I'm quite lost between GPR1, MUX, ANALOG_PLL, ENET registers .....

Can you help me please (again ;-) ) ?

0 Kudos

648 Views
mchaplet
Contributor II

Ok, it seems that it was only missing MUX_MODE_SION in Muxing :

#define MX6_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 | MUX_PAD_CTRL(ENET_PAD_CTRL) | MUX_MODE_SION,

Now I'm able to send packet ... but RX doesn't work because the ENET_RX_EN signal is not wired on my board :-/

I copied my design from an iMX6Solo and it seems that RX_EN signal is now muxed on RX_CTL pad instead of CRS pad.

I need to wait the second board version .... :-(

0 Kudos

648 Views
robyf
Contributor IV

Hi Martin,

Once patched the PCB but keeping the clocks from the second MAC I was able to progress a bit. uboot was patched accordingly with such particular clock wiring. The interface was able to acquire a DHCP address but pinging never worked. Due to that I haven't invested much time to check it, I have preferred to complete my tests with the rest of the peripherals and wait a new PCB version with the right wiring.

0 Kudos