diff options
author | Tom Rini <trini@konsulko.com> | 2016-10-13 13:38:49 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-10-13 13:38:49 -0400 |
commit | 44afdc4a12b9f6f48338e7975e4f08cfe90dba74 (patch) | |
tree | 56b563576cc0986ce57a97d7c80a41391ca29417 | |
parent | c69f6d04ec66433f2360490a5cd0263c83aab18f (diff) | |
parent | c9abfbdd66ed97e1cac8553d0b31bd23f68480a9 (diff) | |
download | u-boot-imx-44afdc4a12b9f6f48338e7975e4f08cfe90dba74.zip u-boot-imx-44afdc4a12b9f6f48338e7975e4f08cfe90dba74.tar.gz u-boot-imx-44afdc4a12b9f6f48338e7975e4f08cfe90dba74.tar.bz2 |
Merge branch 'master' of git://git.denx.de/u-boot-net
-rw-r--r-- | board/ti/am335x/board.c | 154 | ||||
-rw-r--r-- | cmd/net.c | 3 | ||||
-rw-r--r-- | drivers/net/cpsw.c | 157 | ||||
-rw-r--r-- | drivers/net/mvneta.c | 2 | ||||
-rw-r--r-- | drivers/net/phy/atheros.c | 53 | ||||
-rw-r--r-- | drivers/net/phy/mv88e61xx.c | 61 | ||||
-rw-r--r-- | drivers/net/rtl8169.c | 3 | ||||
-rw-r--r-- | drivers/usb/eth/smsc95xx.c | 16 | ||||
-rw-r--r-- | include/configs/am335x_evm.h | 2 | ||||
-rw-r--r-- | include/cpsw.h | 1 | ||||
-rw-r--r-- | net/eth-uclass.c | 1 | ||||
-rw-r--r-- | test/py/tests/test_net.py | 49 |
12 files changed, 447 insertions, 55 deletions
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index 0ed16ca..fc1353a 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -47,11 +47,19 @@ DECLARE_GLOBAL_DATA_PTR; #define GPIO_MUX_MII_CTRL GPIO_TO_PIN(3, 10) #define GPIO_FET_SWITCH_CTRL GPIO_TO_PIN(0, 7) #define GPIO_PHY_RESET GPIO_TO_PIN(2, 5) +#define GPIO_ETH0_MODE GPIO_TO_PIN(0, 11) +#define GPIO_ETH1_MODE GPIO_TO_PIN(1, 26) -#if defined(CONFIG_SPL_BUILD) || \ - (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_DM_ETH)) static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; -#endif + +#define GPIO0_RISINGDETECT (AM33XX_GPIO0_BASE + OMAP_GPIO_RISINGDETECT) +#define GPIO1_RISINGDETECT (AM33XX_GPIO1_BASE + OMAP_GPIO_RISINGDETECT) + +#define GPIO0_IRQSTATUS1 (AM33XX_GPIO0_BASE + OMAP_GPIO_IRQSTATUS1) +#define GPIO1_IRQSTATUS1 (AM33XX_GPIO1_BASE + OMAP_GPIO_IRQSTATUS1) + +#define GPIO0_IRQSTATUSRAW (AM33XX_GPIO0_BASE + 0x024) +#define GPIO1_IRQSTATUSRAW (AM33XX_GPIO1_BASE + 0x024) /* * Read header information from EEPROM into global structure. @@ -492,9 +500,9 @@ void sdram_init(void) } #endif -#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ +#if !defined(CONFIG_SPL_BUILD) || \ (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) -static void request_and_set_gpio(int gpio, char *name) +static void request_and_set_gpio(int gpio, char *name, int val) { int ret; @@ -510,7 +518,7 @@ static void request_and_set_gpio(int gpio, char *name) goto err_free_gpio; } - gpio_set_value(gpio, 1); + gpio_set_value(gpio, val); return; @@ -518,7 +526,8 @@ err_free_gpio: gpio_free(gpio); } -#define REQUEST_AND_SET_GPIO(N) request_and_set_gpio(N, #N); +#define REQUEST_AND_SET_GPIO(N) request_and_set_gpio(N, #N, 1); +#define REQUEST_AND_CLR_GPIO(N) request_and_set_gpio(N, #N, 0); /** * RMII mode on ICEv2 board needs 50MHz clock. Given the clock @@ -548,20 +557,76 @@ int board_init(void) #if defined(CONFIG_NOR) || defined(CONFIG_NAND) gpmc_init(); #endif -#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) - int rv; +#if !defined(CONFIG_SPL_BUILD) || \ + (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) if (board_is_icev2()) { + int rv; + u32 reg; + REQUEST_AND_SET_GPIO(GPIO_PR1_MII_CTRL); - REQUEST_AND_SET_GPIO(GPIO_MUX_MII_CTRL); + /* Make J19 status available on GPIO1_26 */ + REQUEST_AND_CLR_GPIO(GPIO_MUX_MII_CTRL); + REQUEST_AND_SET_GPIO(GPIO_FET_SWITCH_CTRL); + /* + * Both ports can be set as RMII-CPSW or MII-PRU-ETH using + * jumpers near the port. Read the jumper value and set + * the pinmux, external mux and PHY clock accordingly. + * As jumper line is overridden by PHY RX_DV pin immediately + * after bootstrap (power-up/reset), we need to sample + * it during PHY reset using GPIO rising edge detection. + */ REQUEST_AND_SET_GPIO(GPIO_PHY_RESET); + /* Enable rising edge IRQ on GPIO0_11 and GPIO 1_26 */ + reg = readl(GPIO0_RISINGDETECT) | BIT(11); + writel(reg, GPIO0_RISINGDETECT); + reg = readl(GPIO1_RISINGDETECT) | BIT(26); + writel(reg, GPIO1_RISINGDETECT); + /* Reset PHYs to capture the Jumper setting */ + gpio_set_value(GPIO_PHY_RESET, 0); + udelay(2); /* PHY datasheet states 1uS min. */ + gpio_set_value(GPIO_PHY_RESET, 1); + + reg = readl(GPIO0_IRQSTATUSRAW) & BIT(11); + if (reg) { + writel(reg, GPIO0_IRQSTATUS1); /* clear irq */ + /* RMII mode */ + printf("ETH0, CPSW\n"); + } else { + /* MII mode */ + printf("ETH0, PRU\n"); + cdce913_data.pdiv3 = 4; /* 25MHz PHY clk */ + } + + reg = readl(GPIO1_IRQSTATUSRAW) & BIT(26); + if (reg) { + writel(reg, GPIO1_IRQSTATUS1); /* clear irq */ + /* RMII mode */ + printf("ETH1, CPSW\n"); + gpio_set_value(GPIO_MUX_MII_CTRL, 1); + } else { + /* MII mode */ + printf("ETH1, PRU\n"); + cdce913_data.pdiv2 = 4; /* 25MHz PHY clk */ + } + + /* disable rising edge IRQs */ + reg = readl(GPIO0_RISINGDETECT) & ~BIT(11); + writel(reg, GPIO0_RISINGDETECT); + reg = readl(GPIO1_RISINGDETECT) & ~BIT(26); + writel(reg, GPIO1_RISINGDETECT); rv = setup_clock_synthesizer(&cdce913_data); if (rv) { printf("Clock synthesizer setup failed %d\n", rv); return rv; } + + /* reset PHYs */ + gpio_set_value(GPIO_PHY_RESET, 0); + udelay(2); /* PHY datasheet states 1uS min. */ + gpio_set_value(GPIO_PHY_RESET, 1); } #endif @@ -571,6 +636,11 @@ int board_init(void) #ifdef CONFIG_BOARD_LATE_INIT int board_late_init(void) { +#if !defined(CONFIG_SPL_BUILD) + uint8_t mac_addr[6]; + uint32_t mac_hi, mac_lo; +#endif + #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG int rc; char *name = NULL; @@ -584,6 +654,39 @@ int board_late_init(void) set_board_info_env(name); #endif +#if !defined(CONFIG_SPL_BUILD) + /* try reading mac address from efuse */ + mac_lo = readl(&cdev->macid0l); + mac_hi = readl(&cdev->macid0h); + mac_addr[0] = mac_hi & 0xFF; + mac_addr[1] = (mac_hi & 0xFF00) >> 8; + mac_addr[2] = (mac_hi & 0xFF0000) >> 16; + mac_addr[3] = (mac_hi & 0xFF000000) >> 24; + mac_addr[4] = mac_lo & 0xFF; + mac_addr[5] = (mac_lo & 0xFF00) >> 8; + + if (!getenv("ethaddr")) { + printf("<ethaddr> not set. Validating first E-fuse MAC\n"); + + if (is_valid_ethaddr(mac_addr)) + eth_setenv_enetaddr("ethaddr", mac_addr); + } + + mac_lo = readl(&cdev->macid1l); + mac_hi = readl(&cdev->macid1h); + mac_addr[0] = mac_hi & 0xFF; + mac_addr[1] = (mac_hi & 0xFF00) >> 8; + mac_addr[2] = (mac_hi & 0xFF0000) >> 16; + mac_addr[3] = (mac_hi & 0xFF000000) >> 24; + mac_addr[4] = mac_lo & 0xFF; + mac_addr[5] = (mac_lo & 0xFF00) >> 8; + + if (!getenv("eth1addr")) { + if (is_valid_ethaddr(mac_addr)) + eth_setenv_enetaddr("eth1addr", mac_addr); + } +#endif + return 0; } #endif @@ -652,11 +755,15 @@ static struct cpsw_platform_data cpsw_data = { int board_eth_init(bd_t *bis) { int rv, n = 0; +#if defined(CONFIG_USB_ETHER) && \ + (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USBETH_SUPPORT)) uint8_t mac_addr[6]; uint32_t mac_hi, mac_lo; - __maybe_unused struct ti_am_eeprom *header; - /* try reading mac address from efuse */ + /* + * use efuse mac address for USB ethernet as we know that + * both CPSW and USB ethernet will never be active at the same time + */ mac_lo = readl(&cdev->macid0l); mac_hi = readl(&cdev->macid0h); mac_addr[0] = mac_hi & 0xFF; @@ -665,32 +772,13 @@ int board_eth_init(bd_t *bis) mac_addr[3] = (mac_hi & 0xFF000000) >> 24; mac_addr[4] = mac_lo & 0xFF; mac_addr[5] = (mac_lo & 0xFF00) >> 8; +#endif + #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) - if (!getenv("ethaddr")) { - printf("<ethaddr> not set. Validating first E-fuse MAC\n"); - - if (is_valid_ethaddr(mac_addr)) - eth_setenv_enetaddr("ethaddr", mac_addr); - } #ifdef CONFIG_DRIVER_TI_CPSW - - mac_lo = readl(&cdev->macid1l); - mac_hi = readl(&cdev->macid1h); - mac_addr[0] = mac_hi & 0xFF; - mac_addr[1] = (mac_hi & 0xFF00) >> 8; - mac_addr[2] = (mac_hi & 0xFF0000) >> 16; - mac_addr[3] = (mac_hi & 0xFF000000) >> 24; - mac_addr[4] = mac_lo & 0xFF; - mac_addr[5] = (mac_lo & 0xFF00) >> 8; - - if (!getenv("eth1addr")) { - if (is_valid_ethaddr(mac_addr)) - eth_setenv_enetaddr("eth1addr", mac_addr); - } - if (read_eeprom() < 0) puts("Could not get board ID.\n"); @@ -243,9 +243,6 @@ static int netboot_common(enum proto_t proto, cmd_tbl_t *cmdtp, int argc, return CMD_RET_SUCCESS; } - /* flush cache */ - flush_cache(load_addr, size); - bootstage_mark(BOOTSTAGE_ID_NET_LOADED); rcode = bootm_maybe_autostart(cmdtp, argv[0]); diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index d17505e..d1f024e 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -225,6 +225,18 @@ struct cpdma_chan { void *hdp, *cp, *rxfree; }; +/* AM33xx SoC specific definitions for the CONTROL port */ +#define AM33XX_GMII_SEL_MODE_MII 0 +#define AM33XX_GMII_SEL_MODE_RMII 1 +#define AM33XX_GMII_SEL_MODE_RGMII 2 + +#define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4) +#define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5) +#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6) +#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7) + +#define GMII_SEL_MODE_MASK 0x3 + #define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld) #define desc_read(desc, fld) __raw_readl(&(desc)->fld) #define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld)) @@ -1150,12 +1162,129 @@ static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node) false); } +static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, + phy_interface_t phy_mode) +{ + u32 reg; + u32 mask; + u32 mode = 0; + bool rgmii_id = false; + int slave = priv->data.active_slave; + + reg = readl(priv->data.gmii_sel); + + switch (phy_mode) { + case PHY_INTERFACE_MODE_RMII: + mode = AM33XX_GMII_SEL_MODE_RMII; + break; + + case PHY_INTERFACE_MODE_RGMII: + mode = AM33XX_GMII_SEL_MODE_RGMII; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + mode = AM33XX_GMII_SEL_MODE_RGMII; + rgmii_id = true; + break; + + case PHY_INTERFACE_MODE_MII: + default: + mode = AM33XX_GMII_SEL_MODE_MII; + break; + }; + + mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6); + mode <<= slave * 2; + + if (priv->data.rmii_clock_external) { + if (slave == 0) + mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN; + else + mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN; + } + + if (rgmii_id) { + if (slave == 0) + mode |= AM33XX_GMII_SEL_RGMII1_IDMODE; + else + mode |= AM33XX_GMII_SEL_RGMII2_IDMODE; + } + + reg &= ~mask; + reg |= mode; + + writel(reg, priv->data.gmii_sel); +} + +static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, + phy_interface_t phy_mode) +{ + u32 reg; + u32 mask; + u32 mode = 0; + int slave = priv->data.active_slave; + + reg = readl(priv->data.gmii_sel); + + switch (phy_mode) { + case PHY_INTERFACE_MODE_RMII: + mode = AM33XX_GMII_SEL_MODE_RMII; + break; + + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + mode = AM33XX_GMII_SEL_MODE_RGMII; + break; + + case PHY_INTERFACE_MODE_MII: + default: + mode = AM33XX_GMII_SEL_MODE_MII; + break; + }; + + switch (slave) { + case 0: + mask = GMII_SEL_MODE_MASK; + break; + case 1: + mask = GMII_SEL_MODE_MASK << 4; + mode <<= 4; + break; + default: + dev_err(priv->dev, "invalid slave number...\n"); + return; + } + + if (priv->data.rmii_clock_external) + dev_err(priv->dev, "RMII External clock is not supported\n"); + + reg &= ~mask; + reg |= mode; + + writel(reg, priv->data.gmii_sel); +} + +static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, + phy_interface_t phy_mode) +{ + if (!strcmp(compat, "ti,am3352-cpsw-phy-sel")) + cpsw_gmii_sel_am3352(priv, phy_mode); + if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel")) + cpsw_gmii_sel_am3352(priv, phy_mode); + else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel")) + cpsw_gmii_sel_dra7xx(priv, phy_mode); +} + static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); struct cpsw_priv *priv = dev_get_priv(dev); struct gpio_desc *mode_gpios; const char *phy_mode; + const char *phy_sel_compat = NULL; const void *fdt = gd->fdt_blob; int node = dev->of_offset; int subnode; @@ -1271,6 +1400,17 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) error("Not able to get gmii_sel reg address\n"); return -ENOENT; } + + if (fdt_get_property(fdt, subnode, "rmii-clock-ext", + NULL)) + priv->data.rmii_clock_external = true; + + phy_sel_compat = fdt_getprop(fdt, subnode, "compatible", + NULL); + if (!phy_sel_compat) { + error("Not able to get gmii_sel compatible\n"); + return -ENOENT; + } } } @@ -1293,20 +1433,9 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); return -EINVAL; } - switch (pdata->phy_interface) { - case PHY_INTERFACE_MODE_MII: - writel(MII_MODE_ENABLE, priv->data.gmii_sel); - break; - case PHY_INTERFACE_MODE_RMII: - writel(RMII_MODE_ENABLE, priv->data.gmii_sel); - break; - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - writel(RGMII_MODE_ENABLE, priv->data.gmii_sel); - break; - } + + /* Select phy interface in control module */ + cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface); return 0; } diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index 51bb569..00f378f 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -1619,7 +1619,7 @@ static int mvneta_probe(struct udevice *dev) /* * Allocate buffer area for descs and rx_buffers. This is only * done once for all interfaces. As only one interface can - * be active. Make this area DMA save by disabling the D-cache + * be active. Make this area DMA safe by disabling the D-cache */ if (!buffer_loc.tx_descs) { /* Align buffer area for descs and rx_buffers to 1MiB */ diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c index e57c412..b34cdd3 100644 --- a/drivers/net/phy/atheros.c +++ b/drivers/net/phy/atheros.c @@ -8,6 +8,15 @@ */ #include <phy.h> +#define AR803x_PHY_DEBUG_ADDR_REG 0x1d +#define AR803x_PHY_DEBUG_DATA_REG 0x1e + +#define AR803x_DEBUG_REG_5 0x5 +#define AR803x_RGMII_TX_CLK_DLY 0x100 + +#define AR803x_DEBUG_REG_0 0x0 +#define AR803x_RGMII_RX_CLK_DLY 0x8000 + static int ar8021_config(struct phy_device *phydev) { phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); @@ -17,6 +26,32 @@ static int ar8021_config(struct phy_device *phydev) return 0; } +static int ar8031_config(struct phy_device *phydev) +{ + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, + AR803x_DEBUG_REG_5); + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, + AR803x_RGMII_TX_CLK_DLY); + } + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG, + AR803x_DEBUG_REG_0); + phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG, + AR803x_RGMII_RX_CLK_DLY); + } + + phydev->supported = phydev->drv->features; + + genphy_config_aneg(phydev); + genphy_restart_aneg(phydev); + + return 0; +} + static int ar8035_config(struct phy_device *phydev) { int regval; @@ -31,6 +66,22 @@ static int ar8035_config(struct phy_device *phydev) regval = phy_read(phydev, MDIO_DEVAD_NONE, 0x1e); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, (regval|0x0100)); + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { + /* select debug reg 5 */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1D, 0x5); + /* enable tx delay */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1E, 0x0100); + } + + if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || + (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) { + /* select debug reg 0 */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1D, 0x0); + /* enable rx delay */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1E, 0x8000); + } + phydev->supported = phydev->drv->features; genphy_config_aneg(phydev); @@ -54,7 +105,7 @@ static struct phy_driver AR8031_driver = { .uid = 0x4dd074, .mask = 0xffffffef, .features = PHY_GBIT_FEATURES, - .config = ar8035_config, + .config = ar8031_config, .startup = genphy_startup, .shutdown = genphy_shutdown, }; diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c index 74d5609..a2fd168 100644 --- a/drivers/net/phy/mv88e61xx.c +++ b/drivers/net/phy/mv88e61xx.c @@ -40,7 +40,7 @@ #define PHY_AUTONEGOTIATE_TIMEOUT 5000 -#define PORT_COUNT 7 +#define PORT_COUNT 11 #define PORT_MASK ((1 << PORT_COUNT) - 1) /* Device addresses */ @@ -103,8 +103,16 @@ #define PORT_REG_STATUS_CMODE_1000BASE_X 0x9 #define PORT_REG_STATUS_CMODE_SGMII 0xa +#define PORT_REG_PHYS_CTRL_PCS_AN_EN BIT(10) +#define PORT_REG_PHYS_CTRL_PCS_AN_RST BIT(9) +#define PORT_REG_PHYS_CTRL_FC_VALUE BIT(7) +#define PORT_REG_PHYS_CTRL_FC_FORCE BIT(6) #define PORT_REG_PHYS_CTRL_LINK_VALUE BIT(5) #define PORT_REG_PHYS_CTRL_LINK_FORCE BIT(4) +#define PORT_REG_PHYS_CTRL_DUPLEX_VALUE BIT(3) +#define PORT_REG_PHYS_CTRL_DUPLEX_FORCE BIT(2) +#define PORT_REG_PHYS_CTRL_SPD1000 BIT(1) +#define PORT_REG_PHYS_CTRL_SPD_MASK (BIT(1) | BIT(0)) #define PORT_REG_CTRL_PSTATE_SHIFT 0 #define PORT_REG_CTRL_PSTATE_WIDTH 2 @@ -166,7 +174,17 @@ #error Define CONFIG_MV88E61XX_CPU_PORT to the port the CPU is attached to #endif +/* + * These are ports without PHYs that may be wired directly + * to other serdes interfaces + */ +#ifndef CONFIG_MV88E61XX_FIXED_PORTS +#define CONFIG_MV88E61XX_FIXED_PORTS 0 +#endif + /* ID register values for different switch models */ +#define PORT_SWITCH_ID_6096 0x0980 +#define PORT_SWITCH_ID_6097 0x0990 #define PORT_SWITCH_ID_6172 0x1720 #define PORT_SWITCH_ID_6176 0x1760 #define PORT_SWITCH_ID_6240 0x2400 @@ -580,7 +598,7 @@ static int mv88e61xx_port_enable(struct phy_device *phydev, u8 port) } static int mv88e61xx_port_set_vlan(struct phy_device *phydev, u8 port, - u8 mask) + u16 mask) { int val; @@ -791,6 +809,27 @@ static int mv88e61xx_phy_setup(struct phy_device *phydev, u8 phy) return 0; } +static int mv88e61xx_fixed_port_setup(struct phy_device *phydev, u8 port) +{ + int val; + + val = mv88e61xx_port_read(phydev, port, PORT_REG_PHYS_CTRL); + if (val < 0) + return val; + + val &= ~(PORT_REG_PHYS_CTRL_SPD_MASK | + PORT_REG_PHYS_CTRL_FC_VALUE); + val |= PORT_REG_PHYS_CTRL_PCS_AN_EN | + PORT_REG_PHYS_CTRL_PCS_AN_RST | + PORT_REG_PHYS_CTRL_FC_FORCE | + PORT_REG_PHYS_CTRL_DUPLEX_VALUE | + PORT_REG_PHYS_CTRL_DUPLEX_FORCE | + PORT_REG_PHYS_CTRL_SPD1000; + + return mv88e61xx_port_write(phydev, port, PORT_REG_PHYS_CTRL, + val); +} + static int mv88e61xx_phy_config_port(struct phy_device *phydev, u8 phy) { int val; @@ -909,6 +948,12 @@ static int mv88e61xx_phy_config(struct phy_device *phydev) /* Return success if any PHY succeeds */ ret = 0; + } else if ((1 << i) & CONFIG_MV88E61XX_FIXED_PORTS) { + res = mv88e61xx_fixed_port_setup(phydev, i); + if (res < 0) { + printf("Error configuring port %i\n", i); + continue; + } } } @@ -974,9 +1019,21 @@ static struct phy_driver mv88e61xx_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver mv88e609x_driver = { + .name = "Marvell MV88E609x", + .uid = 0x1410c89, + .mask = 0xfffffff0, + .features = PHY_GBIT_FEATURES, + .probe = mv88e61xx_probe, + .config = mv88e61xx_phy_config, + .startup = mv88e61xx_phy_startup, + .shutdown = &genphy_shutdown, +}; + int phy_mv88e61xx_init(void) { phy_register(&mv88e61xx_driver); + phy_register(&mv88e609x_driver); return 0; } diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 1cc0b40..a3f4423 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -629,11 +629,12 @@ static int rtl_send_common(pci_dev_t dev, unsigned long dev_iobase, /* point to the current txb incase multiple tx_rings are used */ ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE]; memcpy(ptxb, (char *)packet, (int)length); - rtl_flush_buffer(ptxb, length); while (len < ETH_ZLEN) ptxb[len++] = '\0'; + rtl_flush_buffer(ptxb, ALIGN(len, RTL8169_ALIGN)); + tpc->TxDescArray[entry].buf_Haddr = 0; #ifdef CONFIG_DM_ETH tpc->TxDescArray[entry].buf_addr = cpu_to_le32( diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c index 7d9abfd..d4c8ea4 100644 --- a/drivers/usb/eth/smsc95xx.c +++ b/drivers/usb/eth/smsc95xx.c @@ -519,9 +519,11 @@ static int smsc95xx_init_common(struct usb_device *udev, struct ueth_data *dev, debug("timeout waiting for PHY Reset\n"); return -ETIMEDOUT; } +#ifndef CONFIG_DM_ETH if (!priv->have_hwaddr && smsc95xx_init_mac_address(enetaddr, udev) == 0) priv->have_hwaddr = 1; +#endif if (!priv->have_hwaddr) { puts("Error: SMSC95xx: No MAC address set - set usbethaddr\n"); return -EADDRNOTAVAIL; @@ -1022,6 +1024,19 @@ int smsc95xx_write_hwaddr(struct udevice *dev) return smsc95xx_write_hwaddr_common(udev, priv, pdata->enetaddr); } +int smsc95xx_read_rom_hwaddr(struct udevice *dev) +{ + struct usb_device *udev = dev_get_parent_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + int ret; + + ret = smsc95xx_init_mac_address(pdata->enetaddr, udev); + if (ret) + memset(pdata->enetaddr, 0, 6); + + return 0; +} + static int smsc95xx_eth_probe(struct udevice *dev) { struct smsc95xx_private *priv = dev_get_priv(dev); @@ -1037,6 +1052,7 @@ static const struct eth_ops smsc95xx_eth_ops = { .free_pkt = smsc95xx_free_pkt, .stop = smsc95xx_eth_stop, .write_hwaddr = smsc95xx_write_hwaddr, + .read_rom_hwaddr = smsc95xx_read_rom_hwaddr, }; U_BOOT_DRIVER(smsc95xx_eth) = { diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index 272c71b..daa7dd8 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -432,6 +432,8 @@ #define CONFIG_PHY_GIGE #define CONFIG_PHYLIB #define CONFIG_PHY_SMSC +/* Enable Atheros phy driver */ +#define CONFIG_PHY_ATHEROS /* * NOR Size = 16 MiB diff --git a/include/cpsw.h b/include/cpsw.h index 257d12a..f135e7b 100644 --- a/include/cpsw.h +++ b/include/cpsw.h @@ -48,6 +48,7 @@ struct cpsw_platform_data { void (*control)(int enabled); u32 host_port_num; u32 active_slave; + bool rmii_clock_external; u8 version; }; diff --git a/net/eth-uclass.c b/net/eth-uclass.c index c15cc4d..a32961e 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -227,6 +227,7 @@ static int on_ethaddr(const char *name, const char *value, enum env_op op, case env_op_create: case env_op_overwrite: eth_parse_enetaddr(value, pdata->enetaddr); + eth_write_hwaddr(dev); break; case env_op_delete: memset(pdata->enetaddr, 0, 6); diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py index 4ab58b4..0884051 100644 --- a/test/py/tests/test_net.py +++ b/test/py/tests/test_net.py @@ -47,6 +47,15 @@ env__net_tftp_readable_file = { "size": 5058624, "crc32": "c2244b26", } + +# Details regarding a file that may be read from a NFS server. This variable +# may be omitted or set to None if NFS testing is not possible or desired. +env__net_nfs_readable_file = { + "fn": "ubtest-readable.bin", + "addr": 0x10000000, + "size": 5058624, + "crc32": "c2244b26", +} """ net_set_up = False @@ -157,3 +166,43 @@ def test_net_tftpboot(u_boot_console): output = u_boot_console.run_command('crc32 %x $filesize' % addr) assert expected_crc in output + +@pytest.mark.buildconfigspec('cmd_nfs') +def test_net_nfs(u_boot_console): + """Test the nfs command. + + A file is downloaded from the NFS server, its size and optionally its + CRC32 are validated. + + The details of the file to download are provided by the boardenv_* file; + see the comment at the beginning of this file. + """ + + if not net_set_up: + pytest.skip('Network not initialized') + + f = u_boot_console.config.env.get('env__net_nfs_readable_file', None) + if not f: + pytest.skip('No NFS readable file to read') + + addr = f.get('addr', None) + if not addr: + addr = u_boot_utils.find_ram_base(u_boot_console) + + fn = f['fn'] + output = u_boot_console.run_command('nfs %x %s' % (addr, fn)) + expected_text = 'Bytes transferred = ' + sz = f.get('size', None) + if sz: + expected_text += '%d' % sz + assert expected_text in output + + expected_crc = f.get('crc32', None) + if not expected_crc: + return + + if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y': + return + + output = u_boot_console.run_command('crc32 %x $filesize' % addr) + assert expected_crc in output |