Porting KSZ9031 to i.MX BSP

Document created by jimmychan Employee on Sep 25, 2019Last modified by jimmychan Employee on Sep 26, 2019
Version 3Show Document
  • View in full screen mode

KSZ9031 is a very common PHY used with many ethernet design. This document will show you how to add it in u-boot and kernel.

 

1. Schematic

 

 

The MODE[3:0] strap-in pins are sampled and latched at power-up/reset. MODE[3:0]=1111 is RGMII mode - Advertise all capabilities (10/100/1000 speed half-/full-duplex)

The PHY address, PHYAD[2:0], is sampled and latched at power-up/reset. Here PHY address is set to 001.

In this design example, the ENET_RESET_B is connected to GPIO pin GPIO1_IO03.

 

2. Source code modification

 

In u-boot source code, add the following code in the <board_name>.c file.

- IOMUX setup for the GPIO1_IO03 pin.

static iomux_v3_cfg_t const phy_reset_pads[] = {
     MX7D_PAD_GPIO1_IO03__GPIO1_IO3 | MUX_PAD_CTRL(NO_PAD_CTRL),
};

 

- In the function setup_fec(int fec_id), add the code for phy reset.

imx_iomux_v3_setup_multiple_pads(phy_reset_pads, ARRAY_SIZE(phy_reset_pads));

gpio_request(IMX_GPIO_NR(1, 3), "ENET PHY Reset");
gpio_direction_output(IMX_GPIO_NR(1, 3) , 0);
mdelay(20);
gpio_set_value(IMX_GPIO_NR(1, 3), 1);

 

- There is a PHY config for the KSZ9031.

int board_phy_config(struct phy_device *phydev)
{    /*
     * Default setting for GMII Clock Pad Skew Register 0x1EF:
     * MMD Address 0x2h, Register 0x8h
     *
     * GTX_CLK Pad Skew 0xF -> 0.9 nsec skew
     * RX_CLK Pad Skew 0xF -> 0.9 nsec skew
     *
     * Adjustment -> write 0x3FF:
     * GTX_CLK Pad Skew 0x1F -> 1.8 nsec skew
     * RX_CLK Pad Skew 0x1F -> 1.8 nsec skew
     *
     */
    /* control data pad skew - devaddr = 0x02, register = 0x04 */
    ksz9031_phy_extended_write(phydev, 0x02,
                   MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW,
                   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
    /* rx data pad skew - devaddr = 0x02, register = 0x05 */
    ksz9031_phy_extended_write(phydev, 0x02,
                   MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW,
                   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
    /* tx data pad skew - devaddr = 0x02, register = 0x05 */
    ksz9031_phy_extended_write(phydev, 0x02,
                   MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW,
                   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);
    /* gtx and rx clock pad skew - devaddr = 0x02, register = 0x08 */
    ksz9031_phy_extended_write(phydev, 0x02,
                   MII_KSZ9031_EXT_RGMII_CLOCK_SKEW,
                   MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x03FF);

 

    if (phydev->drv->config)
        phydev->drv->config(phydev);
    return 0;
}

 

The KSZ9031 driver (drivers/net/phy/micrel.c) had already supported in the u-boot source code. Add the following #define to enable the driver for building.

#define CONFIG_PHY_MICREL

 

As the PHY address on the board is 001, change the PHYADDR to 1 in the <board_name>.h file.

#define CONFIG_FEC_MXC_PHYADDR          0x1

 

In the kernel source code, add/modify the PHY setting in dts file like this.

&fec1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet_reset>;
    assigned-clocks = <&clks IMX7D_ENET_PHY_REF_ROOT_SRC>,
              <&clks IMX7D_ENET_AXI_ROOT_SRC>,
              <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
              <&clks IMX7D_ENET1_TIME_ROOT_CLK>,
              <&clks IMX7D_ENET_AXI_ROOT_CLK>;
    assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_25M_CLK>,
                 <&clks IMX7D_PLL_ENET_MAIN_250M_CLK>,
                 <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
    assigned-clock-rates = <0>, <0>, <0>, <100000000>, <250000000>;
    phy-mode = "rgmii";
    phy-handle = <&ethphy0>;
    phy-reset-gpios = <&gpio1 3 0>;
    fsl,magic-packet;
    status = "okay";

    mdio {
        #address-cells = <1>;
        #size-cells = <0>;

        ethphy0: ethernet-phy@1 {    //here '@1' is the PHY address
            compatible = "ethernet-phy-ieee802.3-c22";
            reg = <1>;
        };

    };
};

 

Add the GPIO pin for the ENET_RESET_B

&iomuxc {

...

...

pinctrl_enet_reset: enet_resetgrp {
            fsl,pins = <
                MX7D_PAD_GPIO1_IO03__GPIO1_IO3      0x14     //ENET_RESET_B
            >;
        };

 

}

 

There is a PHY fixup in the arch/arm/mach-imx/<imx_cpu>.c

Here is the example in mach-imx7d.c

 

#define PHY_ID_KSZ9031    0x00221620
#define MICREL_PHY_ID_MASK 0x00fffff0

 

static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
{
    phy_write(dev, 0x0d, device);
    phy_write(dev, 0x0e, reg);
    phy_write(dev, 0x0d, (1 << 14) | device);
    phy_write(dev, 0x0e, val);
}

 

static int ksz9031rn_phy_fixup(struct phy_device *dev)
{
    /*
     * min rx data delay, max rx/tx clock delay,
     * min rx/tx control delay
     */
    mmd_write_reg(dev, -1, 0x4, 0);
    mmd_write_reg(dev, -1, 0x5, 0);
    mmd_write_reg(dev, -1, 0x6, 0);
    mmd_write_reg(dev, -1, 0x8, 0x003ff);

 

    return 0;
}

 

static void __init imx7d_enet_phy_init(void)
{
    if (IS_BUILTIN(CONFIG_PHYLIB)) {
        phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
                       ar8031_phy_fixup);
        phy_register_fixup_for_uid(PHY_ID_BCM54220, 0xffffffff,
                       bcm54220_phy_fixup);
        phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
                ksz9031rn_phy_fixup);
    }
}

 

Now, the PHY is working on your board.

 

Reference:

1.  Create an Ubuntu VM environment to build Yocto BSP 

2.  i.MX Software | NXP 

1 person found this helpful

Attachments

    Outcomes