Merge git://git.denx.de/u-boot-net
authorTom Rini <trini@konsulko.com>
Tue, 16 Jan 2018 00:01:23 +0000 (19:01 -0500)
committerTom Rini <trini@konsulko.com>
Tue, 16 Jan 2018 00:01:23 +0000 (19:01 -0500)
53 files changed:
configs/Lamobo_R1_defconfig
configs/alt_defconfig
configs/ap_sh4a_4a_defconfig
configs/armadillo-800eva_defconfig
configs/ecovec_defconfig
configs/espt_defconfig
configs/gose_defconfig
configs/koelsch_defconfig
configs/lager_defconfig
configs/porter_defconfig
configs/r0p7734_defconfig
configs/sh7752evb_defconfig
configs/sh7753evb_defconfig
configs/sh7757lcr_defconfig
configs/sh7763rdp_defconfig
configs/silk_defconfig
configs/stout_defconfig
drivers/core/read.c
drivers/net/Kconfig
drivers/net/designware.c
drivers/net/designware.h
drivers/net/macb.c
drivers/net/macb.h
drivers/net/mvneta.c
drivers/net/netconsole.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/atheros.c
drivers/net/phy/b53.c [new file with mode: 0644]
drivers/net/phy/marvell.c
drivers/net/phy/miiphybb.c
drivers/net/phy/phy.c
drivers/net/sh_eth.c
drivers/net/sh_eth.h
include/configs/alt.h
include/configs/ap_sh4a_4a.h
include/configs/armadillo-800eva.h
include/configs/ecovec.h
include/configs/espt.h
include/configs/gose.h
include/configs/koelsch.h
include/configs/lager.h
include/configs/porter.h
include/configs/r0p7734.h
include/configs/sh7752evb.h
include/configs/sh7753evb.h
include/configs/sh7757lcr.h
include/configs/sh7763rdp.h
include/configs/silk.h
include/configs/stout.h
include/phy.h
net/bootp.c
scripts/config_whitelist.txt

index 4cc4dc4..805d4b7 100644 (file)
@@ -23,3 +23,6 @@ CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
+CONFIG_B53_SWITCH=y
+CONFIG_B53_CPU_PORT=8
+CONFIG_B53_PHY_PORTS=0x1f
index bf51e53..157d830 100644 (file)
@@ -24,7 +24,8 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_PHY_MICREL=y
 CONFIG_BAUDRATE=38400
 CONFIG_SCIF_CONSOLE=y
index ef14121..976680a 100644 (file)
@@ -25,6 +25,7 @@ CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
index d9a5169..14d6c84 100644 (file)
@@ -27,6 +27,7 @@ CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_ENV_IS_IN_FLASH=y
 # CONFIG_MMC is not set
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_OF_LIBFDT=y
index 5d65e9d..5c6c55f 100644 (file)
@@ -29,7 +29,8 @@ CONFIG_CMD_EXT2=y
 CONFIG_CMD_FAT=y
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
index 520bc9f..32ba9d0 100644 (file)
@@ -25,6 +25,7 @@ CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
index bc32990..5f10d9a 100644 (file)
@@ -24,8 +24,9 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_BAUDRATE=38400
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USB=y
index 5def33b..acc7289 100644 (file)
@@ -24,8 +24,9 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_BAUDRATE=38400
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USB=y
index 5072045..c0778ee 100644 (file)
@@ -24,8 +24,9 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_BAUDRATE=38400
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USB=y
index ac36dca..7374a30 100644 (file)
@@ -24,8 +24,9 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_BAUDRATE=38400
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USB=y
index e0b19bb..342365d 100644 (file)
@@ -25,6 +25,7 @@ CONFIG_CMD_PING=y
 # CONFIG_CMD_MISC is not set
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
index 3152859..9e4f5aa 100644 (file)
@@ -34,6 +34,7 @@ CONFIG_MMC=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
index 259d6a7..631f241 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_MMC=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
index b2e7362..c7e30af 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_MMC=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
index 693a873..a211e4c 100644 (file)
@@ -26,6 +26,7 @@ CONFIG_CMD_PING=y
 CONFIG_CMD_JFFS2=y
 CONFIG_ENV_IS_IN_FLASH=y
 CONFIG_MTD_NOR_FLASH=y
-CONFIG_PHYLIB=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USE_PRIVATE_LIBGCC=y
index 8af1e19..ffe1d8b 100644 (file)
@@ -24,8 +24,9 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_BAUDRATE=38400
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USB=y
index b6e71e7..6750dcd 100644 (file)
@@ -24,8 +24,9 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_PHYLIB=y
 CONFIG_PHY_MICREL=y
+CONFIG_NETDEVICES=y
+CONFIG_SH_ETHER=y
 CONFIG_BAUDRATE=38400
 CONFIG_SCIF_CONSOLE=y
 CONFIG_USB=y
index 5d440ce..f346cc1 100644 (file)
@@ -103,6 +103,13 @@ int dev_read_phandle_with_args(struct udevice *dev, const char *list_name,
                                              out_args);
 }
 
+int dev_count_phandle_with_args(struct udevice *dev, const char *list_name,
+                               const char *cells_name)
+{
+       return ofnode_count_phandle_with_args(dev_ofnode(dev), list_name,
+                                             cells_name);
+}
+
 int dev_read_addr_cells(struct udevice *dev)
 {
        return ofnode_read_addr_cells(dev_ofnode(dev));
index 46b17b1..de1947c 100644 (file)
@@ -185,6 +185,13 @@ config MACB
          GEM (Gigabit Ethernet MAC) found in some ARM SoC devices.
          Say Y to include support for the MACB/GEM chip.
 
+config MACB_ZYNQ
+       bool "Cadence MACB/GEM Ethernet Interface for Xilinx Zynq"
+       depends on MACB
+       help
+         The Cadence MACB ethernet interface was used on Zynq platform.
+         Say Y to enable support for the MACB/GEM in Zynq chip.
+
 config PCH_GBE
        bool "Intel Platform Controller Hub EG20T GMAC driver"
        depends on DM_ETH && DM_PCI
@@ -269,6 +276,12 @@ config SUN8I_EMAC
          It can be found in H3/A64/A83T based SoCs and compatible with both
          External and Internal PHYs.
 
+config SH_ETHER
+       bool "Renesas SH Ethernet MAC"
+       select PHYLIB
+       help
+         This driver supports the Ethernet for Renesas SH and ARM SoCs.
+
 config XILINX_AXIEMAC
        depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
        select PHYLIB
index 036d231..6d53071 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <miiphy.h>
@@ -17,6 +18,7 @@
 #include <pci.h>
 #include <linux/compiler.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 #include <asm/io.h>
 #include <power/regulator.h>
 #include "designware.h"
@@ -343,6 +345,8 @@ int designware_eth_enable(struct dw_eth_dev *priv)
        return 0;
 }
 
+#define ETH_ZLEN       60
+
 static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
 {
        struct eth_dma_regs *dma_p = priv->dma_regs_p;
@@ -369,6 +373,8 @@ static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
                return -EPERM;
        }
 
+       length = max(length, ETH_ZLEN);
+
        memcpy((void *)data_start, packet, length);
 
        /* Flush data to be sent */
@@ -661,6 +667,35 @@ int designware_eth_probe(struct udevice *dev)
        u32 iobase = pdata->iobase;
        ulong ioaddr;
        int ret;
+#ifdef CONFIG_CLK
+       int i, err, clock_nb;
+
+       priv->clock_count = 0;
+       clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+       if (clock_nb > 0) {
+               priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
+                                           GFP_KERNEL);
+               if (!priv->clocks)
+                       return -ENOMEM;
+
+               for (i = 0; i < clock_nb; i++) {
+                       err = clk_get_by_index(dev, i, &priv->clocks[i]);
+                       if (err < 0)
+                               break;
+
+                       err = clk_enable(&priv->clocks[i]);
+                       if (err) {
+                               pr_err("failed to enable clock %d\n", i);
+                               clk_free(&priv->clocks[i]);
+                               goto clk_err;
+                       }
+                       priv->clock_count++;
+               }
+       } else if (clock_nb != -ENOENT) {
+               pr_err("failed to get clock phandle(%d)\n", clock_nb);
+               return clock_nb;
+       }
+#endif
 
 #if defined(CONFIG_DM_REGULATOR)
        struct udevice *phy_supply;
@@ -707,6 +742,15 @@ int designware_eth_probe(struct udevice *dev)
        debug("%s, ret=%d\n", __func__, ret);
 
        return ret;
+
+#ifdef CONFIG_CLK
+clk_err:
+       ret = clk_release_all(priv->clocks, priv->clock_count);
+       if (ret)
+               pr_err("failed to disable all clocks\n");
+
+       return err;
+#endif
 }
 
 static int designware_eth_remove(struct udevice *dev)
@@ -717,7 +761,11 @@ static int designware_eth_remove(struct udevice *dev)
        mdio_unregister(priv->bus);
        mdio_free(priv->bus);
 
+#ifdef CONFIG_CLK
+       return clk_release_all(priv->clocks, priv->clock_count);
+#else
        return 0;
+#endif
 }
 
 const struct eth_ops designware_eth_ops = {
index 7992d0e..252cd24 100644 (file)
@@ -239,6 +239,10 @@ struct dw_eth_dev {
 #ifdef CONFIG_DM_GPIO
        struct gpio_desc reset_gpio;
 #endif
+#ifdef CONFIG_CLK
+       struct clk *clocks;     /* clock list */
+       int clock_count;        /* number of clock in clock list */
+#endif
 
        struct phy_device *phydev;
        struct mii_dev *bus;
index f9373db..e62aefc 100644 (file)
@@ -52,6 +52,22 @@ DECLARE_GLOBAL_DATA_PTR;
 #define MACB_TX_TIMEOUT                1000
 #define MACB_AUTONEG_TIMEOUT   5000000
 
+#ifdef CONFIG_MACB_ZYNQ
+/* INCR4 AHB bursts */
+#define MACB_ZYNQ_GEM_DMACR_BLENGTH            0x00000004
+/* Use full configured addressable space (8 Kb) */
+#define MACB_ZYNQ_GEM_DMACR_RXSIZE             0x00000300
+/* Use full configured addressable space (4 Kb) */
+#define MACB_ZYNQ_GEM_DMACR_TXSIZE             0x00000400
+/* Set RXBUF with use of 128 byte */
+#define MACB_ZYNQ_GEM_DMACR_RXBUF              0x00020000
+#define MACB_ZYNQ_GEM_DMACR_INIT \
+                               (MACB_ZYNQ_GEM_DMACR_BLENGTH | \
+                               MACB_ZYNQ_GEM_DMACR_RXSIZE | \
+                               MACB_ZYNQ_GEM_DMACR_TXSIZE | \
+                               MACB_ZYNQ_GEM_DMACR_RXBUF)
+#endif
+
 struct macb_dma_desc {
        u32     addr;
        u32     ctrl;
@@ -461,13 +477,25 @@ static int macb_phy_find(struct macb_device *macb, const char *name)
                phy_id = macb_mdio_read(macb, MII_PHYSID1);
                if (phy_id != 0xffff) {
                        printf("%s: PHY present at %d\n", name, i);
-                       return 1;
+                       return 0;
                }
        }
 
        /* PHY isn't up to snuff */
        printf("%s: PHY not found\n", name);
 
+       return -ENODEV;
+}
+
+/**
+ * macb_linkspd_cb - Linkspeed change callback function
+ * @regs:      Base Register of MACB devices
+ * @speed:     Linkspeed
+ * Returns 0 when operation success and negative errno number
+ * when operation failed.
+ */
+int __weak macb_linkspd_cb(void *regs, unsigned int speed)
+{
        return 0;
 }
 
@@ -483,18 +511,20 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
        u32 ncfgr;
        u16 phy_id, status, adv, lpa;
        int media, speed, duplex;
+       int ret;
        int i;
 
        arch_get_mdio_control(name);
        /* Auto-detect phy_addr */
-       if (!macb_phy_find(macb, name))
-               return 0;
+       ret = macb_phy_find(macb, name);
+       if (ret)
+               return ret;
 
        /* Check if the PHY is up to snuff... */
        phy_id = macb_mdio_read(macb, MII_PHYSID1);
        if (phy_id == 0xffff) {
                printf("%s: No PHY present\n", name);
-               return 0;
+               return -ENODEV;
        }
 
 #ifdef CONFIG_PHYLIB
@@ -530,7 +560,7 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
        if (!(status & BMSR_LSTATUS)) {
                printf("%s: link down (status: 0x%04x)\n",
                       name, status);
-               return 0;
+               return -ENETDOWN;
        }
 
        /* First check for GMAC and that it is GiB capable */
@@ -554,7 +584,11 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
 
                        macb_writel(macb, NCFGR, ncfgr);
 
-                       return 1;
+                       ret = macb_linkspd_cb(macb->regs, _1000BASET);
+                       if (ret)
+                               return ret;
+
+                       return 0;
                }
        }
 
@@ -573,13 +607,21 @@ static int macb_phy_init(struct macb_device *macb, const char *name)
 
        ncfgr = macb_readl(macb, NCFGR);
        ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE));
-       if (speed)
+       if (speed) {
                ncfgr |= MACB_BIT(SPD);
+               ret = macb_linkspd_cb(macb->regs, _100BASET);
+       } else {
+               ret = macb_linkspd_cb(macb->regs, _10BASET);
+       }
+
+       if (ret)
+               return ret;
+
        if (duplex)
                ncfgr |= MACB_BIT(FD);
        macb_writel(macb, NCFGR, ncfgr);
 
-       return 1;
+       return 0;
 }
 
 static int gmac_init_multi_queues(struct macb_device *macb)
@@ -616,6 +658,7 @@ static int _macb_init(struct macb_device *macb, const char *name)
        struct macb_device *macb = dev_get_priv(dev);
 #endif
        unsigned long paddr;
+       int ret;
        int i;
 
        /*
@@ -649,6 +692,10 @@ static int _macb_init(struct macb_device *macb, const char *name)
        macb->tx_tail = 0;
        macb->next_rx_tail = 0;
 
+#ifdef CONFIG_MACB_ZYNQ
+       macb_writel(macb, DMACFG, MACB_ZYNQ_GEM_DMACR_INIT);
+#endif
+
        macb_writel(macb, RBQP, macb->rx_ring_dma);
        macb_writel(macb, TBQP, macb->tx_ring_dma);
 
@@ -709,11 +756,12 @@ static int _macb_init(struct macb_device *macb, const char *name)
        }
 
 #ifdef CONFIG_DM_ETH
-       if (!macb_phy_init(dev, name))
+       ret = macb_phy_init(dev, name);
 #else
-       if (!macb_phy_init(macb, name))
+       ret = macb_phy_init(macb, name);
 #endif
-               return -1;
+       if (ret)
+               return ret;
 
        /* Enable TX and RX */
        macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE));
@@ -1013,9 +1061,15 @@ static int macb_enable_clk(struct udevice *dev)
        if (ret)
                return -EINVAL;
 
+       /*
+        * Zynq clock driver didn't support for enable or disable
+        * clock. Hence, clk_enable() didn't apply for Zynq
+        */
+#ifndef CONFIG_MACB_ZYNQ
        ret = clk_enable(&clk);
        if (ret)
                return ret;
+#endif
 
        clk_rate = clk_get_rate(&clk);
        if (!clk_rate)
@@ -1083,12 +1137,24 @@ static int macb_eth_remove(struct udevice *dev)
        return 0;
 }
 
+/**
+ * macb_late_eth_ofdata_to_platdata
+ * @dev:       udevice struct
+ * Returns 0 when operation success and negative errno number
+ * when operation failed.
+ */
+int __weak macb_late_eth_ofdata_to_platdata(struct udevice *dev)
+{
+       return 0;
+}
+
 static int macb_eth_ofdata_to_platdata(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
 
        pdata->iobase = devfdt_get_addr(dev);
-       return 0;
+
+       return macb_late_eth_ofdata_to_platdata(dev);
 }
 
 static const struct udevice_id macb_eth_ids[] = {
@@ -1097,6 +1163,7 @@ static const struct udevice_id macb_eth_ids[] = {
        { .compatible = "atmel,sama5d2-gem" },
        { .compatible = "atmel,sama5d3-gem" },
        { .compatible = "atmel,sama5d4-gem" },
+       { .compatible = "cdns,zynq-gem" },
        { }
 };
 
index 5bb48f4..c39554d 100644 (file)
@@ -11,6 +11,7 @@
 #define MACB_NCFGR                             0x0004
 #define MACB_NSR                               0x0008
 #define GEM_UR                                 0x000c
+#define MACB_DMACFG                            0x0010
 #define MACB_TSR                               0x0014
 #define MACB_RBQP                              0x0018
 #define MACB_TBQP                              0x001c
index f1be952..83e3153 100644 (file)
@@ -1654,7 +1654,11 @@ static int mvneta_recv(struct udevice *dev, int flags, uchar **packetp)
                 */
                *packetp = data;
 
-               mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
+               /*
+                * Only mark one descriptor as free
+                * since only one was processed
+                */
+               mvneta_rxq_desc_num_update(pp, rxq, 1, 1);
        }
 
        return rx_bytes;
index e9dbedf..028fca9 100644 (file)
@@ -153,14 +153,17 @@ int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
                len = sizeof(input_buffer) - input_size;
 
        end = input_offset + input_size;
-       if (end > sizeof(input_buffer))
+       if (end >= sizeof(input_buffer))
                end -= sizeof(input_buffer);
 
        chunk = len;
-       if (end + len > sizeof(input_buffer)) {
+       /* Check if packet will wrap in input_buffer */
+       if (end + len >= sizeof(input_buffer)) {
                chunk = sizeof(input_buffer) - end;
+               /* Copy the second part of the pkt to start of input_buffer */
                memcpy(input_buffer, pkt + chunk, len - chunk);
        }
+       /* Copy first (or only) part of pkt after end of current valid input*/
        memcpy(input_buffer + end, pkt, chunk);
 
        input_size += len;
index e32f1eb..95b7534 100644 (file)
@@ -12,6 +12,23 @@ menuconfig PHYLIB
 
 if PHYLIB
 
+config B53_SWITCH
+       bool "Broadcom BCM53xx (RoboSwitch) Ethernet switch PHY support."
+       help
+         Enable support for Broadcom BCM53xx (RoboSwitch) Ethernet switches.
+         This currently supports BCM53125 and similar models.
+
+if B53_SWITCH
+
+config B53_CPU_PORT
+       int "CPU port"
+       default 8
+
+config B53_PHY_PORTS
+       hex "Bitmask of PHY ports"
+
+endif # B53_SWITCH
+
 config MV88E61XX_SWITCH
        bool "Marvel MV88E61xx Ethernet switch PHY support."
 
index 1e264b2..f198037 100644 (file)
@@ -6,6 +6,7 @@
 #
 
 obj-$(CONFIG_BITBANGMII) += miiphybb.o
+obj-$(CONFIG_B53_SWITCH) += b53.o
 obj-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o
 obj-$(CONFIG_MV88E6352_SWITCH) += mv88e6352.o
 
index b34cdd3..d7e76de 100644 (file)
@@ -19,6 +19,7 @@
 
 static int ar8021_config(struct phy_device *phydev)
 {
+       phy_write(phydev, MDIO_DEVAD_NONE, 0x00, 0x1200);
        phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47);
 
diff --git a/drivers/net/phy/b53.c b/drivers/net/phy/b53.c
new file mode 100644 (file)
index 0000000..f7f2d9f
--- /dev/null
@@ -0,0 +1,768 @@
+/*
+ * Copyright (C) 2017
+ * Broadcom
+ * Florian Fainelli <f.fainelli@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/*
+ * PHY driver for Broadcom BCM53xx (roboswitch) Ethernet switches.
+ *
+ * This driver configures the b53 for basic use as a PHY. The switch supports
+ * vendor tags and VLAN configuration that can affect the switching decisions.
+ * This driver uses a simple configuration in which all ports are only allowed
+ * to send frames to the CPU port and receive frames from the CPU port this
+ * providing port isolation (no cross talk).
+ *
+ * The configuration determines which PHY ports to activate using the
+ * CONFIG_B53_PHY_PORTS bitmask. Set bit N will active port N and so on.
+ *
+ * This driver was written primarily for the Lamobo R1 platform using a BCM53152
+ * switch but the BCM53xx being largely register compatible, extending it to
+ * cover other switches would be trivial.
+ */
+
+#include <common.h>
+
+#include <errno.h>
+#include <malloc.h>
+#include <miiphy.h>
+#include <netdev.h>
+
+/* Pseudo-PHY address (non configurable) to access internal registers */
+#define BRCM_PSEUDO_PHY_ADDR           30
+
+/* Maximum number of ports possible */
+#define B53_N_PORTS                    9
+
+#define B53_CTRL_PAGE                  0x00 /* Control */
+#define B53_MGMT_PAGE                  0x02 /* Management Mode */
+/* Port VLAN Page */
+#define B53_PVLAN_PAGE                 0x31
+
+/* Control Page registers */
+#define B53_PORT_CTRL(i)               (0x00 + (i))
+#define   PORT_CTRL_RX_DISABLE         BIT(0)
+#define   PORT_CTRL_TX_DISABLE         BIT(1)
+#define   PORT_CTRL_RX_BCST_EN         BIT(2) /* Broadcast RX (P8 only) */
+#define   PORT_CTRL_RX_MCST_EN         BIT(3) /* Multicast RX (P8 only) */
+#define   PORT_CTRL_RX_UCST_EN         BIT(4) /* Unicast RX (P8 only) */
+
+/* Switch Mode Control Register (8 bit) */
+#define B53_SWITCH_MODE                        0x0b
+#define   SM_SW_FWD_MODE               BIT(0)  /* 1 = Managed Mode */
+#define   SM_SW_FWD_EN                 BIT(1)  /* Forwarding Enable */
+
+/* IMP Port state override register (8 bit) */
+#define B53_PORT_OVERRIDE_CTRL         0x0e
+#define   PORT_OVERRIDE_LINK           BIT(0)
+#define   PORT_OVERRIDE_FULL_DUPLEX    BIT(1) /* 0 = Half Duplex */
+#define   PORT_OVERRIDE_SPEED_S                2
+#define   PORT_OVERRIDE_SPEED_10M      (0 << PORT_OVERRIDE_SPEED_S)
+#define   PORT_OVERRIDE_SPEED_100M     (1 << PORT_OVERRIDE_SPEED_S)
+#define   PORT_OVERRIDE_SPEED_1000M    (2 << PORT_OVERRIDE_SPEED_S)
+/* BCM5325 only */
+#define   PORT_OVERRIDE_RV_MII_25      BIT(4)
+#define   PORT_OVERRIDE_RX_FLOW                BIT(4)
+#define   PORT_OVERRIDE_TX_FLOW                BIT(5)
+/* BCM5301X only, requires setting 1000M */
+#define   PORT_OVERRIDE_SPEED_2000M    BIT(6)
+#define   PORT_OVERRIDE_EN             BIT(7) /* Use the register contents */
+
+#define B53_RGMII_CTRL_IMP             0x60
+#define   RGMII_CTRL_ENABLE_GMII       BIT(7)
+#define   RGMII_CTRL_TIMING_SEL                BIT(2)
+#define   RGMII_CTRL_DLL_RXC           BIT(1)
+#define   RGMII_CTRL_DLL_TXC           BIT(0)
+
+/* Switch control (8 bit) */
+#define B53_SWITCH_CTRL                        0x22
+#define  B53_MII_DUMB_FWDG_EN          BIT(6)
+
+/* Software reset register (8 bit) */
+#define B53_SOFTRESET                  0x79
+#define   SW_RST                       BIT(7)
+#define   EN_CH_RST                    BIT(6)
+#define   EN_SW_RST                    BIT(4)
+
+/* Fast Aging Control register (8 bit) */
+#define B53_FAST_AGE_CTRL              0x88
+#define   FAST_AGE_STATIC              BIT(0)
+#define   FAST_AGE_DYNAMIC             BIT(1)
+#define   FAST_AGE_PORT                        BIT(2)
+#define   FAST_AGE_VLAN                        BIT(3)
+#define   FAST_AGE_STP                 BIT(4)
+#define   FAST_AGE_MC                  BIT(5)
+#define   FAST_AGE_DONE                        BIT(7)
+
+/* Port VLAN mask (16 bit) IMP port is always 8, also on 5325 & co */
+#define B53_PVLAN_PORT_MASK(i)         ((i) * 2)
+
+/* MII registers */
+#define REG_MII_PAGE    0x10    /* MII Page register */
+#define REG_MII_ADDR    0x11    /* MII Address register */
+#define REG_MII_DATA0   0x18    /* MII Data register 0 */
+#define REG_MII_DATA1   0x19    /* MII Data register 1 */
+#define REG_MII_DATA2   0x1a    /* MII Data register 2 */
+#define REG_MII_DATA3   0x1b    /* MII Data register 3 */
+
+#define REG_MII_PAGE_ENABLE     BIT(0)
+#define REG_MII_ADDR_WRITE      BIT(0)
+#define REG_MII_ADDR_READ       BIT(1)
+
+struct b53_device {
+       struct mii_dev  *bus;
+       unsigned int cpu_port;
+};
+
+static int b53_mdio_op(struct mii_dev *bus, u8 page, u8 reg, u16 op)
+{
+       int ret;
+       int i;
+       u16 v;
+
+       /* set page number */
+       v = (page << 8) | REG_MII_PAGE_ENABLE;
+       ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                        REG_MII_PAGE, v);
+       if (ret)
+               return ret;
+
+       /* set register address */
+       v = (reg << 8) | op;
+       ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                        REG_MII_ADDR, v);
+       if (ret)
+               return ret;
+
+       /* check if operation completed */
+       for (i = 0; i < 5; ++i) {
+               v = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                             REG_MII_ADDR);
+               if (!(v & (REG_MII_ADDR_WRITE | REG_MII_ADDR_READ)))
+                       break;
+
+               udelay(100);
+       }
+
+       if (i == 5)
+               return -EIO;
+
+       return 0;
+}
+
+static int b53_mdio_read8(struct mii_dev *bus, u8 page, u8 reg, u8 *val)
+{
+       int ret;
+
+       ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
+       if (ret)
+               return ret;
+
+       *val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                        REG_MII_DATA0) & 0xff;
+
+       return 0;
+}
+
+static int b53_mdio_read16(struct mii_dev *bus, u8 page, u8 reg, u16 *val)
+{
+       int ret;
+
+       ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
+       if (ret)
+               return ret;
+
+       *val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                        REG_MII_DATA0);
+
+       return 0;
+}
+
+static int b53_mdio_read32(struct mii_dev *bus, u8 page, u8 reg, u32 *val)
+{
+       int ret;
+
+       ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
+       if (ret)
+               return ret;
+
+       *val = bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                        REG_MII_DATA0);
+       *val |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                         REG_MII_DATA1) << 16;
+
+       return 0;
+}
+
+static int b53_mdio_read48(struct mii_dev *bus, u8 page, u8 reg, u64 *val)
+{
+       u64 temp = 0;
+       int i;
+       int ret;
+
+       ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
+       if (ret)
+               return ret;
+
+       for (i = 2; i >= 0; i--) {
+               temp <<= 16;
+               temp |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                                 REG_MII_DATA0 + i);
+       }
+
+       *val = temp;
+
+       return 0;
+}
+
+static int b53_mdio_read64(struct mii_dev *bus, u8 page, u8 reg, u64 *val)
+{
+       u64 temp = 0;
+       int i;
+       int ret;
+
+       ret = b53_mdio_op(bus, page, reg, REG_MII_ADDR_READ);
+       if (ret)
+               return ret;
+
+       for (i = 3; i >= 0; i--) {
+               temp <<= 16;
+               temp |= bus->read(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                                 REG_MII_DATA0 + i);
+       }
+
+       *val = temp;
+
+       return 0;
+}
+
+static int b53_mdio_write8(struct mii_dev *bus, u8 page, u8 reg, u8 value)
+{
+       int ret;
+
+       ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                        REG_MII_DATA0, value);
+       if (ret)
+               return ret;
+
+       return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
+}
+
+static int b53_mdio_write16(struct mii_dev *bus, u8 page, u8 reg,
+                           u16 value)
+{
+       int ret;
+
+       ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR, MDIO_DEVAD_NONE,
+                        REG_MII_DATA0, value);
+       if (ret)
+               return ret;
+
+       return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
+}
+
+static int b53_mdio_write32(struct mii_dev *bus, u8 page, u8 reg,
+                           u32 value)
+{
+       unsigned int i;
+       u32 temp = value;
+
+       for (i = 0; i < 2; i++) {
+               int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
+                                    MDIO_DEVAD_NONE,
+                                    REG_MII_DATA0 + i, temp & 0xffff);
+               if (ret)
+                       return ret;
+               temp >>= 16;
+       }
+
+       return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
+}
+
+static int b53_mdio_write48(struct mii_dev *bus, u8 page, u8 reg,
+                           u64 value)
+{
+       unsigned int i;
+       u64 temp = value;
+
+       for (i = 0; i < 3; i++) {
+               int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
+                                    MDIO_DEVAD_NONE,
+                                    REG_MII_DATA0 + i, temp & 0xffff);
+               if (ret)
+                       return ret;
+               temp >>= 16;
+       }
+
+       return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
+}
+
+static int b53_mdio_write64(struct mii_dev *bus, u8 page, u8 reg,
+                           u64 value)
+{
+       unsigned int i;
+       u64 temp = value;
+
+       for (i = 0; i < 4; i++) {
+               int ret = bus->write(bus, BRCM_PSEUDO_PHY_ADDR,
+                                    MDIO_DEVAD_NONE,
+                                    REG_MII_DATA0 + i, temp & 0xffff);
+               if (ret)
+                       return ret;
+               temp >>= 16;
+       }
+
+       return b53_mdio_op(bus, page, reg, REG_MII_ADDR_WRITE);
+}
+
+static inline int b53_read8(struct b53_device *dev, u8 page,
+                           u8 reg, u8 *value)
+{
+       return b53_mdio_read8(dev->bus, page, reg, value);
+}
+
+static inline int b53_read16(struct b53_device *dev, u8 page,
+                            u8 reg, u16 *value)
+{
+       return b53_mdio_read16(dev->bus, page, reg, value);
+}
+
+static inline int b53_read32(struct b53_device *dev, u8 page,
+                            u8 reg, u32 *value)
+{
+       return b53_mdio_read32(dev->bus, page, reg, value);
+}
+
+static inline int b53_read48(struct b53_device *dev, u8 page,
+                            u8 reg, u64 *value)
+{
+       return b53_mdio_read48(dev->bus, page, reg, value);
+}
+
+static inline int b53_read64(struct b53_device *dev, u8 page,
+                            u8 reg, u64 *value)
+{
+       return b53_mdio_read64(dev->bus, page, reg, value);
+}
+
+static inline int b53_write8(struct b53_device *dev, u8 page,
+                            u8 reg, u8 value)
+{
+       return b53_mdio_write8(dev->bus, page, reg, value);
+}
+
+static inline int b53_write16(struct b53_device *dev, u8 page,
+                             u8 reg, u16 value)
+{
+       return b53_mdio_write16(dev->bus, page, reg, value);
+}
+
+static inline int b53_write32(struct b53_device *dev, u8 page,
+                             u8 reg, u32 value)
+{
+       return b53_mdio_write32(dev->bus, page, reg, value);
+}
+
+static inline int b53_write48(struct b53_device *dev, u8 page,
+                             u8 reg, u64 value)
+{
+       return b53_mdio_write48(dev->bus, page, reg, value);
+}
+
+static inline int b53_write64(struct b53_device *dev, u8 page,
+                             u8 reg, u64 value)
+{
+       return b53_mdio_write64(dev->bus, page, reg, value);
+}
+
+static int b53_flush_arl(struct b53_device *dev, u8 mask)
+{
+       unsigned int i;
+
+       b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL,
+                  FAST_AGE_DONE | FAST_AGE_DYNAMIC | mask);
+
+       for (i = 0; i < 10; i++) {
+               u8 fast_age_ctrl;
+
+               b53_read8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL,
+                         &fast_age_ctrl);
+
+               if (!(fast_age_ctrl & FAST_AGE_DONE))
+                       goto out;
+
+               mdelay(1);
+       }
+
+       return -ETIMEDOUT;
+out:
+       /* Only age dynamic entries (default behavior) */
+       b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, FAST_AGE_DYNAMIC);
+       return 0;
+}
+
+static int b53_switch_reset(struct phy_device *phydev)
+{
+       struct b53_device *dev = phydev->priv;
+       unsigned int timeout = 1000;
+       u8 mgmt;
+       u8 reg;
+
+       b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, &reg);
+       reg |= SW_RST | EN_SW_RST | EN_CH_RST;
+       b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, reg);
+
+       do {
+               b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, &reg);
+               if (!(reg & SW_RST))
+                       break;
+
+               mdelay(1);
+       } while (timeout-- > 0);
+
+       if (timeout == 0)
+               return -ETIMEDOUT;
+
+       b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+
+       if (!(mgmt & SM_SW_FWD_EN)) {
+               mgmt &= ~SM_SW_FWD_MODE;
+               mgmt |= SM_SW_FWD_EN;
+
+               b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
+               b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+
+               if (!(mgmt & SM_SW_FWD_EN)) {
+                       printf("Failed to enable switch!\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* Include IMP port in dumb forwarding mode when no tagging protocol
+        * is configured
+        */
+       b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt);
+       mgmt |= B53_MII_DUMB_FWDG_EN;
+       b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt);
+
+       return b53_flush_arl(dev, FAST_AGE_STATIC);
+}
+
+static void b53_enable_cpu_port(struct phy_device *phydev)
+{
+       struct b53_device *dev = phydev->priv;
+       u8 port_ctrl;
+
+       port_ctrl = PORT_CTRL_RX_BCST_EN |
+                   PORT_CTRL_RX_MCST_EN |
+                   PORT_CTRL_RX_UCST_EN;
+       b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(dev->cpu_port), port_ctrl);
+
+       port_ctrl = PORT_OVERRIDE_EN | PORT_OVERRIDE_LINK |
+                   PORT_OVERRIDE_FULL_DUPLEX | PORT_OVERRIDE_SPEED_1000M;
+       b53_write8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, port_ctrl);
+
+       b53_read8(dev, B53_CTRL_PAGE, B53_RGMII_CTRL_IMP, &port_ctrl);
+}
+
+static void b53_imp_vlan_setup(struct b53_device *dev, int cpu_port)
+{
+       unsigned int port;
+       u16 pvlan;
+
+       /* Enable the IMP port to be in the same VLAN as the other ports
+        * on a per-port basis such that we only have Port i and IMP in
+        * the same VLAN.
+        */
+       for (port = 0; port < B53_N_PORTS; port++) {
+               if (!((1 << port) & CONFIG_B53_PHY_PORTS))
+                       continue;
+
+               b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port),
+                          &pvlan);
+               pvlan |= BIT(cpu_port);
+               b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port),
+                           pvlan);
+       }
+}
+
+static int b53_port_enable(struct phy_device *phydev, unsigned int port)
+{
+       struct b53_device *dev = phydev->priv;
+       unsigned int cpu_port = dev->cpu_port;
+       u16 pvlan;
+
+       /* Clear the Rx and Tx disable bits and set to no spanning tree */
+       b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), 0);
+
+       /* Set this port, and only this one to be in the default VLAN */
+       b53_read16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), &pvlan);
+       pvlan &= ~0x1ff;
+       pvlan |= BIT(port);
+       b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
+
+       b53_imp_vlan_setup(dev, cpu_port);
+
+       return 0;
+}
+
+static int b53_switch_init(struct phy_device *phydev)
+{
+       static int init;
+       int ret;
+
+       if (init)
+               return 0;
+
+       ret = b53_switch_reset(phydev);
+       if (ret < 0)
+               return ret;
+
+       b53_enable_cpu_port(phydev);
+
+       init = 1;
+
+       return 0;
+}
+
+static int b53_probe(struct phy_device *phydev)
+{
+       struct b53_device *dev;
+       int ret;
+
+       dev = malloc(sizeof(*dev));
+       if (!dev)
+               return -ENOMEM;
+
+       memset(dev, 0, sizeof(*dev));
+
+       phydev->priv = dev;
+       dev->bus = phydev->bus;
+       dev->cpu_port = CONFIG_B53_CPU_PORT;
+
+       ret = b53_switch_reset(phydev);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int b53_phy_config(struct phy_device *phydev)
+{
+       unsigned int port;
+       int res;
+
+       res = b53_switch_init(phydev);
+       if (res < 0)
+               return res;
+
+       for (port = 0; port < B53_N_PORTS; port++) {
+               if (!((1 << port) & CONFIG_B53_PHY_PORTS))
+                       continue;
+
+               res = b53_port_enable(phydev, port);
+               if (res < 0) {
+                       printf("Error enabling port %i\n", port);
+                       continue;
+               }
+
+               res = genphy_config_aneg(phydev);
+               if (res < 0) {
+                       printf("Error setting PHY %i autoneg\n", port);
+                       continue;
+               }
+
+               res = 0;
+       }
+
+       return res;
+}
+
+static int b53_phy_startup(struct phy_device *phydev)
+{
+       unsigned int port;
+       int res;
+
+       for (port = 0; port < B53_N_PORTS; port++) {
+               if (!((1 << port) & CONFIG_B53_PHY_PORTS))
+                       continue;
+
+               phydev->addr = port;
+
+               res = genphy_startup(phydev);
+               if (res < 0)
+                       continue;
+               else
+                       break;
+       }
+
+       /* Since we are connected directly to the switch, hardcode the link
+        * parameters to match those of the CPU port configured in
+        * b53_enable_cpu_port, we cannot be dependent on the user-facing port
+        * settings (e.g: 100Mbits/sec would not work here)
+        */
+       phydev->speed = 1000;
+       phydev->duplex = 1;
+       phydev->link = 1;
+
+       return 0;
+}
+
+static struct phy_driver b53_driver = {
+       .name = "Broadcom BCM53125",
+       .uid = 0x03625c00,
+       .mask = 0xfffffc00,
+       .features = PHY_GBIT_FEATURES,
+       .probe = b53_probe,
+       .config = b53_phy_config,
+       .startup = b53_phy_startup,
+       .shutdown = &genphy_shutdown,
+};
+
+int phy_b53_init(void)
+{
+       phy_register(&b53_driver);
+
+       return 0;
+}
+
+int do_b53_reg_read(const char *name, int argc, char * const argv[])
+{
+       u8 page, offset, width;
+       struct mii_dev *bus;
+       int ret = -EINVAL;
+       u64 value64 = 0;
+       u32 value32 = 0;
+       u16 value16 = 0;
+       u8 value8 = 0;
+
+       bus = miiphy_get_dev_by_name(name);
+       if (!bus) {
+               printf("unable to find MDIO bus: %s\n", name);
+               return ret;
+       }
+
+       page = simple_strtoul(argv[1], NULL, 16);
+       offset = simple_strtoul(argv[2], NULL, 16);
+       width = simple_strtoul(argv[3], NULL, 10);
+
+       switch (width) {
+       case 8:
+               ret = b53_mdio_read8(bus, page, offset, &value8);
+               printf("page=0x%02x, offset=0x%02x, value=0x%02x\n",
+                      page, offset, value8);
+               break;
+       case 16:
+               ret = b53_mdio_read16(bus, page, offset, &value16);
+               printf("page=0x%02x, offset=0x%02x, value=0x%04x\n",
+                      page, offset, value16);
+               break;
+       case 32:
+               ret = b53_mdio_read32(bus, page, offset, &value32);
+               printf("page=0x%02x, offset=0x%02x, value=0x%08x\n",
+                      page, offset, value32);
+               break;
+       case 48:
+               ret = b53_mdio_read48(bus, page, offset, &value64);
+               printf("page=0x%02x, offset=0x%02x, value=0x%012llx\n",
+                      page, offset, value64);
+               break;
+       case 64:
+               ret = b53_mdio_read48(bus, page, offset, &value64);
+               printf("page=0x%02x, offset=0x%02x, value=0x%016llx\n",
+                      page, offset, value64);
+               break;
+       default:
+               printf("Unsupported width: %d\n", width);
+               break;
+       }
+
+       return ret;
+}
+
+int do_b53_reg_write(const char *name, int argc, char * const argv[])
+{
+       u8 page, offset, width;
+       struct mii_dev *bus;
+       int ret = -EINVAL;
+       u64 value64 = 0;
+       u32 value = 0;
+
+       bus = miiphy_get_dev_by_name(name);
+       if (!bus) {
+               printf("unable to find MDIO bus: %s\n", name);
+               return ret;
+       }
+
+       page = simple_strtoul(argv[1], NULL, 16);
+       offset = simple_strtoul(argv[2], NULL, 16);
+       width = simple_strtoul(argv[3], NULL, 10);
+       if (width == 48 || width == 64)
+               value64 = simple_strtoull(argv[4], NULL, 16);
+       else
+               value = simple_strtoul(argv[4], NULL, 16);
+
+       switch (width) {
+       case 8:
+               ret = b53_mdio_write8(bus, page, offset, value & 0xff);
+               break;
+       case 16:
+               ret = b53_mdio_write16(bus, page, offset, value);
+               break;
+       case 32:
+               ret = b53_mdio_write32(bus, page, offset, value);
+               break;
+       case 48:
+               ret = b53_mdio_write48(bus, page, offset, value64);
+               break;
+       case 64:
+               ret = b53_mdio_write64(bus, page, offset, value64);
+               break;
+       default:
+               printf("Unsupported width: %d\n", width);
+               break;
+       }
+
+       return ret;
+}
+
+int do_b53_reg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       const char *cmd, *mdioname;
+       int ret = 0;
+
+       if (argc < 2)
+               return cmd_usage(cmdtp);
+
+       cmd = argv[1];
+       --argc;
+       ++argv;
+
+       if (!strcmp(cmd, "write")) {
+               if (argc < 4)
+                       return cmd_usage(cmdtp);
+               mdioname = argv[1];
+               --argc;
+               ++argv;
+               ret = do_b53_reg_write(mdioname, argc, argv);
+       } else if (!strcmp(cmd, "read")) {
+               if (argc < 5)
+                       return cmd_usage(cmdtp);
+               mdioname = argv[1];
+               --argc;
+               ++argv;
+               ret = do_b53_reg_read(mdioname, argc, argv);
+       } else {
+               return cmd_usage(cmdtp);
+       }
+
+       return ret;
+}
+
+U_BOOT_CMD(b53_reg, 7, 1, do_b53_reg,
+          "Broadcom B53 switch register access",
+          "write mdioname page (hex) offset (hex) width (dec) value (hex)\n"
+          "read mdioname page (hex) offset (hex) width (dec)\n"
+         );
index b7f300e..0b9a9fc 100644 (file)
 #define MIIM_88E151x_MODE_SGMII                1
 #define MIIM_88E151x_RESET_OFFS                15
 
+static int m88e1xxx_phy_extread(struct phy_device *phydev, int addr,
+                               int devaddr, int regnum)
+{
+       int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE);
+       int val;
+
+       phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, devaddr);
+       val = phy_read(phydev, MDIO_DEVAD_NONE, regnum);
+       phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, oldpage);
+
+       return val;
+}
+
+static int m88e1xxx_phy_extwrite(struct phy_device *phydev, int addr,
+                                int devaddr, int regnum, u16 val)
+{
+       int oldpage = phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE);
+
+       phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, devaddr);
+       phy_write(phydev, MDIO_DEVAD_NONE, regnum, val);
+       phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, oldpage);
+
+       return 0;
+}
+
 /* Marvell 88E1011S */
 static int m88e1011s_config(struct phy_device *phydev)
 {
@@ -669,6 +694,8 @@ static struct phy_driver M88E1510_driver = {
        .config = &m88e1510_config,
        .startup = &m88e1011s_startup,
        .shutdown = &genphy_shutdown,
+       .readext = &m88e1xxx_phy_extread,
+       .writeext = &m88e1xxx_phy_extwrite,
 };
 
 /*
@@ -684,6 +711,8 @@ static struct phy_driver M88E1518_driver = {
        .config = &m88e1518_config,
        .startup = &m88e1011s_startup,
        .shutdown = &genphy_shutdown,
+       .readext = &m88e1xxx_phy_extread,
+       .writeext = &m88e1xxx_phy_extwrite,
 };
 
 static struct phy_driver M88E1310_driver = {
index af676b9..d617224 100644 (file)
@@ -232,7 +232,7 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read,
  */
 int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg)
 {
-       short rdreg; /* register working value */
+       unsigned short rdreg; /* register working value */
        int v;
        int j; /* counter */
        struct bb_miiphy_bus *bus;
index fd3dd55..e31f3aa 100644 (file)
@@ -461,6 +461,9 @@ static LIST_HEAD(phy_drivers);
 
 int phy_init(void)
 {
+#ifdef CONFIG_B53_SWITCH
+       phy_b53_init();
+#endif
 #ifdef CONFIG_MV88E61XX_SWITCH
        phy_mv88e61xx_init();
 #endif
index 970d730..6edb51e 100644 (file)
@@ -29,7 +29,8 @@
 
 #if defined(CONFIG_SH_ETHER_CACHE_WRITEBACK) && !defined(CONFIG_SYS_DCACHE_OFF)
 #define flush_cache_wback(addr, len)    \
-               flush_dcache_range((u32)addr, (u32)(addr + len - 1))
+               flush_dcache_range((u32)addr, \
+               (u32)(addr + ALIGN(len, CONFIG_SH_ETHER_ALIGNE_SIZE)))
 #else
 #define flush_cache_wback(...)
 #endif
@@ -67,7 +68,7 @@ int sh_eth_send(struct eth_device *dev, void *packet, int len)
 
        /* packet must be a 4 byte boundary */
        if ((int)packet & 3) {
-               printf(SHETHER_NAME ": %s: packet not 4 byte alligned\n"
+               printf(SHETHER_NAME ": %s: packet not 4 byte aligned\n"
                                , __func__);
                ret = -EFAULT;
                goto err;
@@ -86,8 +87,8 @@ int sh_eth_send(struct eth_device *dev, void *packet, int len)
        flush_cache_wback(port_info->tx_desc_cur, sizeof(struct tx_desc_s));
 
        /* Restart the transmitter if disabled */
-       if (!(sh_eth_read(eth, EDTRR) & EDTRR_TRNS))
-               sh_eth_write(eth, EDTRR_TRNS, EDTRR);
+       if (!(sh_eth_read(port_info, EDTRR) & EDTRR_TRNS))
+               sh_eth_write(port_info, EDTRR_TRNS, EDTRR);
 
        /* Wait until packet is transmitted */
        timeout = TIMEOUT_CNT;
@@ -147,24 +148,25 @@ int sh_eth_recv(struct eth_device *dev)
        }
 
        /* Restart the receiver if disabled */
-       if (!(sh_eth_read(eth, EDRRR) & EDRRR_R))
-               sh_eth_write(eth, EDRRR_R, EDRRR);
+       if (!(sh_eth_read(port_info, EDRRR) & EDRRR_R))
+               sh_eth_write(port_info, EDRRR_R, EDRRR);
 
        return len;
 }
 
 static int sh_eth_reset(struct sh_eth_dev *eth)
 {
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
 #if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)
        int ret = 0, i;
 
        /* Start e-dmac transmitter and receiver */
-       sh_eth_write(eth, EDSR_ENALL, EDSR);
+       sh_eth_write(port_info, EDSR_ENALL, EDSR);
 
        /* Perform a software reset and wait for it to complete */
-       sh_eth_write(eth, EDMR_SRST, EDMR);
+       sh_eth_write(port_info, EDMR_SRST, EDMR);
        for (i = 0; i < TIMEOUT_CNT; i++) {
-               if (!(sh_eth_read(eth, EDMR) & EDMR_SRST))
+               if (!(sh_eth_read(port_info, EDMR) & EDMR_SRST))
                        break;
                udelay(1000);
        }
@@ -176,9 +178,10 @@ static int sh_eth_reset(struct sh_eth_dev *eth)
 
        return ret;
 #else
-       sh_eth_write(eth, sh_eth_read(eth, EDMR) | EDMR_SRST, EDMR);
+       sh_eth_write(port_info, sh_eth_read(port_info, EDMR) | EDMR_SRST, EDMR);
        udelay(3000);
-       sh_eth_write(eth, sh_eth_read(eth, EDMR) & ~EDMR_SRST, EDMR);
+       sh_eth_write(port_info,
+                    sh_eth_read(port_info, EDMR) & ~EDMR_SRST, EDMR);
 
        return 0;
 #endif
@@ -203,7 +206,7 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
                goto err;
        }
 
-       flush_cache_wback((u32)port_info->tx_desc_alloc, alloc_desc_size);
+       flush_cache_wback(port_info->tx_desc_alloc, alloc_desc_size);
 
        /* Make sure we use a P2 address (non-cacheable) */
        port_info->tx_desc_base =
@@ -222,13 +225,15 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
        cur_tx_desc--;
        cur_tx_desc->td0 |= TD_TDLE;
 
-       /* Point the controller to the tx descriptor list. Must use physical
-          addresses */
-       sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDLAR);
+       /*
+        * Point the controller to the tx descriptor list. Must use physical
+        * addresses
+        */
+       sh_eth_write(port_info, ADDR_TO_PHY(port_info->tx_desc_base), TDLAR);
 #if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)
-       sh_eth_write(eth, ADDR_TO_PHY(port_info->tx_desc_base), TDFAR);
-       sh_eth_write(eth, ADDR_TO_PHY(cur_tx_desc), TDFXR);
-       sh_eth_write(eth, 0x01, TDFFR);/* Last discriptor bit */
+       sh_eth_write(port_info, ADDR_TO_PHY(port_info->tx_desc_base), TDFAR);
+       sh_eth_write(port_info, ADDR_TO_PHY(cur_tx_desc), TDFXR);
+       sh_eth_write(port_info, 0x01, TDFFR);/* Last discriptor bit */
 #endif
 
 err:
@@ -237,7 +242,7 @@ err:
 
 static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
 {
-       int port = eth->port, i , ret = 0;
+       int port = eth->port, i, ret = 0;
        u32 alloc_desc_size = NUM_RX_DESC * sizeof(struct rx_desc_s);
        struct sh_eth_info *port_info = &eth->port_info[port];
        struct rx_desc_s *cur_rx_desc;
@@ -283,7 +288,7 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
             i < NUM_RX_DESC; cur_rx_desc++, rx_buf += MAX_BUF_SIZE, i++) {
                cur_rx_desc->rd0 = RD_RACT;
                cur_rx_desc->rd1 = MAX_BUF_SIZE << 16;
-               cur_rx_desc->rd2 = (u32) ADDR_TO_PHY(rx_buf);
+               cur_rx_desc->rd2 = (u32)ADDR_TO_PHY(rx_buf);
        }
 
        /* Mark the end of the descriptors */
@@ -291,11 +296,11 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
        cur_rx_desc->rd0 |= RD_RDLE;
 
        /* Point the controller to the rx descriptor list */
-       sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
+       sh_eth_write(port_info, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
 #if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)
-       sh_eth_write(eth, ADDR_TO_PHY(port_info->rx_desc_base), RDFAR);
-       sh_eth_write(eth, ADDR_TO_PHY(cur_rx_desc), RDFXR);
-       sh_eth_write(eth, RDFFR_RDLF, RDFFR);
+       sh_eth_write(port_info, ADDR_TO_PHY(port_info->rx_desc_base), RDFAR);
+       sh_eth_write(port_info, ADDR_TO_PHY(cur_rx_desc), RDFXR);
+       sh_eth_write(port_info, RDFFR_RDLF, RDFFR);
 #endif
 
        return ret;
@@ -371,7 +376,7 @@ static int sh_eth_phy_config(struct sh_eth_dev *eth)
        return ret;
 }
 
-static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
+static int sh_eth_config(struct sh_eth_dev *eth)
 {
        int port = eth->port, ret = 0;
        u32 val;
@@ -380,45 +385,45 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
        struct phy_device *phy;
 
        /* Configure e-dmac registers */
-       sh_eth_write(eth, (sh_eth_read(eth, EDMR) & ~EMDR_DESC_R) |
+       sh_eth_write(port_info, (sh_eth_read(port_info, EDMR) & ~EMDR_DESC_R) |
                        (EMDR_DESC | EDMR_EL), EDMR);
 
-       sh_eth_write(eth, 0, EESIPR);
-       sh_eth_write(eth, 0, TRSCER);
-       sh_eth_write(eth, 0, TFTR);
-       sh_eth_write(eth, (FIFO_SIZE_T | FIFO_SIZE_R), FDR);
-       sh_eth_write(eth, RMCR_RST, RMCR);
+       sh_eth_write(port_info, 0, EESIPR);
+       sh_eth_write(port_info, 0, TRSCER);
+       sh_eth_write(port_info, 0, TFTR);
+       sh_eth_write(port_info, (FIFO_SIZE_T | FIFO_SIZE_R), FDR);
+       sh_eth_write(port_info, RMCR_RST, RMCR);
 #if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)
-       sh_eth_write(eth, 0, RPADIR);
+       sh_eth_write(port_info, 0, RPADIR);
 #endif
-       sh_eth_write(eth, (FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR);
+       sh_eth_write(port_info, (FIFO_F_D_RFF | FIFO_F_D_RFD), FCFTR);
 
        /* Configure e-mac registers */
-       sh_eth_write(eth, 0, ECSIPR);
+       sh_eth_write(port_info, 0, ECSIPR);
 
        /* Set Mac address */
        val = dev->enetaddr[0] << 24 | dev->enetaddr[1] << 16 |
            dev->enetaddr[2] << 8 | dev->enetaddr[3];
-       sh_eth_write(eth, val, MAHR);
+       sh_eth_write(port_info, val, MAHR);
 
        val = dev->enetaddr[4] << 8 | dev->enetaddr[5];
-       sh_eth_write(eth, val, MALR);
+       sh_eth_write(port_info, val, MALR);
 
-       sh_eth_write(eth, RFLR_RFL_MIN, RFLR);
+       sh_eth_write(port_info, RFLR_RFL_MIN, RFLR);
 #if defined(SH_ETH_TYPE_GETHER)
-       sh_eth_write(eth, 0, PIPR);
+       sh_eth_write(port_info, 0, PIPR);
 #endif
 #if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)
-       sh_eth_write(eth, APR_AP, APR);
-       sh_eth_write(eth, MPR_MP, MPR);
-       sh_eth_write(eth, TPAUSER_TPAUSE, TPAUSER);
+       sh_eth_write(port_info, APR_AP, APR);
+       sh_eth_write(port_info, MPR_MP, MPR);
+       sh_eth_write(port_info, TPAUSER_TPAUSE, TPAUSER);
 #endif
 
 #if defined(CONFIG_CPU_SH7734) || defined(CONFIG_R8A7740)
-       sh_eth_write(eth, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
+       sh_eth_write(port_info, CONFIG_SH_ETHER_SH7734_MII, RMII_MII);
 #elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) || \
        defined(CONFIG_R8A7793) || defined(CONFIG_R8A7794)
-       sh_eth_write(eth, sh_eth_read(eth, RMIIMR) | 0x1, RMIIMR);
+       sh_eth_write(port_info, sh_eth_read(port_info, RMIIMR) | 0x1, RMIIMR);
 #endif
        /* Configure phy */
        ret = sh_eth_phy_config(eth);
@@ -439,9 +444,9 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
        if (phy->speed == 100) {
                printf(SHETHER_NAME ": 100Base/");
 #if defined(SH_ETH_TYPE_GETHER)
-               sh_eth_write(eth, GECMR_100B, GECMR);
+               sh_eth_write(port_info, GECMR_100B, GECMR);
 #elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
-               sh_eth_write(eth, 1, RTRATE);
+               sh_eth_write(port_info, 1, RTRATE);
 #elif defined(CONFIG_CPU_SH7724) || defined(CONFIG_R8A7790) || \
                defined(CONFIG_R8A7791) || defined(CONFIG_R8A7793) || \
                defined(CONFIG_R8A7794)
@@ -450,26 +455,29 @@ static int sh_eth_config(struct sh_eth_dev *eth, bd_t *bd)
        } else if (phy->speed == 10) {
                printf(SHETHER_NAME ": 10Base/");
 #if defined(SH_ETH_TYPE_GETHER)
-               sh_eth_write(eth, GECMR_10B, GECMR);
+               sh_eth_write(port_info, GECMR_10B, GECMR);
 #elif defined(CONFIG_CPU_SH7757) || defined(CONFIG_CPU_SH7752)
-               sh_eth_write(eth, 0, RTRATE);
+               sh_eth_write(port_info, 0, RTRATE);
 #endif
        }
 #if defined(SH_ETH_TYPE_GETHER)
        else if (phy->speed == 1000) {
                printf(SHETHER_NAME ": 1000Base/");
-               sh_eth_write(eth, GECMR_1000B, GECMR);
+               sh_eth_write(port_info, GECMR_1000B, GECMR);
        }
 #endif
 
        /* Check if full duplex mode is supported by the phy */
        if (phy->duplex) {
                printf("Full\n");
-               sh_eth_write(eth, val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE|ECMR_DM),
+               sh_eth_write(port_info,
+                            val | (ECMR_CHG_DM | ECMR_RE | ECMR_TE | ECMR_DM),
                             ECMR);
        } else {
                printf("Half\n");
-               sh_eth_write(eth, val | (ECMR_CHG_DM|ECMR_RE|ECMR_TE), ECMR);
+               sh_eth_write(port_info,
+                            val | (ECMR_CHG_DM | ECMR_RE | ECMR_TE),
+                            ECMR);
        }
 
        return ret;
@@ -480,16 +488,20 @@ err_phy_cfg:
 
 static void sh_eth_start(struct sh_eth_dev *eth)
 {
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
+
        /*
         * Enable the e-dmac receiver only. The transmitter will be enabled when
         * we have something to transmit
         */
-       sh_eth_write(eth, EDRRR_R, EDRRR);
+       sh_eth_write(port_info, EDRRR_R, EDRRR);
 }
 
 static void sh_eth_stop(struct sh_eth_dev *eth)
 {
-       sh_eth_write(eth, ~EDRRR_R, EDRRR);
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
+
+       sh_eth_write(port_info, ~EDRRR_R, EDRRR);
 }
 
 int sh_eth_init(struct eth_device *dev, bd_t *bd)
@@ -505,7 +517,7 @@ int sh_eth_init(struct eth_device *dev, bd_t *bd)
        if (ret)
                goto err;
 
-       ret = sh_eth_config(eth, bd);
+       ret = sh_eth_config(eth);
        if (ret)
                goto err_config;
 
@@ -524,6 +536,7 @@ err:
 void sh_eth_halt(struct eth_device *dev)
 {
        struct sh_eth_dev *eth = dev->priv;
+
        sh_eth_stop(eth);
 }
 
@@ -532,6 +545,7 @@ int sh_eth_initialize(bd_t *bd)
        int ret = 0;
        struct sh_eth_dev *eth = NULL;
        struct eth_device *dev = NULL;
+       struct mii_dev *mdiodev;
 
        eth = (struct sh_eth_dev *)malloc(sizeof(struct sh_eth_dev));
        if (!eth) {
@@ -551,6 +565,8 @@ int sh_eth_initialize(bd_t *bd)
 
        eth->port = CONFIG_SH_ETHER_USE_PORT;
        eth->port_info[eth->port].phy_addr = CONFIG_SH_ETHER_PHY_ADDR;
+       eth->port_info[eth->port].iobase =
+               (void __iomem *)(BASE_IO_ADDR + 0x800 * eth->port);
 
        dev->priv = (void *)eth;
        dev->iobase = 0;
@@ -566,17 +582,16 @@ int sh_eth_initialize(bd_t *bd)
        eth_register(dev);
 
        bb_miiphy_buses[0].priv = eth;
-       int retval;
-       struct mii_dev *mdiodev = mdio_alloc();
+       mdiodev = mdio_alloc();
        if (!mdiodev)
                return -ENOMEM;
        strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
        mdiodev->read = bb_miiphy_read;
        mdiodev->write = bb_miiphy_write;
 
-       retval = mdio_register(mdiodev);
-       if (retval < 0)
-               return retval;
+       ret = mdio_register(mdiodev);
+       if (ret < 0)
+               return ret;
 
        if (!eth_env_get_enetaddr("ethaddr", dev->enetaddr))
                puts("Please set MAC address\n");
@@ -603,8 +618,9 @@ static int sh_eth_bb_init(struct bb_miiphy_bus *bus)
 static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus)
 {
        struct sh_eth_dev *eth = bus->priv;
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
 
-       sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MMD, PIR);
+       sh_eth_write(port_info, sh_eth_read(port_info, PIR) | PIR_MMD, PIR);
 
        return 0;
 }
@@ -612,8 +628,9 @@ static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus)
 static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus)
 {
        struct sh_eth_dev *eth = bus->priv;
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
 
-       sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MMD, PIR);
+       sh_eth_write(port_info, sh_eth_read(port_info, PIR) & ~PIR_MMD, PIR);
 
        return 0;
 }
@@ -621,11 +638,14 @@ static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus)
 static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v)
 {
        struct sh_eth_dev *eth = bus->priv;
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
 
        if (v)
-               sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MDO, PIR);
+               sh_eth_write(port_info,
+                            sh_eth_read(port_info, PIR) | PIR_MDO, PIR);
        else
-               sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MDO, PIR);
+               sh_eth_write(port_info,
+                            sh_eth_read(port_info, PIR) & ~PIR_MDO, PIR);
 
        return 0;
 }
@@ -633,8 +653,9 @@ static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v)
 static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v)
 {
        struct sh_eth_dev *eth = bus->priv;
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
 
-       *v = (sh_eth_read(eth, PIR) & PIR_MDI) >> 3;
+       *v = (sh_eth_read(port_info, PIR) & PIR_MDI) >> 3;
 
        return 0;
 }
@@ -642,11 +663,14 @@ static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v)
 static int sh_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v)
 {
        struct sh_eth_dev *eth = bus->priv;
+       struct sh_eth_info *port_info = &eth->port_info[eth->port];
 
        if (v)
-               sh_eth_write(eth, sh_eth_read(eth, PIR) | PIR_MDC, PIR);
+               sh_eth_write(port_info,
+                            sh_eth_read(port_info, PIR) | PIR_MDC, PIR);
        else
-               sh_eth_write(eth, sh_eth_read(eth, PIR) & ~PIR_MDC, PIR);
+               sh_eth_write(port_info,
+                            sh_eth_read(port_info, PIR) & ~PIR_MDC, PIR);
 
        return 0;
 }
@@ -670,4 +694,5 @@ struct bb_miiphy_bus bb_miiphy_buses[] = {
                .delay          = sh_eth_bb_delay,
        }
 };
+
 int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
index 3645f0e..a0dcfca 100644 (file)
 #define ADDR_TO_PHY(addr)      ((int)(addr) & ~0xe0000000)
 #endif
 #elif defined(CONFIG_ARM)
-#define inl            readl
+#ifndef inl
+#define inl    readl
 #define outl   writel
+#endif
 #define ADDR_TO_PHY(addr)      ((int)(addr))
 #define ADDR_TO_P2(addr)       (addr)
 #endif /* defined(CONFIG_SH) */
@@ -90,6 +92,7 @@ struct sh_eth_info {
        u8 phy_addr;
        struct eth_device *dev;
        struct phy_device *phydev;
+       void __iomem *iobase;
 };
 
 struct sh_eth_dev {
@@ -226,61 +229,6 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
        [RMII_MII] =  0x0790,
 };
 
-#if defined(SH_ETH_TYPE_RZ)
-static const u16 sh_eth_offset_rz[SH_ETH_MAX_REGISTER_OFFSET] = {
-       [EDSR]  = 0x0000,
-       [EDMR]  = 0x0400,
-       [EDTRR] = 0x0408,
-       [EDRRR] = 0x0410,
-       [EESR]  = 0x0428,
-       [EESIPR]        = 0x0430,
-       [TDLAR] = 0x0010,
-       [TDFAR] = 0x0014,
-       [TDFXR] = 0x0018,
-       [TDFFR] = 0x001c,
-       [RDLAR] = 0x0030,
-       [RDFAR] = 0x0034,
-       [RDFXR] = 0x0038,
-       [RDFFR] = 0x003c,
-       [TRSCER]        = 0x0438,
-       [RMFCR] = 0x0440,
-       [TFTR]  = 0x0448,
-       [FDR]   = 0x0450,
-       [RMCR]  = 0x0458,
-       [RPADIR]        = 0x0460,
-       [FCFTR] = 0x0468,
-       [CSMR] = 0x04E4,
-
-       [ECMR]  = 0x0500,
-       [ECSR]  = 0x0510,
-       [ECSIPR]        = 0x0518,
-       [PSR]   = 0x0528,
-       [PIPR]  = 0x052c,
-       [RFLR]  = 0x0508,
-       [APR]   = 0x0554,
-       [MPR]   = 0x0558,
-       [PFTCR] = 0x055c,
-       [PFRCR] = 0x0560,
-       [TPAUSER]       = 0x0564,
-       [GECMR] = 0x05b0,
-       [BCULR] = 0x05b4,
-       [MAHR]  = 0x05c0,
-       [MALR]  = 0x05c8,
-       [TROCR] = 0x0700,
-       [CDCR]  = 0x0708,
-       [LCCR]  = 0x0710,
-       [CEFCR] = 0x0740,
-       [FRECR] = 0x0748,
-       [TSFRCR]        = 0x0750,
-       [TLFRCR]        = 0x0758,
-       [RFCR]  = 0x0760,
-       [CERCR] = 0x0768,
-       [CEECR] = 0x0770,
-       [MAFCR] = 0x0778,
-       [RMII_MII] =  0x0790,
-};
-#endif
-
 static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
        [ECMR]  = 0x0100,
        [RFLR]  = 0x0108,
@@ -654,29 +602,27 @@ enum FIFO_SIZE_BIT {
        FIFO_SIZE_T = 0x00000700, FIFO_SIZE_R = 0x00000007,
 };
 
-static inline unsigned long sh_eth_reg_addr(struct sh_eth_dev *eth,
+static inline unsigned long sh_eth_reg_addr(struct sh_eth_info *port,
                                            int enum_index)
 {
-#if defined(SH_ETH_TYPE_GETHER)
+#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)
        const u16 *reg_offset = sh_eth_offset_gigabit;
 #elif defined(SH_ETH_TYPE_ETHER)
        const u16 *reg_offset = sh_eth_offset_fast_sh4;
-#elif defined(SH_ETH_TYPE_RZ)
-       const u16 *reg_offset = sh_eth_offset_rz;
 #else
 #error
 #endif
-       return BASE_IO_ADDR + reg_offset[enum_index] + 0x800 * eth->port;
+       return (unsigned long)port->iobase + reg_offset[enum_index];
 }
 
-static inline void sh_eth_write(struct sh_eth_dev *eth, unsigned long data,
+static inline void sh_eth_write(struct sh_eth_info *port, unsigned long data,
                                int enum_index)
 {
-       outl(data, sh_eth_reg_addr(eth, enum_index));
+       outl(data, sh_eth_reg_addr(port, enum_index));
 }
 
-static inline unsigned long sh_eth_read(struct sh_eth_dev *eth,
+static inline unsigned long sh_eth_read(struct sh_eth_info *port,
                                        int enum_index)
 {
-       return inl(sh_eth_reg_addr(eth, enum_index));
+       return inl(sh_eth_reg_addr(port, enum_index));
 }
index 35518da..e35ddc8 100644 (file)
@@ -44,7 +44,6 @@
 #define CONFIG_SPI_FLASH_QUAD
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x1
 #define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
index 37aaec3..2a01000 100644 (file)
@@ -18,7 +18,6 @@
 #undef  CONFIG_SHOW_BOOT_PROGRESS
 
 /* Ether */
-#define CONFIG_SH_ETHER 1
 #define CONFIG_SH_ETHER_USE_PORT (0)
 #define CONFIG_SH_ETHER_PHY_ADDR (0x0)
 #define CONFIG_SH_ETHER_PHY_MODE (PHY_INTERFACE_MODE_GMII)
index 66ae76b..94aecb7 100644 (file)
@@ -88,7 +88,6 @@
 #define CONFIG_ENV_SIZE_REDUND (CONFIG_ENV_SECT_SIZE)
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x0
 #define CONFIG_SH_ETHER_BASE_ADDR      0xe9a00000
index c6fb59f..32d679d 100644 (file)
@@ -44,7 +44,6 @@
 #define CONFIG_SH_I2C_CLOCK    41666666
 
 /* Ether */
-#define CONFIG_SH_ETHER 1
 #define CONFIG_SH_ETHER_USE_PORT (0)
 #define CONFIG_SH_ETHER_PHY_ADDR (0x1f)
 #define CONFIG_PHY_SMSC 1
index a5ac8cb..65221fc 100644 (file)
@@ -77,7 +77,6 @@
 #define CONFIG_SYS_TMU_CLK_DIV      4
 
 /* Ether */
-#define CONFIG_SH_ETHER 1
 #define CONFIG_SH_ETHER_USE_PORT (1)
 #define CONFIG_SH_ETHER_PHY_ADDR (0x00)
 #define CONFIG_BITBANGMII
index 610ba1a..fab0edd 100644 (file)
@@ -44,7 +44,6 @@
 #define CONFIG_SH_QSPI
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x1
 #define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
index b9214d2..c449e43 100644 (file)
@@ -44,7 +44,6 @@
 #define CONFIG_SH_QSPI
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x1
 #define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
index 291b03c..000e5cd 100644 (file)
@@ -44,7 +44,6 @@
 #define CONFIG_SH_QSPI
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x1
 #define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
index 451d9dd..10dce6b 100644 (file)
@@ -45,7 +45,6 @@
 #define CONFIG_SPI_FLASH_QUAD
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x1
 #define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
index 9258a3b..f9800ec 100644 (file)
@@ -18,7 +18,6 @@
 #undef  CONFIG_SHOW_BOOT_PROGRESS
 
 /* Ether */
-#define CONFIG_SH_ETHER 1
 #define CONFIG_SH_ETHER_USE_PORT (0)
 #define CONFIG_SH_ETHER_PHY_ADDR (0x0)
 #define CONFIG_PHY_SMSC 1
index 2f81cc5..ee57eb2 100644 (file)
@@ -47,7 +47,6 @@
 #define CONFIG_SYS_BOOTMAPSZ           (8 * 1024 * 1024)
 
 /* Ether */
-#define CONFIG_SH_ETHER                        1
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       18
 #define CONFIG_SH_ETHER_CACHE_WRITEBACK        1
index bcb85a6..e7f9f61 100644 (file)
@@ -47,7 +47,6 @@
 #define CONFIG_SYS_BOOTMAPSZ           (8 * 1024 * 1024)
 
 /* Ether */
-#define CONFIG_SH_ETHER                        1
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       18
 #define CONFIG_SH_ETHER_CACHE_WRITEBACK        1
index bee1a1d..a2b3307 100644 (file)
@@ -48,7 +48,6 @@
 #define CONFIG_SYS_BOOTMAPSZ           (8 * 1024 * 1024)
 
 /* Ether */
-#define CONFIG_SH_ETHER                        1
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       1
 #define CONFIG_SH_ETHER_CACHE_WRITEBACK        1
index 0598b25..de4a587 100644 (file)
@@ -77,7 +77,6 @@
 #define CONFIG_SYS_TMU_CLK_DIV         (4)     /* 4 (default), 16, 64, 256 or 1024 */
 
 /* Ether */
-#define CONFIG_SH_ETHER 1
 #define CONFIG_SH_ETHER_USE_PORT (1)
 #define CONFIG_SH_ETHER_PHY_ADDR (0x01)
 #define CONFIG_BITBANGMII
index 0384325..79a4f06 100644 (file)
@@ -45,7 +45,6 @@
 #define CONFIG_SPI_FLASH_QUAD
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x1
 #define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
index 9422c04..789f364 100644 (file)
@@ -48,7 +48,6 @@
 #define CONFIG_SPI_FLASH_QUAD
 
 /* SH Ether */
-#define CONFIG_SH_ETHER
 #define CONFIG_SH_ETHER_USE_PORT       0
 #define CONFIG_SH_ETHER_PHY_ADDR       0x1
 #define CONFIG_SH_ETHER_PHY_MODE PHY_INTERFACE_MODE_RMII
index 50f1e12..0543ec1 100644 (file)
@@ -257,6 +257,7 @@ int gen10g_startup(struct phy_device *phydev);
 int gen10g_shutdown(struct phy_device *phydev);
 int gen10g_discover_mmds(struct phy_device *phydev);
 
+int phy_b53_init(void);
 int phy_mv88e61xx_init(void);
 int phy_aquantia_init(void);
 int phy_atheros_init(void);
index 73370a1..efa9599 100644 (file)
@@ -14,7 +14,6 @@
 #include <net.h>
 #include <net/tftp.h>
 #include "bootp.h"
-#include "nfs.h"
 #ifdef CONFIG_LED_STATUS
 #include <status_led.h>
 #endif
@@ -387,12 +386,19 @@ static void bootp_timeout_handler(void)
 
        if (time_taken >= time_taken_max) {
 #ifdef CONFIG_BOOTP_MAY_FAIL
-               puts("\nRetry time exceeded\n");
-               net_set_state(NETLOOP_FAIL);
-#else
-               puts("\nRetry time exceeded; starting again\n");
-               net_start_again();
+               char *ethrotate;
+
+               ethrotate = env_get("ethrotate");
+               if ((ethrotate && strcmp(ethrotate, "no") == 0) ||
+                   net_restart_wrap) {
+                       puts("\nRetry time exceeded\n");
+                       net_set_state(NETLOOP_FAIL);
+               } else
 #endif
+               {
+                       puts("\nRetry time exceeded; starting again\n");
+                       net_start_again();
+               }
        } else {
                bootp_timeout *= 2;
                if (bootp_timeout > 2000)
index 4e87d66..394243b 100644 (file)
@@ -1924,7 +1924,6 @@ CONFIG_SHOW_ACTIVITY
 CONFIG_SHOW_BOOT_PROGRESS
 CONFIG_SH_CMT_CLK_FREQ
 CONFIG_SH_DSP
-CONFIG_SH_ETHER
 CONFIG_SH_ETHER_ALIGNE_SIZE
 CONFIG_SH_ETHER_BASE_ADDR
 CONFIG_SH_ETHER_CACHE_INVALIDATE