]> git.sur5r.net Git - u-boot/blobdiff - drivers/net/zynq_gem.c
Merge tag 'xilinx-for-v2017.05' of git://www.denx.de/git/u-boot-microblaze
[u-boot] / drivers / net / zynq_gem.c
index d2e5e7c7cd1428dbeb1d0590e49157e3790ed346..357f8c2917d20ae6cff8234b82dfdd1e363eec6a 100644 (file)
@@ -9,6 +9,7 @@
  * SPDX-License-Identifier:    GPL-2.0+
  */
 
+#include <clk.h>
 #include <common.h>
 #include <dm.h>
 #include <net.h>
@@ -174,42 +175,26 @@ struct zynq_gem_priv {
        u32 rxbd_current;
        u32 rx_first_buf;
        int phyaddr;
-       u32 emio;
        int init;
        struct zynq_gem_regs *iobase;
        phy_interface_t interface;
        struct phy_device *phydev;
        int phy_of_handle;
        struct mii_dev *bus;
+       struct clk clk;
 };
 
-static inline int mdio_wait(struct zynq_gem_regs *regs)
-{
-       u32 timeout = 20000;
-
-       /* Wait till MDIO interface is ready to accept a new transaction. */
-       while (--timeout) {
-               if (readl(&regs->nwsr) & ZYNQ_GEM_NWSR_MDIOIDLE_MASK)
-                       break;
-               WATCHDOG_RESET();
-       }
-
-       if (!timeout) {
-               printf("%s: Timeout\n", __func__);
-               return 1;
-       }
-
-       return 0;
-}
-
 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 = priv->iobase;
+       int err;
 
-       if (mdio_wait(regs))
-               return 1;
+       err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+                           true, 20000, true);
+       if (err)
+               return err;
 
        /* Construct mgtcr mask for the operation */
        mgtcr = ZYNQ_GEM_PHYMNTNC_OP_MASK | op |
@@ -219,8 +204,10 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum,
        /* Write mgtcr and wait for completion */
        writel(mgtcr, &regs->phymntnc);
 
-       if (mdio_wait(regs))
-               return 1;
+       err = wait_for_bit(__func__, &regs->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK,
+                           true, 20000, true);
+       if (err)
+               return err;
 
        if (op == ZYNQ_GEM_PHYMNTNC_OP_R_MASK)
                *data = readl(&regs->phymntnc);
@@ -350,12 +337,12 @@ static int zynq_phy_init(struct udevice *dev)
        if (!priv->phydev)
                return -ENODEV;
 
-       priv->phydev->supported = supported | ADVERTISED_Pause |
+       priv->phydev->supported &= supported | ADVERTISED_Pause |
                                  ADVERTISED_Asym_Pause;
        priv->phydev->advertising = priv->phydev->supported;
 
        if (priv->phy_of_handle > 0)
-               priv->phydev->dev->of_offset = priv->phy_of_handle;
+               dev_set_of_offset(priv->phydev->dev, priv->phy_of_handle);
 
        return phy_config(priv->phydev);
 }
@@ -467,10 +454,17 @@ static int zynq_gem_init(struct udevice *dev)
                break;
        }
 
-       /* Change the rclk and clk only not using EMIO interface */
-       if (!priv->emio)
-               zynq_slcr_gem_clk_setup((ulong)priv->iobase !=
-                                       ZYNQ_GEM_BASEADDR0, clk_rate);
+       ret = clk_set_rate(&priv->clk, clk_rate);
+       if (IS_ERR_VALUE(ret) && ret != (unsigned long)-ENOSYS) {
+               dev_err(dev, "failed to set tx clock rate\n");
+               return ret;
+       }
+
+       ret = clk_enable(&priv->clk);
+       if (ret && ret != -ENOSYS) {
+               dev_err(dev, "failed to enable tx clock\n");
+               return ret;
+       }
 
        setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |
                                        ZYNQ_GEM_NWCTRL_TXEN_MASK);
@@ -643,6 +637,12 @@ static int zynq_gem_probe(struct udevice *dev)
        priv->tx_bd = (struct emac_bd *)bd_space;
        priv->rx_bd = (struct emac_bd *)((ulong)bd_space + BD_SEPRN_SPACE);
 
+       ret = clk_get_by_name(dev, "tx_clk", &priv->clk);
+       if (ret < 0) {
+               dev_err(dev, "failed to get clock\n");
+               return -EINVAL;
+       }
+
        priv->bus = mdio_alloc();
        priv->bus->read = zynq_gem_miiphy_read;
        priv->bus->write = zynq_gem_miiphy_write;
@@ -680,21 +680,21 @@ 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 node = dev_of_offset(dev);
        const char *phy_mode;
 
        pdata->iobase = (phys_addr_t)dev_get_addr(dev);
        priv->iobase = (struct zynq_gem_regs *)pdata->iobase;
        /* Hardcode for now */
-       priv->emio = 0;
        priv->phyaddr = -1;
 
-       priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob,
-                                       dev->of_offset, "phy-handle");
+       priv->phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob, node,
+                                                   "phy-handle");
        if (priv->phy_of_handle > 0)
                priv->phyaddr = fdtdec_get_int(gd->fdt_blob,
                                        priv->phy_of_handle, "reg", -1);
 
-       phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+       phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
        if (phy_mode)
                pdata->phy_interface = phy_get_interface_by_name(phy_mode);
        if (pdata->phy_interface == -1) {
@@ -703,8 +703,6 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev)
        }
        priv->interface = pdata->phy_interface;
 
-       priv->emio = fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "xlnx,emio");
-
        printf("ZYNQ GEM: %lx, phyaddr %x, interface %s\n", (ulong)priv->iobase,
               priv->phyaddr, phy_string_for_interface(priv->interface));