From b904725a112f7b7a1b5d657541d77dc8fa1a1615 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 13:38:32 +0100 Subject: net: gem: Do not continue if phy is not found Add return value for phy detection algorithm to stop init function when phy is not found. Signed-off-by: Michal Simek Reviewed-by: Jagan Teki --- drivers/net/zynq_gem.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 858093f0d7..1a5a366c94 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -241,7 +241,7 @@ static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data) ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data); } -static void phy_detection(struct eth_device *dev) +static int phy_detection(struct eth_device *dev) { int i; u16 phyreg; @@ -254,7 +254,7 @@ static void phy_detection(struct eth_device *dev) /* Found a valid PHY address */ debug("Default phy address %d is valid\n", priv->phyaddr); - return; + return 0; } else { debug("PHY address is not setup correctly %d\n", priv->phyaddr); @@ -272,11 +272,12 @@ static void phy_detection(struct eth_device *dev) /* Found a valid PHY address */ priv->phyaddr = i; debug("Found valid phy address, %d\n", i); - return; + return 0; } } } printf("PHY is not detected\n"); + return -1; } static int zynq_gem_setup_mac(struct eth_device *dev) @@ -310,6 +311,7 @@ static int zynq_gem_setup_mac(struct eth_device *dev) static int zynq_gem_init(struct eth_device *dev, bd_t * bis) { u32 i; + int ret; unsigned long clk_rate = 0; struct phy_device *phydev; struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; @@ -384,7 +386,11 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) priv->init++; } - phy_detection(dev); + ret = phy_detection(dev); + if (ret) { + printf("GEM PHY init failed\n"); + return ret; + } /* interface - look at tsec */ phydev = phy_connect(priv->bus, priv->phyaddr, dev, -- cgit From 3fac27243c1ee4bdf903bac031e522f97e27ef44 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 10:09:43 +0100 Subject: net: gem: Change mdio_wait prototype to pass regs Pass regs instead of dev because this will be chagned by driver model. Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 1a5a366c94..7f801d5c4c 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -172,9 +172,8 @@ struct zynq_gem_priv { struct mii_dev *bus; }; -static inline int mdio_wait(struct eth_device *dev) +static inline int mdio_wait(struct zynq_gem_regs *regs) { - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; u32 timeout = 20000; /* Wait till MDIO interface is ready to accept a new transaction. */ @@ -198,7 +197,7 @@ static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum, u32 mgtcr; struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; - if (mdio_wait(dev)) + if (mdio_wait(regs)) return 1; /* Construct mgtcr mask for the operation */ @@ -209,7 +208,7 @@ static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum, /* Write mgtcr and wait for completion */ writel(mgtcr, ®s->phymntnc); - if (mdio_wait(dev)) + if (mdio_wait(regs)) return 1; if (op == ZYNQ_GEM_PHYMNTNC_OP_R_MASK) -- cgit From f2fc27684f4d1f4e0395fcb90a8e5451aeabc2b8 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 10:24:15 +0100 Subject: net: gem: Change mii function not to use eth_device structure Next step to move driver to driver model. Do not use eth_device structure. Use private structure instead. Add iobase to private structure to store gem iobase. Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 7f801d5c4c..65ea5deb23 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -167,6 +167,7 @@ struct zynq_gem_priv { int phyaddr; u32 emio; int init; + struct zynq_gem_regs *iobase; phy_interface_t interface; struct phy_device *phydev; struct mii_dev *bus; @@ -191,11 +192,11 @@ static inline int mdio_wait(struct zynq_gem_regs *regs) return 0; } -static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum, - u32 op, u16 *data) +static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum, + u32 op, u16 *data) { u32 mgtcr; - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; + struct zynq_gem_regs *regs = priv->iobase; if (mdio_wait(regs)) return 1; @@ -217,12 +218,13 @@ static u32 phy_setup_op(struct eth_device *dev, u32 phy_addr, u32 regnum, return 0; } -static u32 phyread(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 *val) +static u32 phyread(struct zynq_gem_priv *priv, u32 phy_addr, + u32 regnum, u16 *val) { u32 ret; - ret = phy_setup_op(dev, phy_addr, regnum, - ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val); + ret = phy_setup_op(priv, phy_addr, regnum, + ZYNQ_GEM_PHYMNTNC_OP_R_MASK, val); if (!ret) debug("%s: phy_addr %d, regnum 0x%x, val 0x%x\n", __func__, @@ -231,13 +233,14 @@ static u32 phyread(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 *val) return ret; } -static u32 phywrite(struct eth_device *dev, u32 phy_addr, u32 regnum, u16 data) +static u32 phywrite(struct zynq_gem_priv *priv, u32 phy_addr, + u32 regnum, u16 data) { debug("%s: phy_addr %d, regnum 0x%x, data 0x%x\n", __func__, phy_addr, regnum, data); - return phy_setup_op(dev, phy_addr, regnum, - ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data); + return phy_setup_op(priv, phy_addr, regnum, + ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data); } static int phy_detection(struct eth_device *dev) @@ -247,7 +250,7 @@ static int phy_detection(struct eth_device *dev) struct zynq_gem_priv *priv = dev->priv; if (priv->phyaddr != -1) { - phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg); + phyread(priv, priv->phyaddr, PHY_DETECT_REG, &phyreg); if ((phyreg != 0xFFFF) && ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { /* Found a valid PHY address */ @@ -265,7 +268,7 @@ static int phy_detection(struct eth_device *dev) if (priv->phyaddr == -1) { /* detect the PHY address */ for (i = 31; i >= 0; i--) { - phyread(dev, i, PHY_DETECT_REG, &phyreg); + phyread(priv, i, PHY_DETECT_REG, &phyreg); if ((phyreg != 0xFFFF) && ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { /* Found a valid PHY address */ @@ -561,9 +564,10 @@ static int zynq_gem_miiphyread(const char *devname, uchar addr, uchar reg, ushort *val) { struct eth_device *dev = eth_get_dev(); + struct zynq_gem_priv *priv = dev->priv; int ret; - ret = phyread(dev, addr, reg, val); + ret = phyread(priv, addr, reg, val); debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *val); return ret; } @@ -572,9 +576,10 @@ static int zynq_gem_miiphy_write(const char *devname, uchar addr, uchar reg, ushort val) { struct eth_device *dev = eth_get_dev(); + struct zynq_gem_priv *priv = dev->priv; debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val); - return phywrite(dev, addr, reg, val); + return phywrite(priv, addr, reg, val); } int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, @@ -620,6 +625,7 @@ int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, sprintf(dev->name, "Gem.%lx", base_addr); dev->iobase = base_addr; + priv->iobase = (struct zynq_gem_regs *)base_addr; dev->init = zynq_gem_init; dev->halt = zynq_gem_halt; -- cgit From 64a7ead64bdb965c648df1fc34143e203b1d979a Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 13:44:49 +0100 Subject: net: gem: Remove phydev variable Resort code to use priv->phydev variable directly. It will simplify move to DM. Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 65ea5deb23..8f3fe91300 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -315,7 +315,6 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) u32 i; int ret; unsigned long clk_rate = 0; - struct phy_device *phydev; struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; struct zynq_gem_priv *priv = dev->priv; struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; @@ -394,23 +393,21 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) return ret; } - /* interface - look at tsec */ - phydev = phy_connect(priv->bus, priv->phyaddr, dev, - priv->interface); + priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, + priv->interface); - phydev->supported = supported | ADVERTISED_Pause | - ADVERTISED_Asym_Pause; - phydev->advertising = phydev->supported; - priv->phydev = phydev; - phy_config(phydev); - phy_startup(phydev); + priv->phydev->supported = supported | ADVERTISED_Pause | + ADVERTISED_Asym_Pause; + priv->phydev->advertising = priv->phydev->supported; + phy_config(priv->phydev); + phy_startup(priv->phydev); - if (!phydev->link) { - printf("%s: No link.\n", phydev->dev->name); + if (!priv->phydev->link) { + printf("%s: No link.\n", priv->phydev->dev->name); return -1; } - switch (phydev->speed) { + switch (priv->phydev->speed) { case SPEED_1000: writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, ®s->nwcfg); -- cgit From 68cc3bd8b2863667513008c975cc69187855317f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 13:54:43 +0100 Subject: net: gem: Extract phy init code Move phy init code out of zynq_gem_init. DM drivers are normally calling this code from probe function. Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 8f3fe91300..86bb759050 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -310,15 +310,10 @@ static int zynq_gem_setup_mac(struct eth_device *dev) return 0; } -static int zynq_gem_init(struct eth_device *dev, bd_t * bis) +static int zynq_phy_init(struct eth_device *dev) { - u32 i; int ret; - unsigned long clk_rate = 0; - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; struct zynq_gem_priv *priv = dev->priv; - struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; - struct emac_bd *dummy_rx_bd = &priv->tx_bd[TX_FREE_DESC + 2]; const u32 supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -326,6 +321,33 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; + ret = phy_detection(dev); + if (ret) { + printf("GEM PHY init failed\n"); + return ret; + } + + priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, + priv->interface); + + priv->phydev->supported = supported | ADVERTISED_Pause | + ADVERTISED_Asym_Pause; + priv->phydev->advertising = priv->phydev->supported; + phy_config(priv->phydev); + + return 0; +} + +static int zynq_gem_init(struct eth_device *dev, bd_t *bis) +{ + u32 i; + int ret; + unsigned long clk_rate = 0; + struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; + struct zynq_gem_priv *priv = dev->priv; + struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; + struct emac_bd *dummy_rx_bd = &priv->tx_bd[TX_FREE_DESC + 2]; + if (!priv->init) { /* Disable all interrupts */ writel(0xFFFFFFFF, ®s->idr); @@ -387,19 +409,10 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) priv->init++; } - ret = phy_detection(dev); - if (ret) { - printf("GEM PHY init failed\n"); + ret = zynq_phy_init(dev); + if (ret) return ret; - } - - priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, - priv->interface); - priv->phydev->supported = supported | ADVERTISED_Pause | - ADVERTISED_Asym_Pause; - priv->phydev->advertising = priv->phydev->supported; - phy_config(priv->phydev); phy_startup(priv->phydev); if (!priv->phydev->link) { -- cgit From 90c6f2e21bb980e5544b1339e7ef7038bc872968 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 14:03:37 +0100 Subject: net: gem: Check if priv->phydev is valid Check return value. Signed-off-by: Michal Simek Reviewed-by: Jagan Teki --- drivers/net/zynq_gem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 86bb759050..d5540ec215 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -329,6 +329,8 @@ static int zynq_phy_init(struct eth_device *dev) priv->phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); + if (!priv->phydev) + return -ENODEV; priv->phydev->supported = supported | ADVERTISED_Pause | ADVERTISED_Asym_Pause; -- cgit From c8e29271b1a45ec87386857b506cfd918d9a4ad2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 13:58:36 +0100 Subject: net: gem: Enable MDIO bus earlier Enable access to MDIO before zynq_gem_init is called. It enables read information about phy earlier. Signed-off-by: Michal Simek --- drivers/net/zynq_gem.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index d5540ec215..9ce1221e8d 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -314,6 +314,7 @@ static int zynq_phy_init(struct eth_device *dev) { int ret; struct zynq_gem_priv *priv = dev->priv; + struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; const u32 supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -321,6 +322,9 @@ static int zynq_phy_init(struct eth_device *dev) SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; + /* Enable only MDIO bus */ + writel(ZYNQ_GEM_NWCTRL_MDEN_MASK, ®s->nwctrl); + ret = phy_detection(dev); if (ret) { printf("GEM PHY init failed\n"); @@ -343,7 +347,6 @@ static int zynq_phy_init(struct eth_device *dev) static int zynq_gem_init(struct eth_device *dev, bd_t *bis) { u32 i; - int ret; unsigned long clk_rate = 0; struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; struct zynq_gem_priv *priv = dev->priv; @@ -411,10 +414,6 @@ static int zynq_gem_init(struct eth_device *dev, bd_t *bis) priv->init++; } - ret = zynq_phy_init(dev); - if (ret) - return ret; - phy_startup(priv->phydev); if (!priv->phydev->link) { @@ -597,6 +596,7 @@ static int zynq_gem_miiphy_write(const char *devname, uchar addr, int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, int phy_addr, u32 emio) { + int ret; struct eth_device *dev; struct zynq_gem_priv *priv; void *bd_space; @@ -650,6 +650,10 @@ int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, miiphy_register(dev->name, zynq_gem_miiphyread, zynq_gem_miiphy_write); priv->bus = miiphy_get_dev_by_name(dev->name); + ret = zynq_phy_init(dev); + if (ret) + return ret; + return 1; } -- cgit From 687d73126361b45f77f977301d141771babd02c0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 14:00:20 +0100 Subject: net: gem: Remove zynq_gem_of_init() This function was used for OF init before DM. Remove this function as the part of move to DM. Signed-off-by: Michal Simek Reviewed-by: Simon Glass Reviewed-by: Jagan Teki --- drivers/net/zynq_gem.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 9ce1221e8d..a569c77aeb 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include #include #include @@ -656,43 +654,3 @@ int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, return 1; } - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int zynq_gem_of_init(const void *blob) -{ - int offset = 0; - u32 ret = 0; - u32 reg, phy_reg; - - debug("ZYNQ GEM: Initialization\n"); - - do { - offset = fdt_node_offset_by_compatible(blob, offset, - "xlnx,ps7-ethernet-1.00.a"); - if (offset != -1) { - reg = fdtdec_get_addr(blob, offset, "reg"); - if (reg != FDT_ADDR_T_NONE) { - offset = fdtdec_lookup_phandle(blob, offset, - "phy-handle"); - if (offset != -1) - phy_reg = fdtdec_get_addr(blob, offset, - "reg"); - else - phy_reg = 0; - - debug("ZYNQ GEM: addr %x, phyaddr %x\n", - reg, phy_reg); - - ret |= zynq_gem_initialize(NULL, reg, - phy_reg, 0); - - } else { - debug("ZYNQ GEM: Can't get base address\n"); - return -1; - } - } - } while (offset != -1); - - return ret; -} -#endif -- cgit From 5a9284f7f503f21c0f231b96d62747662080050d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 14:14:37 +0100 Subject: net: gem: Fix miiphy_read name Sync it with write function. Signed-off-by: Michal Simek Reviewed-by: Jagan Teki --- 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 a569c77aeb..4e93707c7a 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -569,7 +569,7 @@ static void zynq_gem_halt(struct eth_device *dev) ZYNQ_GEM_NWCTRL_TXEN_MASK, 0); } -static int zynq_gem_miiphyread(const char *devname, uchar addr, +static int zynq_gem_miiphy_read(const char *devname, uchar addr, uchar reg, ushort *val) { struct eth_device *dev = eth_get_dev(); @@ -645,7 +645,7 @@ int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, eth_register(dev); - miiphy_register(dev->name, zynq_gem_miiphyread, zynq_gem_miiphy_write); + miiphy_register(dev->name, zynq_gem_miiphy_read, zynq_gem_miiphy_write); priv->bus = miiphy_get_dev_by_name(dev->name); ret = zynq_phy_init(dev); -- cgit From 6889ca7198f68691ddd7923268040eb7f4e6d3ff Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 14:14:56 +0100 Subject: net: gem: Move driver to DM - Enable DM_ETH by default for Zynq and ZynqMP - Remove board_eth_init code - Change miiphy_read function to return value instead of error code based on DM requirement - Do not enable EMIO DT support by default Signed-off-by: Michal Simek Reviewed-by: Jagan Teki Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- drivers/net/zynq_gem.c | 179 ++++++++++++++++++++++++++++++------------------- 1 file changed, 110 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 4e93707c7a..9e8616e053 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -23,6 +24,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + #if !defined(CONFIG_PHYLIB) # error XILINX_GEM_ETHERNET requires PHYLIB #endif @@ -241,7 +244,7 @@ static u32 phywrite(struct zynq_gem_priv *priv, u32 phy_addr, ZYNQ_GEM_PHYMNTNC_OP_W_MASK, &data); } -static int phy_detection(struct eth_device *dev) +static int phy_detection(struct udevice *dev) { int i; u16 phyreg; @@ -280,20 +283,22 @@ static int phy_detection(struct eth_device *dev) return -1; } -static int zynq_gem_setup_mac(struct eth_device *dev) +static int zynq_gem_setup_mac(struct udevice *dev) { u32 i, macaddrlow, macaddrhigh; - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; + struct eth_pdata *pdata = dev_get_platdata(dev); + struct zynq_gem_priv *priv = dev_get_priv(dev); + struct zynq_gem_regs *regs = priv->iobase; /* Set the MAC bits [31:0] in BOT */ - macaddrlow = dev->enetaddr[0]; - macaddrlow |= dev->enetaddr[1] << 8; - macaddrlow |= dev->enetaddr[2] << 16; - macaddrlow |= dev->enetaddr[3] << 24; + macaddrlow = pdata->enetaddr[0]; + macaddrlow |= pdata->enetaddr[1] << 8; + macaddrlow |= pdata->enetaddr[2] << 16; + macaddrlow |= pdata->enetaddr[3] << 24; /* Set MAC bits [47:32] in TOP */ - macaddrhigh = dev->enetaddr[4]; - macaddrhigh |= dev->enetaddr[5] << 8; + macaddrhigh = pdata->enetaddr[4]; + macaddrhigh |= pdata->enetaddr[5] << 8; for (i = 0; i < 4; i++) { writel(0, ®s->laddr[i][LADDR_LOW]); @@ -308,11 +313,11 @@ static int zynq_gem_setup_mac(struct eth_device *dev) return 0; } -static int zynq_phy_init(struct eth_device *dev) +static int zynq_phy_init(struct udevice *dev) { int ret; - struct zynq_gem_priv *priv = dev->priv; - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; + struct zynq_gem_priv *priv = dev_get_priv(dev); + struct zynq_gem_regs *regs = priv->iobase; const u32 supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -342,12 +347,12 @@ static int zynq_phy_init(struct eth_device *dev) return 0; } -static int zynq_gem_init(struct eth_device *dev, bd_t *bis) +static int zynq_gem_init(struct udevice *dev) { u32 i; unsigned long clk_rate = 0; - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; - struct zynq_gem_priv *priv = dev->priv; + struct zynq_gem_priv *priv = dev_get_priv(dev); + struct zynq_gem_regs *regs = priv->iobase; struct emac_bd *dummy_tx_bd = &priv->tx_bd[TX_FREE_DESC]; struct emac_bd *dummy_rx_bd = &priv->tx_bd[TX_FREE_DESC + 2]; @@ -437,7 +442,7 @@ static int zynq_gem_init(struct eth_device *dev, bd_t *bis) /* Change the rclk and clk only not using EMIO interface */ if (!priv->emio) - zynq_slcr_gem_clk_setup(dev->iobase != + zynq_slcr_gem_clk_setup((ulong)priv->iobase != ZYNQ_GEM_BASEADDR0, clk_rate); setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | @@ -473,11 +478,11 @@ static int wait_for_bit(const char *func, u32 *reg, const u32 mask, return -ETIMEDOUT; } -static int zynq_gem_send(struct eth_device *dev, void *ptr, int len) +static int zynq_gem_send(struct udevice *dev, void *ptr, int len) { u32 addr, size; - struct zynq_gem_priv *priv = dev->priv; - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; + struct zynq_gem_priv *priv = dev_get_priv(dev); + struct zynq_gem_regs *regs = priv->iobase; struct emac_bd *current_bd = &priv->tx_bd[1]; /* Setup Tx BD */ @@ -518,10 +523,10 @@ static int zynq_gem_send(struct eth_device *dev, void *ptr, int len) } /* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */ -static int zynq_gem_recv(struct eth_device *dev) +static int zynq_gem_recv(struct udevice *dev, int flags, uchar **packetp) { int frame_len; - struct zynq_gem_priv *priv = dev->priv; + struct zynq_gem_priv *priv = dev_get_priv(dev); struct emac_bd *current_bd = &priv->rx_bd[priv->rxbd_current]; struct emac_bd *first_bd; @@ -561,54 +566,41 @@ static int zynq_gem_recv(struct eth_device *dev) return frame_len; } -static void zynq_gem_halt(struct eth_device *dev) +static void zynq_gem_halt(struct udevice *dev) { - struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase; + struct zynq_gem_priv *priv = dev_get_priv(dev); + struct zynq_gem_regs *regs = priv->iobase; clrsetbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK, 0); } -static int zynq_gem_miiphy_read(const char *devname, uchar addr, - uchar reg, ushort *val) +static int zynq_gem_miiphy_read(struct mii_dev *bus, int addr, + int devad, int reg) { - struct eth_device *dev = eth_get_dev(); - struct zynq_gem_priv *priv = dev->priv; + struct zynq_gem_priv *priv = bus->priv; int ret; + u16 val; - ret = phyread(priv, addr, reg, val); - debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, *val); - return ret; + ret = phyread(priv, addr, reg, &val); + debug("%s 0x%x, 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val, ret); + return val; } -static int zynq_gem_miiphy_write(const char *devname, uchar addr, - uchar reg, ushort val) +static int zynq_gem_miiphy_write(struct mii_dev *bus, int addr, int devad, + int reg, u16 value) { - struct eth_device *dev = eth_get_dev(); - struct zynq_gem_priv *priv = dev->priv; + struct zynq_gem_priv *priv = bus->priv; - debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, val); - return phywrite(priv, addr, reg, val); + debug("%s 0x%x, 0x%x, 0x%x\n", __func__, addr, reg, value); + return phywrite(priv, addr, reg, value); } -int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, - int phy_addr, u32 emio) +static int zynq_gem_probe(struct udevice *dev) { - int ret; - struct eth_device *dev; - struct zynq_gem_priv *priv; void *bd_space; - - dev = calloc(1, sizeof(*dev)); - if (dev == NULL) - return -1; - - dev->priv = calloc(1, sizeof(struct zynq_gem_priv)); - if (dev->priv == NULL) { - free(dev); - return -1; - } - priv = dev->priv; + struct zynq_gem_priv *priv = dev_get_priv(dev); + int ret; /* Align rxbuffers to ARCH_DMA_MINALIGN */ priv->rxbuffers = memalign(ARCH_DMA_MINALIGN, RX_BUF * PKTSIZE_ALIGN); @@ -623,8 +615,11 @@ int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, priv->tx_bd = (struct emac_bd *)bd_space; priv->rx_bd = (struct emac_bd *)((ulong)bd_space + BD_SEPRN_SPACE); - priv->phyaddr = phy_addr; - priv->emio = emio; + priv->bus = mdio_alloc(); + priv->bus->read = zynq_gem_miiphy_read; + priv->bus->write = zynq_gem_miiphy_write; + priv->bus->priv = priv; + strcpy(priv->bus->name, "gem"); #ifndef CONFIG_ZYNQ_GEM_INTERFACE priv->interface = PHY_INTERFACE_MODE_MII; @@ -632,25 +627,71 @@ int zynq_gem_initialize(bd_t *bis, phys_addr_t base_addr, priv->interface = CONFIG_ZYNQ_GEM_INTERFACE; #endif - sprintf(dev->name, "Gem.%lx", base_addr); + ret = mdio_register(priv->bus); + if (ret) + return ret; - dev->iobase = base_addr; - priv->iobase = (struct zynq_gem_regs *)base_addr; + zynq_phy_init(dev); - dev->init = zynq_gem_init; - dev->halt = zynq_gem_halt; - dev->send = zynq_gem_send; - dev->recv = zynq_gem_recv; - dev->write_hwaddr = zynq_gem_setup_mac; + return 0; +} - eth_register(dev); +static int zynq_gem_remove(struct udevice *dev) +{ + struct zynq_gem_priv *priv = dev_get_priv(dev); - miiphy_register(dev->name, zynq_gem_miiphy_read, zynq_gem_miiphy_write); - priv->bus = miiphy_get_dev_by_name(dev->name); + free(priv->phydev); + mdio_unregister(priv->bus); + mdio_free(priv->bus); - ret = zynq_phy_init(dev); - if (ret) - return ret; + return 0; +} + +static const struct eth_ops zynq_gem_ops = { + .start = zynq_gem_init, + .send = zynq_gem_send, + .recv = zynq_gem_recv, + .stop = zynq_gem_halt, + .write_hwaddr = zynq_gem_setup_mac, +}; - return 1; +static int zynq_gem_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct zynq_gem_priv *priv = dev_get_priv(dev); + int offset = 0; + + pdata->iobase = (phys_addr_t)dev_get_addr(dev); + priv->iobase = (struct zynq_gem_regs *)pdata->iobase; + /* Hardcode for now */ + priv->emio = 0; + + offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset, + "phy-handle"); + if (offset > 0) + priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", 0); + + printf("ZYNQ GEM: %lx, phyaddr %d\n", (ulong)priv->iobase, + priv->phyaddr); + + return 0; } + +static const struct udevice_id zynq_gem_ids[] = { + { .compatible = "cdns,zynqmp-gem" }, + { .compatible = "cdns,zynq-gem" }, + { .compatible = "cdns,gem" }, + { } +}; + +U_BOOT_DRIVER(zynq_gem) = { + .name = "zynq_gem", + .id = UCLASS_ETH, + .of_match = zynq_gem_ids, + .ofdata_to_platdata = zynq_gem_ofdata_to_platdata, + .probe = zynq_gem_probe, + .remove = zynq_gem_remove, + .ops = &zynq_gem_ops, + .priv_auto_alloc_size = sizeof(struct zynq_gem_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; -- cgit From 3cdb1450deb236184f0c673f6ea0ad993c285ad2 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 14:17:50 +0100 Subject: net: gem: Read information about interface from DT Do not set interface via configs. Read information from DT. Signed-off-by: Michal Simek Reviewed-by: Jagan Teki --- drivers/net/zynq_gem.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 9e8616e053..0ee909c97f 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -621,12 +621,6 @@ static int zynq_gem_probe(struct udevice *dev) priv->bus->priv = priv; strcpy(priv->bus->name, "gem"); -#ifndef CONFIG_ZYNQ_GEM_INTERFACE - priv->interface = PHY_INTERFACE_MODE_MII; -#else - priv->interface = CONFIG_ZYNQ_GEM_INTERFACE; -#endif - ret = mdio_register(priv->bus); if (ret) return ret; @@ -660,6 +654,7 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev) struct eth_pdata *pdata = dev_get_platdata(dev); struct zynq_gem_priv *priv = dev_get_priv(dev); int offset = 0; + const char *phy_mode; pdata->iobase = (phys_addr_t)dev_get_addr(dev); priv->iobase = (struct zynq_gem_regs *)pdata->iobase; @@ -671,8 +666,17 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev) if (offset > 0) priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", 0); - printf("ZYNQ GEM: %lx, phyaddr %d\n", (ulong)priv->iobase, - priv->phyaddr); + phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL); + if (phy_mode) + pdata->phy_interface = phy_get_interface_by_name(phy_mode); + if (pdata->phy_interface == -1) { + debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); + return -EINVAL; + } + priv->interface = pdata->phy_interface; + + printf("ZYNQ GEM: %lx, phyaddr %d, interface %s\n", (ulong)priv->iobase, + priv->phyaddr, phy_string_for_interface(priv->interface)); return 0; } -- cgit From 596e5782e7bdec7ed275b1204122364a3ab4fbf7 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 14:34:52 +0100 Subject: net: gem: Move gem to Kconfig Signed-off-by: Michal Simek Reviewed-by: Jagan Teki --- drivers/net/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a03a95d0fb..6905cc02e3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -101,4 +101,10 @@ config PCH_GBE This MAC is present in Intel Platform Controller Hub EG20T. It supports 10/100/1000 Mbps operation. +config ZYNQ_GEM + depends on DM_ETH && (ARCH_ZYNQ || ARCH_ZYNQMP) + bool "Xilinx Ethernet GEM" + help + This MAC is presetn in Xilinx Zynq and ZynqMP SoCs. + endif # NETDEVICES -- cgit From b8de29feaee2a26e4a72800ed17994c9312f1735 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 24 Sep 2015 20:13:45 +0200 Subject: net: gem: Enable CTRL+C in wait_for_bit Enable to break waiting loop at any time. Signed-off-by: Michal Simek Acked-by: Joe Hershberger --- drivers/net/zynq_gem.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 0ee909c97f..0a41281e90 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -469,6 +470,11 @@ static int wait_for_bit(const char *func, u32 *reg, const u32 mask, if (get_timer(start) > timeout) break; + if (ctrlc()) { + puts("Abort\n"); + return -EINTR; + } + udelay(1); } -- cgit From b8a9bebeecbf915f2fecab0cfa90899abd872512 Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Wed, 25 Nov 2015 11:51:37 +0530 Subject: zynq: sdhci: Calculate minimum frequency based on max frequency Calculate the minimum sd clock based on max clock. This will be done by add_sdhci() if we pass minimum clock as zero. It also does based on SD host contoller version. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/mmc/zynq_sdhci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index e169b77493..2d6cb31e12 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -29,7 +29,7 @@ int zynq_sdhci_init(phys_addr_t regbase) SDHCI_QUIRK_BROKEN_R1B; host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 52000000 >> 9); + add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 0); return 0; } -- cgit From 400434537b6c79116dde82899037ae532e81482d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 16:07:07 +0100 Subject: zynq: sdhci: Remove zynq_sdhci_of_init() Prepare for using DM. Signed-off-by: Michal Simek --- drivers/mmc/zynq_sdhci.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 2d6cb31e12..87a1f4086f 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -32,30 +32,3 @@ int zynq_sdhci_init(phys_addr_t regbase) add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 0); return 0; } - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int zynq_sdhci_of_init(const void *blob) -{ - int offset = 0; - u32 ret = 0; - phys_addr_t reg; - - debug("ZYNQ SDHCI: Initialization\n"); - - do { - offset = fdt_node_offset_by_compatible(blob, offset, - "arasan,sdhci-8.9a"); - if (offset != -1) { - reg = fdtdec_get_addr(blob, offset, "reg"); - if (reg != FDT_ADDR_T_NONE) { - ret |= zynq_sdhci_init(reg); - } else { - debug("ZYNQ SDHCI: Can't get base address\n"); - return -1; - } - } - } while (offset != -1); - - return ret; -} -#endif -- cgit From d9ae52c8f081e30cfceafc0ddb7f29d4ecd36d00 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 30 Nov 2015 16:13:03 +0100 Subject: zynq: sdhci: Move driver to DM Move driver to DM Signed-off-by: Michal Simek Reviewed-by: Simon Glass --- drivers/mmc/zynq_sdhci.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 87a1f4086f..4fe3da93b2 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2013 Inc. + * (C) Copyright 2013 - 2015 Xilinx, Inc. * * Xilinx Zynq SD Host Controller Interface * @@ -7,28 +7,48 @@ */ #include +#include #include #include #include #include -#include -int zynq_sdhci_init(phys_addr_t regbase) +static int arasan_sdhci_probe(struct udevice *dev) { - struct sdhci_host *host = NULL; + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct sdhci_host *host = dev_get_priv(dev); - host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); - if (!host) { - printf("zynq_sdhci_init: sdhci_host malloc fail\n"); - return 1; - } - - host->name = "zynq_sdhci"; - host->ioaddr = (void *)regbase; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B; host->version = sdhci_readw(host, SDHCI_HOST_VERSION); add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 0); + + upriv->mmc = host->mmc; + return 0; } + +static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) +{ + struct sdhci_host *host = dev_get_priv(dev); + + host->name = (char *)dev->name; + host->ioaddr = (void *)dev_get_addr(dev); + + return 0; +} + +static const struct udevice_id arasan_sdhci_ids[] = { + { .compatible = "arasan,sdhci-8.9a" }, + { } +}; + +U_BOOT_DRIVER(arasan_sdhci_drv) = { + .name = "arasan_sdhci", + .id = UCLASS_MMC, + .of_match = arasan_sdhci_ids, + .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, + .probe = arasan_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct sdhci_host), +}; -- cgit From 6bf87dacd9d2d4962d32781c99ce891bde2b284f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 1 Dec 2015 14:29:34 +0100 Subject: serial: zynq: Fix incorrect reference to s5p driver Remove this c&p error from s5p driver. Signed-off-by: Michal Simek Reviewed-by: Bin Meng Reviewed-by: Simon Glass --- drivers/serial/Kconfig | 2 +- drivers/serial/serial_zynq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 82ad90d9e8..1fc287ee98 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -95,7 +95,7 @@ config DEBUG_UART_S5P config DEBUG_UART_ZYNQ bool "Xilinx Zynq" help - Select this to enable a debug UART using the serial_s5p driver. You + Select this to enable a debug UART using the serial_zynq driver. You will need to provide parameters to make this work. The driver will be available until the real driver-model serial is running. diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 88bebed236..6807f0f812 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -180,7 +180,7 @@ static const struct udevice_id zynq_serial_ids[] = { { } }; -U_BOOT_DRIVER(serial_s5p) = { +U_BOOT_DRIVER(serial_zynq) = { .name = "serial_zynq", .id = UCLASS_SERIAL, .of_match = zynq_serial_ids, -- cgit From c643f3ef9b68a2444c9672bc7b72735a5b7855b0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 2 Dec 2015 12:57:11 +0100 Subject: serial: zynq: Remove duplicated header debug_uart.h is included twice. Signed-off-by: Michal Simek Reviewed-by: Bin Meng Reviewed-by: Simon Glass --- drivers/serial/serial_zynq.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 6807f0f812..b2b98dea15 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -192,9 +192,6 @@ U_BOOT_DRIVER(serial_zynq) = { }; #ifdef CONFIG_DEBUG_UART_ZYNQ - -#include - void _debug_uart_init(void) { struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE; -- cgit From 8bebf03c73cd0830cb2cd234021004cde67c6412 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 1 Dec 2015 08:37:16 +0100 Subject: dm: core: Enable SPL_SIMPLE_BUS by default This option is needed for all SoCs which have nodes on bus. Without enabling this drivers are not found and probed. Issue was found on Zynq MMC probe. Enable this option by default. Signed-off-by: Michal Simek Reviewed-by: Stefan Roese Reviewed-by: Simon Glass --- drivers/core/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index ac681729c0..53acee05fa 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -134,7 +134,7 @@ config SIMPLE_BUS config SPL_SIMPLE_BUS bool "Support simple-bus driver in SPL" depends on SPL_DM && SPL_OF_CONTROL - default n + default y help Supports the 'simple-bus' driver, which is used on some systems in SPL. -- cgit