cgtqmx6eval can be populated with a AR8035 or KSZ9031 depending on the board revision.
Add Ethernet support. Signed-off-by: Otavio Salvador <ota...@ossystems.com.br> --- board/congatec/cgtqmx6eval/cgtqmx6eval.c | 205 +++++++++++++++++++++++++++++++ include/configs/cgtqmx6eval.h | 14 +++ 2 files changed, 219 insertions(+) diff --git a/board/congatec/cgtqmx6eval/cgtqmx6eval.c b/board/congatec/cgtqmx6eval/cgtqmx6eval.c index d06eee1..0a8eccd 100644 --- a/board/congatec/cgtqmx6eval/cgtqmx6eval.c +++ b/board/congatec/cgtqmx6eval/cgtqmx6eval.c @@ -16,8 +16,11 @@ #include <asm/gpio.h> #include <asm/imx-common/iomux-v3.h> #include <asm/imx-common/boot_mode.h> +#include <malloc.h> #include <mmc.h> #include <fsl_esdhc.h> +#include <miiphy.h> +#include <netdev.h> DECLARE_GLOBAL_DATA_PTR; @@ -31,6 +34,10 @@ DECLARE_GLOBAL_DATA_PTR; PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) +#define ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + int dram_init(void) { gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE); @@ -88,6 +95,204 @@ static iomux_v3_cfg_t const ecspi1_pads[] = { MX6_PAD_EIM_D19__GPIO3_IO19 | MUX_PAD_CTRL(NO_PAD_CTRL), }; +static iomux_v3_cfg_t enet_pads_ksz9031[] = { + MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RXC__GPIO6_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL), + MX6_PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL), + MX6_PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL), + MX6_PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL), + MX6_PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL), + MX6_PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL), +}; + +static iomux_v3_cfg_t enet_pads_final_ksz9031[] = { + MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), +}; + +static iomux_v3_cfg_t enet_pads_ar8035[] = { + MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL), + MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL), +}; + +int board_eth_init(bd_t *bis) +{ + struct phy_device *phydev; + struct mii_dev *bus; + unsigned short id1, id2; + int ret; + + iomux_v3_cfg_t enet_reset = MX6_PAD_EIM_D23__GPIO3_IO23 | + MUX_PAD_CTRL(NO_PAD_CTRL); + + /* check whether KSZ9031 or AR8035 has to be configured */ + imx_iomux_v3_setup_multiple_pads(enet_pads_ar8035, + ARRAY_SIZE(enet_pads_ar8035)); + imx_iomux_v3_setup_pad(enet_reset); + + /* phy reset */ + gpio_direction_output(IMX_GPIO_NR(3, 23), 0); + udelay(2000); + gpio_set_value(IMX_GPIO_NR(3, 23), 1); + udelay(500); + + bus = fec_get_miibus(IMX_FEC_BASE, -1); + if (!bus) + return -EINVAL; + phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII); + if (!phydev) { + printf("Error: phy device not found.\n"); + ret = -ENODEV; + goto free_bus; + } + + /* get the PHY id */ + id1 = phy_read(phydev, MDIO_DEVAD_NONE, 2); + id2 = phy_read(phydev, MDIO_DEVAD_NONE, 3); + + if ((id1 == 0x22) && ((id2 & 0xFFF0) == 0x1620)) { + /* re-configure for Micrel KSZ9031 */ + printf("configure Micrel KSZ9031 Ethernet Phy at address %d\n", + phydev->addr); + + /* phy reset: gpio3-23 */ + gpio_set_value(IMX_GPIO_NR(3, 23), 0); + gpio_set_value(IMX_GPIO_NR(6, 30), (phydev->addr >> 2)); + gpio_set_value(IMX_GPIO_NR(6, 25), 1); + gpio_set_value(IMX_GPIO_NR(6, 27), 1); + gpio_set_value(IMX_GPIO_NR(6, 28), 1); + gpio_set_value(IMX_GPIO_NR(6, 29), 1); + imx_iomux_v3_setup_multiple_pads(enet_pads_ksz9031, + ARRAY_SIZE(enet_pads_ksz9031)); + gpio_set_value(IMX_GPIO_NR(6, 24), 1); + udelay(500); + gpio_set_value(IMX_GPIO_NR(3, 23), 1); + imx_iomux_v3_setup_multiple_pads(enet_pads_final_ksz9031, + ARRAY_SIZE(enet_pads_final_ksz9031)); + } else if ((id1 == 0x004d) && (id2 == 0xd072)) { + /* configure Atheros AR8035 - actually nothing to do */ + printf("configure Atheros AR8035 Ethernet Phy at address %d\n", + phydev->addr); + } else { + printf("Unknown Ethernet-Phy: 0x%04x 0x%04x\n", id1, id2); + ret = -EINVAL; + goto free_phydev; + } + + ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev); + if (ret) + goto free_phydev; + + return 0; + +free_phydev: + free(phydev); +free_bus: + free(bus); + return ret; +} + +int mx6_rgmii_rework(struct phy_device *phydev) +{ + unsigned short id1, id2; + unsigned short val; + + /* check whether KSZ9031 or AR8035 has to be configured */ + id1 = phy_read(phydev, MDIO_DEVAD_NONE, 2); + id2 = phy_read(phydev, MDIO_DEVAD_NONE, 3); + + if ((id1 == 0x22) && ((id2 & 0xFFF0) == 0x1620)) { + /* finalize phy configuration for Micrel KSZ9031 */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 2); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 4); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0xc002); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0x0000); + + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 2); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 5); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0xc002); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0x0000); + + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 2); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 6); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0xc002); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0xFFFF); + + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 2); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 8); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0xc002); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0x3FFF); + + /* fix KSZ9031 link up issue */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0x0); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0x4); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0x4000); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0x6); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0x0000); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0x3); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0d, 0x4000); + phy_write(phydev, MDIO_DEVAD_NONE, 0x0e, 0x1A80); + } + + if ((id1 == 0x004d) && (id2 == 0xd072)) { + /* enable AR8035 ouput a 125MHz clk from CLK_25M */ + phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x7); + phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016); + phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007); + val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe); + val &= 0xfe63; + val |= 0x18; + phy_write(phydev, MDIO_DEVAD_NONE, 0xe, val); + + /* introduce tx clock delay */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); + val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); + val |= 0x0100; + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val); + + /* disable hibernation */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0xb); + val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3c40); + } + return 0; +} + +int board_phy_config(struct phy_device *phydev) +{ + mx6_rgmii_rework(phydev); + + if (phydev->drv->config) + phydev->drv->config(phydev); + + return 0; +} + static void setup_iomux_uart(void) { imx_iomux_v3_setup_multiple_pads(uart2_pads, ARRAY_SIZE(uart2_pads)); diff --git a/include/configs/cgtqmx6eval.h b/include/configs/cgtqmx6eval.h index 15ce29b..ebbaf9b 100644 --- a/include/configs/cgtqmx6eval.h +++ b/include/configs/cgtqmx6eval.h @@ -43,6 +43,20 @@ /* Miscellaneous commands */ #define CONFIG_CMD_BMODE +/* Ethernet */ +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#define CONFIG_FEC_MXC +#define CONFIG_MII +#define IMX_FEC_BASE ENET_BASE_ADDR +#define CONFIG_FEC_XCV_TYPE RGMII +#define CONFIG_ETHPRIME "FEC" +#define CONFIG_FEC_MXC_PHYADDR 6 + +#define CONFIG_PHYLIB +#define CONFIG_PHY_ATHEROS + #define CONFIG_DEFAULT_FDT_FILE "imx6q-congatec.dtb" #define CONFIG_EXTRA_ENV_SETTINGS \ -- 2.4.5 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot