From 449ea2cd0d0c4e46c5b2b21480f34523dd928e33 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Sun, 26 Mar 2017 18:50:23 +0200 Subject: net: Kconfig:make PHY_GIGE and individual Micrel PHYs selectable This change migrate the following configuration options for Kconfig: * PHY_GIGE, indicates that a controller (with an appropriate PHY) is Gigabit capable and enables extra support in the miiutil for parsing the status of Gigabit PHYs * adds configuration options for Micrel KSZ9021 and KSZ9031 GbE PHYs, which previously had to enabled through a board-specific config file Signed-off-by: Philipp Tomsich Acked-by: Maxime Ripard Acked-by: Joe Hershberger --- drivers/net/Kconfig | 8 ++++++++ drivers/net/phy/Kconfig | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d49bf57..33634c3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -22,6 +22,13 @@ menuconfig NETDEVICES if NETDEVICES +config PHY_GIGE + bool "Enable GbE PHY status parsing and configuration" + help + Enables support for parsing the status output and for + configuring GbE PHYs (affects the inner workings of some + commands and miiphyutil.c). + config AG7XXX bool "Atheros AG7xxx Ethernet MAC support" depends on DM_ETH && ARCH_ATH79 @@ -187,6 +194,7 @@ config SUN8I_EMAC bool "Allwinner Sun8i Ethernet MAC support" depends on DM_ETH select PHYLIB + select PHY_GIGE help This driver supports the Allwinner based SUN8I/SUN50I Ethernet MAC. It can be found in H3/A64/A83T based SoCs and compatible with both diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index aca3990..1afd809 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -57,6 +57,40 @@ config PHY_MARVELL config PHY_MICREL bool "Micrel Ethernet PHYs support" + help + Enable support for the GbE PHYs manufactured by Micrel (now + a part of Microchip). This includes drivers for the KSZ804, + KSZ8031, KSZ8051, KSZ8081, KSZ8895, KSZ886x, KSZ8721 + either/or KSZ9021 (see the "Micrel KSZ9021 family support" + config option for details), and KSZ9031 (if configured). + +if PHY_MICREL + +config PHY_MICREL_KSZ9021 + bool "Micrel KSZ9021 family support" + select PHY_GIGE + help + Enable support for the Micrel KSZ9021 GbE PHY family. If + enabled, the extended register read/write for KSZ9021 PHYs + is supported through the 'mdio' command and any RGMII signal + delays configured in the device tree will be applied to the + PHY during initialisation. + + Note that the KSZ9021 uses the same part number os the + KSZ8921BL, so enabling this option disables support for the + KSZ8721BL. + +config PHY_MICREL_KSZ9031 + bool "Micrel KSZ9031 family support" + select PHY_GIGE + help + Enable support for the Micrel KSZ9031 GbE PHY family. If + enabled, the extended register read/write for KSZ9021 PHYs + is supported through the 'mdio' command and any RGMII signal + delays configured in the device tree will be applied to the + PHY during initialisatioin. + +endif # PHY_MICREL config PHY_MSCC bool "Microsemi Corp Ethernet PHYs support" -- cgit v1.1 From 6ec922fae20f791882ee455286b1fefd5372a79a Mon Sep 17 00:00:00 2001 From: Jacob Chen Date: Mon, 27 Mar 2017 16:54:17 +0800 Subject: net: designware: Add phy supply support Some board need a regulator for gmac phy, so add this code to handle it. Signed-off-by: Jacob Chen Acked-by: Joe Hershberger --- drivers/net/designware.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/net/designware.c b/drivers/net/designware.c index e3a194c..e8569e6 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "designware.h" DECLARE_GLOBAL_DATA_PTR; @@ -661,6 +662,22 @@ int designware_eth_probe(struct udevice *dev) ulong ioaddr; int ret; +#if defined(CONFIG_DM_REGULATOR) + struct udevice *phy_supply; + + ret = device_get_supply_regulator(dev, "phy-supply", + &phy_supply); + if (ret) { + debug("%s: No phy supply\n", dev->name); + } else { + ret = regulator_set_enable(phy_supply, true); + if (ret) { + puts("Error enabling phy supply\n"); + return ret; + } + } +#endif + #ifdef CONFIG_DM_PCI /* * If we are on PCI bus, either directly attached to a PCI root port, -- cgit v1.1 From b233089787601d63e44d8d3ddb7d2731ef53cf4e Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Mon, 3 Apr 2017 16:18:53 +0200 Subject: net: zynq_gem: Do not return -ENOSYS on success The .read_rom_hwaddr net_ops hook does not check the return value, which is why it was never caught that we are currently returning 0 if the read_rom_hwaddr function return -ENOSYS and -ENOSYS otherwise. In this case we can simplify this by just returning the result of the function. Signed-off-by: Olliver Schinagl Acked-by: Joe Hershberger Acked-by: Michal Simek --- drivers/net/zynq_gem.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 1bb7fa5..f3d6727 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -587,14 +587,12 @@ __weak int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) static int zynq_gem_read_rom_mac(struct udevice *dev) { - int retval; struct eth_pdata *pdata = dev_get_platdata(dev); - retval = zynq_board_read_rom_ethaddr(pdata->enetaddr); - if (retval == -ENOSYS) - retval = 0; + if (!pdata) + return -ENOSYS; - return retval; + return zynq_board_read_rom_ethaddr(pdata->enetaddr); } static int zynq_gem_miiphy_read(struct mii_dev *bus, int addr, -- cgit v1.1 From 5a78a472f6660a72b9343a93791353ac879eeed0 Mon Sep 17 00:00:00 2001 From: Madalin Bucur Date: Mon, 3 Apr 2017 17:43:55 +0300 Subject: armv8/ls1043a: RGMII PHY requires internal delay on Tx Signed-off-by: Madalin Bucur Acked-by: Joe Hershberger --- drivers/net/fm/ls1043.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/ls1043.c b/drivers/net/fm/ls1043.c index 93ba318..6bb6a71 100644 --- a/drivers/net/fm/ls1043.c +++ b/drivers/net/fm/ls1043.c @@ -66,12 +66,12 @@ phy_interface_t fman_port_enet_if(enum fm_port port) if (port == FM1_DTSEC3) if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC1) == FSL_CHASSIS2_RCWSR13_EC1_DTSEC3_RGMII) { - return PHY_INTERFACE_MODE_RGMII; + return PHY_INTERFACE_MODE_RGMII_TXID; } if (port == FM1_DTSEC4) if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC2) == FSL_CHASSIS2_RCWSR13_EC2_DTSEC4_RGMII) { - return PHY_INTERFACE_MODE_RGMII; + return PHY_INTERFACE_MODE_RGMII_TXID; } /* handle SGMII */ -- cgit v1.1 From cc1aa218f51088230149aa4fc8930ef1d6e36a0b Mon Sep 17 00:00:00 2001 From: Madalin Bucur Date: Mon, 3 Apr 2017 17:43:56 +0300 Subject: armv8/ls1046a: RGMII PHY requires internal delay on Tx Signed-off-by: Madalin Bucur Acked-by: Joe Hershberger --- drivers/net/fm/ls1046.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fm/ls1046.c b/drivers/net/fm/ls1046.c index bf55554..6c91fb9 100644 --- a/drivers/net/fm/ls1046.c +++ b/drivers/net/fm/ls1046.c @@ -72,12 +72,12 @@ phy_interface_t fman_port_enet_if(enum fm_port port) if (port == FM1_DTSEC3) if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC1) == FSL_CHASSIS2_RCWSR13_EC1_DTSEC3_RGMII) - return PHY_INTERFACE_MODE_RGMII; + return PHY_INTERFACE_MODE_RGMII_TXID; if (port == FM1_DTSEC4) if ((rcwsr13 & FSL_CHASSIS2_RCWSR13_EC2) == FSL_CHASSIS2_RCWSR13_EC2_DTSEC4_RGMII) - return PHY_INTERFACE_MODE_RGMII; + return PHY_INTERFACE_MODE_RGMII_TXID; /* handle SGMII, only MAC 2/5/6/9/10 available */ switch (port) { -- cgit v1.1 From e09d0c8314933e586de6549581e35cb21f8b4da2 Mon Sep 17 00:00:00 2001 From: Stefan Chulski Date: Thu, 6 Apr 2017 15:39:08 +0200 Subject: net: mvpp2.c: Enable 10G support for port 0 (SFI) This patch fixes some remaining issues in the mvpp2 driver for the 10GB support on port 0. These changes are: - Incorrect PCS configuration - Skip PHY configuration when no PHY is connected - Skip GMAC configurations if 10G SFI mode set Signed-off-by: Stefan Chulski Signed-off-by: Stefan Roese Cc: Kostya Porotchkin Cc: Nadav Haklai Cc: Joe Hershberger Acked-by: Joe Hershberger --- drivers/net/mvpp2.c | 55 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index 6dc7239..1b46218 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -442,7 +442,7 @@ do { \ /* MPCS registers */ #define PCS40G_COMMON_CONTROL 0x14 -#define FORWARD_ERROR_CORRECTION_MASK BIT(1) +#define FORWARD_ERROR_CORRECTION_MASK BIT(10) #define PCS_CLOCK_RESET 0x14c #define TX_SD_CLK_RESET_MASK BIT(0) @@ -3251,7 +3251,7 @@ static int gop_xpcs_mode(struct mvpp2_port *port, int num_of_lanes) /* configure XG MAC mode */ val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG); - val &= ~MVPP22_XPCS_PCSMODE_OFFS; + val &= ~MVPP22_XPCS_PCSMODE_MASK; val &= ~MVPP22_XPCS_LANEACTIVE_MASK; val |= (2 * lane) << MVPP22_XPCS_LANEACTIVE_OFFS; writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG); @@ -4479,7 +4479,15 @@ static int mvpp2_rx_refill(struct mvpp2_port *port, /* Set hw internals when starting port */ static void mvpp2_start_dev(struct mvpp2_port *port) { - mvpp2_gmac_max_rx_size_set(port); + switch (port->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_SGMII: + mvpp2_gmac_max_rx_size_set(port); + default: + break; + } + mvpp2_txp_max_tx_size_set(port); if (port->priv->hw_version == MVPP21) @@ -4574,11 +4582,16 @@ static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port) return err; } - err = mvpp2_phy_connect(dev, port); - if (err < 0) - return err; + if (port->phy_node) { + err = mvpp2_phy_connect(dev, port); + if (err < 0) + return err; - mvpp2_link_event(port); + mvpp2_link_event(port); + } else { + mvpp2_egress_enable(port); + mvpp2_ingress_enable(port); + } mvpp2_start_dev(port); @@ -4723,13 +4736,19 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) const char *phy_mode_str; int phy_node; u32 id; - u32 phyaddr; + u32 phyaddr = 0; int phy_mode = -1; phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy"); - if (phy_node < 0) { - dev_err(&pdev->dev, "missing phy\n"); - return -ENODEV; + + if (phy_node > 0) { + phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0); + if (phyaddr < 0) { + dev_err(&pdev->dev, "could not find phy address\n"); + return -1; + } + } else { + phy_node = 0; } phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, "phy-mode", NULL); @@ -4755,8 +4774,6 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port) port->phy_speed = fdtdec_get_int(gd->fdt_blob, port_node, "phy-speed", 1000); - phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0); - port->id = id; if (port->priv->hw_version == MVPP21) port->first_rxq = port->id * rxq_number; @@ -5316,7 +5333,14 @@ static int mvpp2_start(struct udevice *dev) /* Reconfigure parser accept the original MAC address */ mvpp2_prs_update_mac_da(port, port->dev_addr); - mvpp2_port_power_up(port); + switch (port->phy_interface) { + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_SGMII: + mvpp2_port_power_up(port); + default: + break; + } mvpp2_open(dev, port); @@ -5479,7 +5503,8 @@ static int mvpp2_probe(struct udevice *dev) port->gop_id * MVPP22_PORT_OFFSET; /* Set phy address of the port */ - mvpp22_smi_phy_addr_cfg(port); + if(port->phy_node) + mvpp22_smi_phy_addr_cfg(port); /* GoP Init */ gop_port_init(port); -- cgit v1.1 From 6de046eaa74a2a0fb68f1055a1d38bc93f4f16c7 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Thu, 20 Apr 2017 11:13:13 +0800 Subject: net: macb: Fix GMAC not work when enable DM_ETH Always search the PHY to determine the macb->phy_addr before using the PHY to fix "No PHY present" error. Fix the wrong test of the GMAC's phy interface mode, it should be PHY_INTERFACE_MODE_RGMII. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- drivers/net/macb.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/macb.c b/drivers/net/macb.c index bbbdb74..f9373db 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -450,7 +450,6 @@ static void macb_phy_reset(struct macb_device *macb, const char *name) name, status); } -#ifdef CONFIG_MACB_SEARCH_PHY static int macb_phy_find(struct macb_device *macb, const char *name) { int i; @@ -471,7 +470,6 @@ static int macb_phy_find(struct macb_device *macb, const char *name) return 0; } -#endif /* CONFIG_MACB_SEARCH_PHY */ #ifdef CONFIG_DM_ETH static int macb_phy_init(struct udevice *dev, const char *name) @@ -488,11 +486,9 @@ static int macb_phy_init(struct macb_device *macb, const char *name) int i; arch_get_mdio_control(name); -#ifdef CONFIG_MACB_SEARCH_PHY /* Auto-detect phy_addr */ if (!macb_phy_find(macb, name)) return 0; -#endif /* CONFIG_MACB_SEARCH_PHY */ /* Check if the PHY is up to snuff... */ phy_id = macb_mdio_read(macb, MII_PHYSID1); @@ -667,7 +663,8 @@ static int _macb_init(struct macb_device *macb, const char *name) * to select interface between RMII and MII. */ #ifdef CONFIG_DM_ETH - if (macb->phy_interface == PHY_INTERFACE_MODE_RMII) + if ((macb->phy_interface == PHY_INTERFACE_MODE_RMII) || + (macb->phy_interface == PHY_INTERFACE_MODE_RGMII)) gem_writel(macb, UR, GEM_BIT(RGMII)); else gem_writel(macb, UR, 0); -- cgit v1.1 From 96d1d84c79b63e5882f09be451227f7145ea8599 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Mon, 8 May 2017 20:49:56 +0530 Subject: drivers: net: cpsw: abort init() on aneg timeout Abort CPSW driver init when auto-negotiation of link times out. Currently, the code ignores return status of phy_startup(), and goes ahead with network operation (like DHCP) even though the link may be down. Instead, abort init process if link is down or if there is another error, so phy_startup() can easily be retried again. This also helps quick fallback to next network interface (like USB RNDIS) without inordinate delay. Tested on AM571x IDK and AM335x BeagleBone black. Signed-off-by: Sekhar Nori Reviewed-by: Tom Rini Acked-by: Joe Hershberger --- drivers/net/cpsw.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index 778d2f5..d7db0fc 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -612,21 +612,25 @@ static void cpsw_set_slave_mac(struct cpsw_slave *slave, #endif } -static void cpsw_slave_update_link(struct cpsw_slave *slave, +static int cpsw_slave_update_link(struct cpsw_slave *slave, struct cpsw_priv *priv, int *link) { struct phy_device *phy; u32 mac_control = 0; + int ret = -ENODEV; phy = priv->phydev; - if (!phy) - return; + goto out; + + ret = phy_startup(phy); + if (ret) + goto out; - phy_startup(phy); - *link = phy->link; + if (link) + *link = phy->link; - if (*link) { /* link up */ + if (phy->link) { /* link up */ mac_control = priv->data.mac_control; if (phy->speed == 1000) mac_control |= GIGABITEN; @@ -637,7 +641,7 @@ static void cpsw_slave_update_link(struct cpsw_slave *slave, } if (mac_control == slave->mac_control) - return; + goto out; if (mac_control) { printf("link up on port %d, speed %d, %s duplex\n", @@ -649,17 +653,20 @@ static void cpsw_slave_update_link(struct cpsw_slave *slave, __raw_writel(mac_control, &slave->sliver->mac_control); slave->mac_control = mac_control; + +out: + return ret; } static int cpsw_update_link(struct cpsw_priv *priv) { - int link = 0; + int ret = -ENODEV; struct cpsw_slave *slave; for_active_slave(slave, priv) - cpsw_slave_update_link(slave, priv, &link); + ret = cpsw_slave_update_link(slave, priv, NULL); - return link; + return ret; } static inline u32 cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num) @@ -822,7 +829,9 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) for_active_slave(slave, priv) cpsw_slave_init(slave, priv); - cpsw_update_link(priv); + ret = cpsw_update_link(priv); + if (ret) + goto out; /* init descriptor pool */ for (i = 0; i < NUM_DESCS; i++) { @@ -897,7 +906,8 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) } } - return 0; +out: + return ret; } static void _cpsw_halt(struct cpsw_priv *priv) -- cgit v1.1 From 68e6ecadc551250a73ff28e970440955f3e46ac2 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Wed, 24 May 2017 14:43:06 +0100 Subject: net: phy: marvell 88e151x: Fix handling of RGMII interface types The 88E1518 code is programming the wrong registers for rgmii-id, rgmii-txid and rgmii-rxid interfaces. Since the PHY defaults to rgmii-id, it would appear that the code was previously only used with sgmii and rgmii-id interfaces. Tested on 88E1512 PHY in rgmii-id mode which is from the same family as 88E1518. Signed-off-by: Phil Edworthy Acked-by: Joe Hershberger --- drivers/net/phy/marvell.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index ab0c443..8041922 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -13,6 +13,8 @@ #define PHY_AUTONEGOTIATE_TIMEOUT 5000 +#define MII_MARVELL_PHY_PAGE 22 + /* 88E1011 PHY Status Register */ #define MIIM_88E1xxx_PHY_STATUS 0x11 #define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000 @@ -83,6 +85,11 @@ #define MIIM_88E1310_PHY_PAGE 22 /* 88E151x PHY defines */ +/* Page 2 registers */ +#define MIIM_88E151x_PHY_MSCR 21 +#define MIIM_88E151x_RGMII_RX_DELAY BIT(5) +#define MIIM_88E151x_RGMII_TX_DELAY BIT(4) +#define MIIM_88E151x_RGMII_RXTX_DELAY (BIT(5) | BIT(4)) /* Page 3 registers */ #define MIIM_88E151x_LED_FUNC_CTRL 16 #define MIIM_88E151x_LED_FLD_SZ 4 @@ -295,6 +302,8 @@ void m88e1518_phy_writebits(struct phy_device *phydev, static int m88e1518_config(struct phy_device *phydev) { + u16 reg; + /* * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 * /88E1514 Rev A0, Errata Section 3.1 @@ -331,7 +340,41 @@ static int m88e1518_config(struct phy_device *phydev) udelay(100); } - return m88e1111s_config(phydev); + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + reg = phy_read(phydev, MDIO_DEVAD_NONE, + MIIM_88E1111_PHY_EXT_SR); + + reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); + reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; + reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; + + phy_write(phydev, MDIO_DEVAD_NONE, + MIIM_88E1111_PHY_EXT_SR, reg); + } + + if (phy_interface_is_rgmii(phydev)) { + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 2); + + reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR); + reg &= ~MIIM_88E151x_RGMII_RXTX_DELAY; + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + reg |= MIIM_88E151x_RGMII_RXTX_DELAY; + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) + reg |= MIIM_88E151x_RGMII_RX_DELAY; + else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) + reg |= MIIM_88E151x_RGMII_TX_DELAY; + phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR, reg); + + phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 0); + } + + /* soft reset */ + phy_reset(phydev); + + genphy_config_aneg(phydev); + genphy_restart_aneg(phydev); + + return 0; } /* Marvell 88E1510 */ -- cgit v1.1 From dea004e41a6d1aa8ebf668c450962db45a41b373 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 30 May 2017 14:28:39 +0200 Subject: net: zynq_gem: Use wait_for_bit with non breakable Use wait_for_bit to be non breakable as using it with breakable causes issue of un interruptible auto negotiation. This is due to the ctrlc pressed will taken for wait_for_bit() abort during phy_read() and hence not coming out of auto negotiation. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek Acked-by: Joe Hershberger --- drivers/net/zynq_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index f3d6727..d3919be 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -192,7 +192,7 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum, int err; err = wait_for_bit(__func__, ®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK, - true, 20000, true); + true, 20000, false); if (err) return err; @@ -205,7 +205,7 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum, writel(mgtcr, ®s->phymntnc); err = wait_for_bit(__func__, ®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK, - true, 20000, true); + true, 20000, false); if (err) return err; -- cgit v1.1 From f0b94c4bcd6f6975c4f8826aaf015038a5555b83 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Tue, 30 May 2017 14:28:40 +0200 Subject: net: zynq_gem: Dont flush dummy descriptors Dont flush dummy descriptors as they are already allocated from a region with dcache off. Tested this on Zynq(zc702) and ZynqMP(zcu102) boards. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek Acked-by: Joe Hershberger --- drivers/net/zynq_gem.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index d3919be..f6bbcdc 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -407,10 +407,6 @@ static int zynq_gem_init(struct udevice *dev) dummy_rx_bd->addr = ZYNQ_GEM_RXBUF_WRAP_MASK | ZYNQ_GEM_RXBUF_NEW_MASK; dummy_rx_bd->status = 0; - flush_dcache_range((ulong)&dummy_tx_bd, (ulong)&dummy_tx_bd + - sizeof(dummy_tx_bd)); - flush_dcache_range((ulong)&dummy_rx_bd, (ulong)&dummy_rx_bd + - sizeof(dummy_rx_bd)); writel((ulong)dummy_tx_bd, ®s->transmit_q1_ptr); writel((ulong)dummy_rx_bd, ®s->receive_q1_ptr); -- cgit v1.1 From 43979cbacb81a3211ea41d890152ec090578d37f Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sun, 30 Apr 2017 21:57:05 +0200 Subject: net: pch_gbe: Reset during probe Using the EG20T gigabit ethernet controller on the MIPS Boston board, we find that we have to reset the controller in order for the RGMII link to the PHY to become functional. Without doing so we constantly time out in pch_gbe_mdio_ready. Signed-off-by: Paul Burton Reviewed-by: Bin Meng Tested-by: Bin Meng Signed-off-by: Daniel Schwierzeck Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- drivers/net/pch_gbe.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index d40fff0..4aac0f6 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -422,6 +422,7 @@ int pch_gbe_probe(struct udevice *dev) struct pch_gbe_priv *priv; struct eth_pdata *plat = dev_get_platdata(dev); void *iobase; + int err; /* * The priv structure contains the descriptors and frame buffers which @@ -444,6 +445,10 @@ int pch_gbe_probe(struct udevice *dev) pch_gbe_mdio_init(dev->name, priv->mac_regs); priv->bus = miiphy_get_dev_by_name(dev->name); + err = pch_gbe_reset(dev); + if (err) + return err; + return pch_gbe_phy_init(dev); } -- cgit v1.1 From db225f1131ad97fdf9a5df3b8d8e013284827c5a Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sun, 30 Apr 2017 21:57:06 +0200 Subject: net: pch_gbe: Fix rx descriptor buffer addresses The loop to set up buffer addresses in rx descriptors always operated on descriptor 0, rather than on each descriptor sequentially. Fix this in order to setup correct buffer addresses for each descriptor. Signed-off-by: Paul Burton Signed-off-by: Daniel Schwierzeck Reviewed-by: Bin Meng Tested-by: Bin Meng Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- drivers/net/pch_gbe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index 4aac0f6..7d15616 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -117,8 +117,8 @@ static void pch_gbe_rx_descs_init(struct udevice *dev) memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM); for (i = 0; i < PCH_GBE_DESC_NUM; i++) - rx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, - (ulong)(priv->rx_buff[i])); + rx_desc[i].buffer_addr = dm_pci_phys_to_mem(priv->dev, + priv->rx_buff[i]); writel(dm_pci_phys_to_mem(priv->dev, (ulong)rx_desc), &mac_regs->rx_dsc_base); -- cgit v1.1 From 52e727c8eb449db8b8dcb38201cbe034c8fa3c04 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sun, 30 Apr 2017 21:57:07 +0200 Subject: net: pch_gbe: CPU accessible addresses are virtual Use the virt_to_bus & bus_to_virt functions rather than phys_to_bus & bus_to_phys, since the addresses accessed by the CPU will be virtual rather than physical. On MIPS physical & virtual addresses differ as we use virtual addresses in kseg0, and attempting to use physical addresses directly caused problems as they're in the user segment which would be mapped via the uninitialised TLB. Signed-off-by: Paul Burton Signed-off-by: Daniel Schwierzeck Reviewed-by: Bin Meng Tested-by: Bin Meng Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- drivers/net/pch_gbe.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index 7d15616..1432351 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -117,15 +117,15 @@ static void pch_gbe_rx_descs_init(struct udevice *dev) memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM); for (i = 0; i < PCH_GBE_DESC_NUM; i++) - rx_desc[i].buffer_addr = dm_pci_phys_to_mem(priv->dev, + rx_desc[i].buffer_addr = dm_pci_virt_to_mem(priv->dev, priv->rx_buff[i]); - writel(dm_pci_phys_to_mem(priv->dev, (ulong)rx_desc), + writel(dm_pci_virt_to_mem(priv->dev, rx_desc), &mac_regs->rx_dsc_base); writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1), &mac_regs->rx_dsc_size); - writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_desc + 1)), + writel(dm_pci_virt_to_mem(priv->dev, rx_desc + 1), &mac_regs->rx_dsc_sw_p); } @@ -137,11 +137,11 @@ static void pch_gbe_tx_descs_init(struct udevice *dev) memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM); - writel(dm_pci_phys_to_mem(priv->dev, (ulong)tx_desc), + writel(dm_pci_virt_to_mem(priv->dev, tx_desc), &mac_regs->tx_dsc_base); writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1), &mac_regs->tx_dsc_size); - writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_desc + 1)), + writel(dm_pci_virt_to_mem(priv->dev, tx_desc + 1), &mac_regs->tx_dsc_sw_p); } @@ -251,7 +251,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) if (length < 64) frame_ctrl |= PCH_GBE_TXD_CTRL_APAD; - tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (ulong)packet); + tx_desc->buffer_addr = dm_pci_virt_to_mem(priv->dev, packet); tx_desc->length = length; tx_desc->tx_words_eob = length + 3; tx_desc->tx_frame_ctrl = frame_ctrl; @@ -262,7 +262,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) if (++priv->tx_idx >= PCH_GBE_DESC_NUM) priv->tx_idx = 0; - writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_head + priv->tx_idx)), + writel(dm_pci_virt_to_mem(priv->dev, tx_head + priv->tx_idx), &mac_regs->tx_dsc_sw_p); start = get_timer(0); @@ -283,7 +283,8 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp) struct pch_gbe_priv *priv = dev_get_priv(dev); struct pch_gbe_regs *mac_regs = priv->mac_regs; struct pch_gbe_rx_desc *rx_desc; - ulong hw_desc, buffer_addr, length; + ulong hw_desc, length; + void *buffer; rx_desc = &priv->rx_desc[priv->rx_idx]; @@ -291,12 +292,12 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp) hw_desc = readl(&mac_regs->rx_dsc_hw_p_hld); /* Just return if not receiving any packet */ - if ((ulong)rx_desc == hw_desc) + if (virt_to_phys(rx_desc) == hw_desc) return -EAGAIN; - buffer_addr = dm_pci_mem_to_phys(priv->dev, rx_desc->buffer_addr); - *packetp = (uchar *)buffer_addr; length = rx_desc->rx_words_eob - 3 - ETH_FCS_LEN; + buffer = dm_pci_mem_to_virt(priv->dev, rx_desc->buffer_addr, length, 0); + *packetp = (uchar *)buffer; return length; } @@ -315,7 +316,7 @@ static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length) if (++rx_swp >= PCH_GBE_DESC_NUM) rx_swp = 0; - writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_head + rx_swp)), + writel(dm_pci_virt_to_mem(priv->dev, rx_head + rx_swp), &mac_regs->rx_dsc_sw_p); return 0; -- cgit v1.1 From 2303bff7d55df47105740e5d635d50ef9f6856b6 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Sun, 30 Apr 2017 21:57:08 +0200 Subject: net: pch_gbe: Add cache maintenance On MIPS systems DMA isn't coherent with the CPU caches unless an IOCU is present. When there is no IOCU we need to writeback or invalidate the data caches at appropriate points. Perform this cache maintenance in the pch_gbe driver which is used on the MIPS Boston development board. Signed-off-by: Paul Burton Reviewed-by: Bin Meng Tested-by: Bin Meng Signed-off-by: Daniel Schwierzeck Reviewed-by: Simon Glass Acked-by: Joe Hershberger --- drivers/net/pch_gbe.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index 1432351..8866f66 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -120,6 +120,8 @@ static void pch_gbe_rx_descs_init(struct udevice *dev) rx_desc[i].buffer_addr = dm_pci_virt_to_mem(priv->dev, priv->rx_buff[i]); + flush_dcache_range((ulong)rx_desc, (ulong)&rx_desc[PCH_GBE_DESC_NUM]); + writel(dm_pci_virt_to_mem(priv->dev, rx_desc), &mac_regs->rx_dsc_base); writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1), @@ -137,6 +139,8 @@ static void pch_gbe_tx_descs_init(struct udevice *dev) memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM); + flush_dcache_range((ulong)tx_desc, (ulong)&tx_desc[PCH_GBE_DESC_NUM]); + writel(dm_pci_virt_to_mem(priv->dev, tx_desc), &mac_regs->tx_dsc_base); writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1), @@ -245,6 +249,8 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) u32 int_st; ulong start; + flush_dcache_range((ulong)packet, (ulong)packet + length); + tx_head = &priv->tx_desc[0]; tx_desc = &priv->tx_desc[priv->tx_idx]; @@ -258,6 +264,8 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) tx_desc->dma_status = 0; tx_desc->gbec_status = 0; + flush_dcache_range((ulong)tx_desc, (ulong)&tx_desc[1]); + /* Test the wrap-around condition */ if (++priv->tx_idx >= PCH_GBE_DESC_NUM) priv->tx_idx = 0; @@ -295,8 +303,12 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp) if (virt_to_phys(rx_desc) == hw_desc) return -EAGAIN; + /* Invalidate the descriptor */ + invalidate_dcache_range((ulong)rx_desc, (ulong)&rx_desc[1]); + length = rx_desc->rx_words_eob - 3 - ETH_FCS_LEN; buffer = dm_pci_mem_to_virt(priv->dev, rx_desc->buffer_addr, length, 0); + invalidate_dcache_range((ulong)buffer, (ulong)buffer + length); *packetp = (uchar *)buffer; return length; -- cgit v1.1