enetc: Make MDIO accessors more generic and export to include/linux/fsl
[linux-block.git] / drivers / net / ethernet / freescale / enetc / enetc_mdio.c
index 149883c8f0b8c8347864ebac8eec78040d10802f..18c68e048d43a4cf79ffc5ba89af091a71127fd4 100644 (file)
@@ -1,24 +1,35 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /* Copyright 2019 NXP */
 
+#include <linux/fsl/enetc_mdio.h>
 #include <linux/mdio.h>
 #include <linux/of_mdio.h>
 #include <linux/iopoll.h>
 #include <linux/of.h>
 
-#include "enetc_mdio.h"
+#include "enetc_pf.h"
 
-#define        ENETC_MDIO_REG_OFFSET   0x1c00
 #define        ENETC_MDIO_CFG  0x0     /* MDIO configuration and status */
 #define        ENETC_MDIO_CTL  0x4     /* MDIO control */
 #define        ENETC_MDIO_DATA 0x8     /* MDIO data */
 #define        ENETC_MDIO_ADDR 0xc     /* MDIO address */
 
-#define enetc_mdio_rd(hw, off) \
-       enetc_port_rd(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET)
-#define enetc_mdio_wr(hw, off, val) \
-       enetc_port_wr(hw, ENETC_##off + ENETC_MDIO_REG_OFFSET, val)
-#define enetc_mdio_rd_reg(off) enetc_mdio_rd(hw, off)
+static inline u32 _enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
+{
+       return enetc_port_rd(mdio_priv->hw, mdio_priv->mdio_base + off);
+}
+
+static inline void _enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
+                                 u32 val)
+{
+       enetc_port_wr(mdio_priv->hw, mdio_priv->mdio_base + off, val);
+}
+
+#define enetc_mdio_rd(mdio_priv, off) \
+       _enetc_mdio_rd(mdio_priv, ENETC_##off)
+#define enetc_mdio_wr(mdio_priv, off, val) \
+       _enetc_mdio_wr(mdio_priv, ENETC_##off, val)
+#define enetc_mdio_rd_reg(off) enetc_mdio_rd(mdio_priv, off)
 
 #define ENETC_MDC_DIV          258
 
@@ -35,7 +46,7 @@
 #define MDIO_DATA(x)           ((x) & 0xffff)
 
 #define TIMEOUT        1000
-static int enetc_mdio_wait_complete(struct enetc_hw *hw)
+static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
 {
        u32 val;
 
@@ -46,7 +57,6 @@ static int enetc_mdio_wait_complete(struct enetc_hw *hw)
 int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
 {
        struct enetc_mdio_priv *mdio_priv = bus->priv;
-       struct enetc_hw *hw = mdio_priv->hw;
        u32 mdio_ctl, mdio_cfg;
        u16 dev_addr;
        int ret;
@@ -61,39 +71,39 @@ int enetc_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
                mdio_cfg &= ~MDIO_CFG_ENC45;
        }
 
-       enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
+       enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg);
 
-       ret = enetc_mdio_wait_complete(hw);
+       ret = enetc_mdio_wait_complete(mdio_priv);
        if (ret)
                return ret;
 
        /* set port and dev addr */
        mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
-       enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
+       enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl);
 
        /* set the register address */
        if (regnum & MII_ADDR_C45) {
-               enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
+               enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff);
 
-               ret = enetc_mdio_wait_complete(hw);
+               ret = enetc_mdio_wait_complete(mdio_priv);
                if (ret)
                        return ret;
        }
 
        /* write the value */
-       enetc_mdio_wr(hw, MDIO_DATA, MDIO_DATA(value));
+       enetc_mdio_wr(mdio_priv, MDIO_DATA, MDIO_DATA(value));
 
-       ret = enetc_mdio_wait_complete(hw);
+       ret = enetc_mdio_wait_complete(mdio_priv);
        if (ret)
                return ret;
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(enetc_mdio_write);
 
 int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
 {
        struct enetc_mdio_priv *mdio_priv = bus->priv;
-       struct enetc_hw *hw = mdio_priv->hw;
        u32 mdio_ctl, mdio_cfg;
        u16 dev_addr, value;
        int ret;
@@ -107,86 +117,56 @@ int enetc_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
                mdio_cfg &= ~MDIO_CFG_ENC45;
        }
 
-       enetc_mdio_wr(hw, MDIO_CFG, mdio_cfg);
+       enetc_mdio_wr(mdio_priv, MDIO_CFG, mdio_cfg);
 
-       ret = enetc_mdio_wait_complete(hw);
+       ret = enetc_mdio_wait_complete(mdio_priv);
        if (ret)
                return ret;
 
        /* set port and device addr */
        mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
-       enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl);
+       enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl);
 
        /* set the register address */
        if (regnum & MII_ADDR_C45) {
-               enetc_mdio_wr(hw, MDIO_ADDR, regnum & 0xffff);
+               enetc_mdio_wr(mdio_priv, MDIO_ADDR, regnum & 0xffff);
 
-               ret = enetc_mdio_wait_complete(hw);
+               ret = enetc_mdio_wait_complete(mdio_priv);
                if (ret)
                        return ret;
        }
 
        /* initiate the read */
-       enetc_mdio_wr(hw, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
+       enetc_mdio_wr(mdio_priv, MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
 
-       ret = enetc_mdio_wait_complete(hw);
+       ret = enetc_mdio_wait_complete(mdio_priv);
        if (ret)
                return ret;
 
        /* return all Fs if nothing was there */
-       if (enetc_mdio_rd(hw, MDIO_CFG) & MDIO_CFG_RD_ER) {
+       if (enetc_mdio_rd(mdio_priv, MDIO_CFG) & MDIO_CFG_RD_ER) {
                dev_dbg(&bus->dev,
                        "Error while reading PHY%d reg at %d.%hhu\n",
                        phy_id, dev_addr, regnum);
                return 0xffff;
        }
 
-       value = enetc_mdio_rd(hw, MDIO_DATA) & 0xffff;
+       value = enetc_mdio_rd(mdio_priv, MDIO_DATA) & 0xffff;
 
        return value;
 }
+EXPORT_SYMBOL_GPL(enetc_mdio_read);
 
-int enetc_mdio_probe(struct enetc_pf *pf)
+struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
 {
-       struct device *dev = &pf->si->pdev->dev;
-       struct enetc_mdio_priv *mdio_priv;
-       struct device_node *np;
-       struct mii_bus *bus;
-       int err;
-
-       bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
-       if (!bus)
-               return -ENOMEM;
-
-       bus->name = "Freescale ENETC MDIO Bus";
-       bus->read = enetc_mdio_read;
-       bus->write = enetc_mdio_write;
-       bus->parent = dev;
-       mdio_priv = bus->priv;
-       mdio_priv->hw = &pf->si->hw;
-       snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
-
-       np = of_get_child_by_name(dev->of_node, "mdio");
-       if (!np) {
-               dev_err(dev, "MDIO node missing\n");
-               return -EINVAL;
-       }
-
-       err = of_mdiobus_register(bus, np);
-       if (err) {
-               of_node_put(np);
-               dev_err(dev, "cannot register MDIO bus\n");
-               return err;
-       }
+       struct enetc_hw *hw;
 
-       of_node_put(np);
-       pf->mdio = bus;
+       hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
+       if (!hw)
+               return ERR_PTR(-ENOMEM);
 
-       return 0;
-}
+       hw->port = port_regs;
 
-void enetc_mdio_remove(struct enetc_pf *pf)
-{
-       if (pf->mdio)
-               mdiobus_unregister(pf->mdio);
+       return hw;
 }
+EXPORT_SYMBOL_GPL(enetc_hw_alloc);