Commit f02229021d2698e97915740ed491ddc3f0975f2e

Authored by Otavio Salvador
Committed by Stefano Babic
1 parent 066f876bf6

cgtqmx6eval: Add Ethernet support

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

Add Ethernet support.

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

Showing 3 changed files with 224 additions and 0 deletions Side-by-side Diff

board/congatec/cgtqmx6eval/cgtqmx6eval.c
... ... @@ -27,6 +27,10 @@
27 27 #include <power/pfuze100_pmic.h>
28 28 #include <linux/fb.h>
29 29 #include <ipu_pixfmt.h>
  30 +#include <malloc.h>
  31 +#include <miiphy.h>
  32 +#include <netdev.h>
  33 +#include <micrel.h>
30 34  
31 35 DECLARE_GLOBAL_DATA_PTR;
32 36  
... ... @@ -43,6 +47,11 @@
43 47  
44 48 #define MX6Q_QMX6_PFUZE_MUX IMX_GPIO_NR(6, 9)
45 49  
  50 +
  51 +#define ENET_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
  52 + PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \
  53 + PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
  54 +
46 55 int dram_init(void)
47 56 {
48 57 gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
... ... @@ -98,6 +107,51 @@
98 107 MX6_PAD_GPIO_1__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL),
99 108 };
100 109  
  110 +static iomux_v3_cfg_t enet_pads_ksz9031[] = {
  111 + MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
  112 + MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  113 + MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  114 + MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  115 + MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  116 + MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  117 + MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  118 + MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
  119 + MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
  120 + MX6_PAD_RGMII_RXC__GPIO6_IO30 | MUX_PAD_CTRL(NO_PAD_CTRL),
  121 + MX6_PAD_RGMII_RD0__GPIO6_IO25 | MUX_PAD_CTRL(NO_PAD_CTRL),
  122 + MX6_PAD_RGMII_RD1__GPIO6_IO27 | MUX_PAD_CTRL(NO_PAD_CTRL),
  123 + MX6_PAD_RGMII_RD2__GPIO6_IO28 | MUX_PAD_CTRL(NO_PAD_CTRL),
  124 + MX6_PAD_RGMII_RD3__GPIO6_IO29 | MUX_PAD_CTRL(NO_PAD_CTRL),
  125 + MX6_PAD_RGMII_RX_CTL__GPIO6_IO24 | MUX_PAD_CTRL(NO_PAD_CTRL),
  126 +};
  127 +
  128 +static iomux_v3_cfg_t enet_pads_final_ksz9031[] = {
  129 + MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  130 + MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  131 + MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  132 + MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  133 + MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  134 + MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
  135 +};
  136 +
  137 +static iomux_v3_cfg_t enet_pads_ar8035[] = {
  138 + MX6_PAD_ENET_MDIO__ENET_MDIO | MUX_PAD_CTRL(ENET_PAD_CTRL),
  139 + MX6_PAD_ENET_MDC__ENET_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  140 + MX6_PAD_RGMII_TXC__RGMII_TXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  141 + MX6_PAD_RGMII_TD0__RGMII_TD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  142 + MX6_PAD_RGMII_TD1__RGMII_TD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  143 + MX6_PAD_RGMII_TD2__RGMII_TD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  144 + MX6_PAD_RGMII_TD3__RGMII_TD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  145 + MX6_PAD_RGMII_TX_CTL__RGMII_TX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
  146 + MX6_PAD_ENET_REF_CLK__ENET_TX_CLK | MUX_PAD_CTRL(ENET_PAD_CTRL),
  147 + MX6_PAD_RGMII_RXC__RGMII_RXC | MUX_PAD_CTRL(ENET_PAD_CTRL),
  148 + MX6_PAD_RGMII_RD0__RGMII_RD0 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  149 + MX6_PAD_RGMII_RD1__RGMII_RD1 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  150 + MX6_PAD_RGMII_RD2__RGMII_RD2 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  151 + MX6_PAD_RGMII_RD3__RGMII_RD3 | MUX_PAD_CTRL(ENET_PAD_CTRL),
  152 + MX6_PAD_RGMII_RX_CTL__RGMII_RX_CTL | MUX_PAD_CTRL(ENET_PAD_CTRL),
  153 +};
  154 +
101 155 #define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
102 156 struct i2c_pads_info i2c_pad_info1 = {
103 157 .scl = {
... ... @@ -166,6 +220,159 @@
166 220 return ret;
167 221 }
168 222 }
  223 +
  224 + return 0;
  225 +}
  226 +
  227 +int board_eth_init(bd_t *bis)
  228 +{
  229 + struct phy_device *phydev;
  230 + struct mii_dev *bus;
  231 + unsigned short id1, id2;
  232 + int ret;
  233 +
  234 + iomux_v3_cfg_t enet_reset = MX6_PAD_EIM_D23__GPIO3_IO23 |
  235 + MUX_PAD_CTRL(NO_PAD_CTRL);
  236 +
  237 + /* check whether KSZ9031 or AR8035 has to be configured */
  238 + imx_iomux_v3_setup_multiple_pads(enet_pads_ar8035,
  239 + ARRAY_SIZE(enet_pads_ar8035));
  240 + imx_iomux_v3_setup_pad(enet_reset);
  241 +
  242 + /* phy reset */
  243 + gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
  244 + udelay(2000);
  245 + gpio_set_value(IMX_GPIO_NR(3, 23), 1);
  246 + udelay(500);
  247 +
  248 + bus = fec_get_miibus(IMX_FEC_BASE, -1);
  249 + if (!bus)
  250 + return -EINVAL;
  251 + phydev = phy_find_by_mask(bus, (0xf << 4), PHY_INTERFACE_MODE_RGMII);
  252 + if (!phydev) {
  253 + printf("Error: phy device not found.\n");
  254 + ret = -ENODEV;
  255 + goto free_bus;
  256 + }
  257 +
  258 + /* get the PHY id */
  259 + id1 = phy_read(phydev, MDIO_DEVAD_NONE, 2);
  260 + id2 = phy_read(phydev, MDIO_DEVAD_NONE, 3);
  261 +
  262 + if ((id1 == 0x22) && ((id2 & 0xFFF0) == 0x1620)) {
  263 + /* re-configure for Micrel KSZ9031 */
  264 + printf("configure Micrel KSZ9031 Ethernet Phy at address %d\n",
  265 + phydev->addr);
  266 +
  267 + /* phy reset: gpio3-23 */
  268 + gpio_set_value(IMX_GPIO_NR(3, 23), 0);
  269 + gpio_set_value(IMX_GPIO_NR(6, 30), (phydev->addr >> 2));
  270 + gpio_set_value(IMX_GPIO_NR(6, 25), 1);
  271 + gpio_set_value(IMX_GPIO_NR(6, 27), 1);
  272 + gpio_set_value(IMX_GPIO_NR(6, 28), 1);
  273 + gpio_set_value(IMX_GPIO_NR(6, 29), 1);
  274 + imx_iomux_v3_setup_multiple_pads(enet_pads_ksz9031,
  275 + ARRAY_SIZE(enet_pads_ksz9031));
  276 + gpio_set_value(IMX_GPIO_NR(6, 24), 1);
  277 + udelay(500);
  278 + gpio_set_value(IMX_GPIO_NR(3, 23), 1);
  279 + imx_iomux_v3_setup_multiple_pads(enet_pads_final_ksz9031,
  280 + ARRAY_SIZE(enet_pads_final_ksz9031));
  281 + } else if ((id1 == 0x004d) && (id2 == 0xd072)) {
  282 + /* configure Atheros AR8035 - actually nothing to do */
  283 + printf("configure Atheros AR8035 Ethernet Phy at address %d\n",
  284 + phydev->addr);
  285 + } else {
  286 + printf("Unknown Ethernet-Phy: 0x%04x 0x%04x\n", id1, id2);
  287 + ret = -EINVAL;
  288 + goto free_phydev;
  289 + }
  290 +
  291 + ret = fec_probe(bis, -1, IMX_FEC_BASE, bus, phydev);
  292 + if (ret)
  293 + goto free_phydev;
  294 +
  295 + return 0;
  296 +
  297 +free_phydev:
  298 + free(phydev);
  299 +free_bus:
  300 + free(bus);
  301 + return ret;
  302 +}
  303 +
  304 +int mx6_rgmii_rework(struct phy_device *phydev)
  305 +{
  306 + unsigned short id1, id2;
  307 + unsigned short val;
  308 +
  309 + /* check whether KSZ9031 or AR8035 has to be configured */
  310 + id1 = phy_read(phydev, MDIO_DEVAD_NONE, 2);
  311 + id2 = phy_read(phydev, MDIO_DEVAD_NONE, 3);
  312 +
  313 + if ((id1 == 0x22) && ((id2 & 0xFFF0) == 0x1620)) {
  314 + /* finalize phy configuration for Micrel KSZ9031 */
  315 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
  316 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 4);
  317 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
  318 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x0000);
  319 +
  320 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
  321 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 5);
  322 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
  323 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, MII_KSZ9031_MOD_REG);
  324 +
  325 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
  326 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 6);
  327 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
  328 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0xFFFF);
  329 +
  330 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 2);
  331 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 8);
  332 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_POST_INC_W | 0x2);
  333 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x3FFF);
  334 +
  335 + /* fix KSZ9031 link up issue */
  336 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 0x0);
  337 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x4);
  338 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_NO_POST_INC);
  339 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x6);
  340 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_REG);
  341 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x3);
  342 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_NO_POST_INC);
  343 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, 0x1A80);
  344 + }
  345 +
  346 + if ((id1 == 0x004d) && (id2 == 0xd072)) {
  347 + /* enable AR8035 ouput a 125MHz clk from CLK_25M */
  348 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, 0x7);
  349 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, MII_KSZ9031_MOD_DATA_POST_INC_RW | 0x16);
  350 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_CONTROL, MII_KSZ9031_MOD_DATA_NO_POST_INC | 0x7);
  351 + val = phy_read(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA);
  352 + val &= 0xfe63;
  353 + val |= 0x18;
  354 + phy_write(phydev, MDIO_DEVAD_NONE, MMD_ACCESS_REG_DATA, val);
  355 +
  356 + /* introduce tx clock delay */
  357 + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
  358 + val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
  359 + val |= 0x0100;
  360 + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, val);
  361 +
  362 + /* disable hibernation */
  363 + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0xb);
  364 + val = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e);
  365 + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3c40);
  366 + }
  367 + return 0;
  368 +}
  369 +
  370 +int board_phy_config(struct phy_device *phydev)
  371 +{
  372 + mx6_rgmii_rework(phydev);
  373 +
  374 + if (phydev->drv->config)
  375 + phydev->drv->config(phydev);
169 376  
170 377 return 0;
171 378 }
include/configs/cgtqmx6eval.h
... ... @@ -97,6 +97,19 @@
97 97 #define CONFIG_LBA48
98 98 #define CONFIG_LIBATA
99 99  
  100 +/* Ethernet */
  101 +#define CONFIG_CMD_PING
  102 +#define CONFIG_CMD_DHCP
  103 +#define CONFIG_CMD_MII
  104 +#define CONFIG_FEC_MXC
  105 +#define CONFIG_MII
  106 +#define IMX_FEC_BASE ENET_BASE_ADDR
  107 +#define CONFIG_FEC_XCV_TYPE RGMII
  108 +#define CONFIG_ETHPRIME "FEC"
  109 +#define CONFIG_FEC_MXC_PHYADDR 6
  110 +#define CONFIG_PHYLIB
  111 +#define CONFIG_PHY_ATHEROS
  112 +
100 113 /* Command definition */
101 114  
102 115 #define CONFIG_MXC_UART_BASE UART2_BASE
... ... @@ -20,6 +20,10 @@
20 20 #define MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW 0x6
21 21 #define MII_KSZ9031_EXT_RGMII_CLOCK_SKEW 0x8
22 22  
  23 +/* Registers */
  24 +#define MMD_ACCESS_CONTROL 0xd
  25 +#define MMD_ACCESS_REG_DATA 0xe
  26 +
23 27 struct phy_device;
24 28 int ksz9021_phy_extended_write(struct phy_device *phydev, int regnum, u16 val);
25 29 int ksz9021_phy_extended_read(struct phy_device *phydev, int regnum);