[U-Boot] [PATCH v3 08/15] cgtqmx6eval: Add Ethernet support

Otavio Salvador otavio at ossystems.com.br
Thu Jul 23 16:02:26 CEST 2015


cgtqmx6eval can be populated with a AR8035 or KSZ9031 depending on the
board revision.

Add Ethernet support.

Signed-off-by: Otavio Salvador <otavio at ossystems.com.br>
---

Changes in v3: None
Changes in v2: None

 board/congatec/cgtqmx6eval/cgtqmx6eval.c | 206 +++++++++++++++++++++++++++++++
 include/configs/cgtqmx6eval.h            |  14 +++
 2 files changed, 220 insertions(+)

diff --git a/board/congatec/cgtqmx6eval/cgtqmx6eval.c b/board/congatec/cgtqmx6eval/cgtqmx6eval.c
index 1ae126c..1563ac7 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;
 
@@ -27,6 +30,11 @@ DECLARE_GLOBAL_DATA_PTR;
 #define USDHC_PAD_CTRL (PAD_CTL_PUS_47K_UP  | PAD_CTL_SPEED_LOW |\
 	PAD_CTL_DSE_80ohm   | PAD_CTL_SRE_FAST  | PAD_CTL_HYS)
 
+
+#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);
@@ -77,6 +85,204 @@ static iomux_v3_cfg_t const usdhc4_pads[] = {
 	MX6_PAD_NANDF_D6__GPIO2_IO06    | MUX_PAD_CTRL(NO_PAD_CTRL), /* CD */
 };
 
+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 9d9e388..8ba47bf 100644
--- a/include/configs/cgtqmx6eval.h
+++ b/include/configs/cgtqmx6eval.h
@@ -32,6 +32,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.6



More information about the U-Boot mailing list