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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 858093f0d7e..1a5a366c944 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 1a5a366c944..7f801d5c4c0 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 7f801d5c4c0..65ea5deb23c 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 65ea5deb23c..8f3fe913006 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 8f3fe913006..86bb7590507 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 86bb7590507..d5540ec2155 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index d5540ec2155..9ce1221e8d0 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 9ce1221e8d0..a569c77aeb6 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index a569c77aeb6..4e93707c7ab 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 4e93707c7ab..9e8616e0530 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 9e8616e0530..0ee909c97fd 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 v1.2.3 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/net/zynq_gem.c') diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 0ee909c97fd..0a41281e901 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 v1.2.3