]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - drivers/net/sun8i_emac.c
net: sun8i_emac: Fix build for non-H3/H5 SoCs
[people/ms/u-boot.git] / drivers / net / sun8i_emac.c
index 91570a29106f6d5ccd8ba80be7c976d097c8e8d9..3ccc6b0bb612de20e6973979c28bb7d981cbc2df 100644 (file)
@@ -21,6 +21,9 @@
 #include <malloc.h>
 #include <miiphy.h>
 #include <net.h>
+#ifdef CONFIG_DM_GPIO
+#include <asm-generic/gpio.h>
+#endif
 
 #define MDIO_CMD_MII_BUSY              BIT(0)
 #define MDIO_CMD_MII_WRITE             BIT(1)
@@ -62,7 +65,7 @@
 
 #define AHB_GATE_OFFSET_EPHY   0
 
-#if defined(CONFIG_MACH_SUN8I_H3)
+#if defined(CONFIG_MACH_SUNXI_H3_H5)
 #define SUN8I_GPD8_GMAC                2
 #else
 #define SUN8I_GPD8_GMAC                4
@@ -128,11 +131,22 @@ struct emac_eth_dev {
        phys_addr_t sysctl_reg;
        struct phy_device *phydev;
        struct mii_dev *bus;
+#ifdef CONFIG_DM_GPIO
+       struct gpio_desc reset_gpio;
+#endif
+};
+
+
+struct sun8i_eth_pdata {
+       struct eth_pdata eth_pdata;
+       u32 reset_delays[3];
 };
 
+
 static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
-       struct emac_eth_dev *priv = bus->priv;
+       struct udevice *dev = bus->priv;
+       struct emac_eth_dev *priv = dev_get_priv(dev);
        ulong start;
        u32 miiaddr = 0;
        int timeout = CONFIG_MDIO_TIMEOUT;
@@ -164,7 +178,8 @@ static int sun8i_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
                            u16 val)
 {
-       struct emac_eth_dev *priv = bus->priv;
+       struct udevice *dev = bus->priv;
+       struct emac_eth_dev *priv = dev_get_priv(dev);
        ulong start;
        u32 miiaddr = 0;
        int ret = -1, timeout = CONFIG_MDIO_TIMEOUT;
@@ -180,8 +195,8 @@ static int sun8i_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
        miiaddr |= MDIO_CMD_MII_WRITE;
        miiaddr |= MDIO_CMD_MII_BUSY;
 
-       writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
        writel(val, priv->mac_reg + EMAC_MII_DATA);
+       writel(miiaddr, priv->mac_reg + EMAC_MII_CMD);
 
        start = get_timer(0);
        while (get_timer(start) < timeout) {
@@ -442,7 +457,7 @@ static int parse_phy_pins(struct udevice *dev)
        const char *pin_name;
        int drive, pull, i;
 
-       offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+       offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
                                       "pinctrl-0");
        if (offset < 0) {
                printf("WARNING: emac: cannot find pinctrl-0 node\n");
@@ -457,7 +472,7 @@ static int parse_phy_pins(struct udevice *dev)
                int pin;
 
                pin_name = fdt_stringlist_get(gd->fdt_blob, offset,
-                                        "allwinner,pins", i, NULL);
+                                             "allwinner,pins", i, NULL);
                if (!pin_name)
                        break;
                if (pin_name[0] != 'P')
@@ -589,6 +604,8 @@ static void sun8i_emac_board_setup(struct emac_eth_dev *priv)
 {
        struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
+#ifdef CONFIG_MACH_SUNXI_H3_H5
+       /* Only H3/H5 have clock controls for internal EPHY */
        if (priv->use_internal_phy) {
                /* Set clock gating for ephy */
                setbits_le32(&ccm->bus_gate4, BIT(AHB_GATE_OFFSET_EPHY));
@@ -596,6 +613,7 @@ static void sun8i_emac_board_setup(struct emac_eth_dev *priv)
                /* Deassert EPHY */
                setbits_le32(&ccm->ahb_reset2_cfg, BIT(AHB_RESET_OFFSET_EPHY));
        }
+#endif
 
        /* Set clock gating for emac */
        setbits_le32(&ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_GMAC));
@@ -604,7 +622,41 @@ static void sun8i_emac_board_setup(struct emac_eth_dev *priv)
        setbits_le32(&ccm->ahb_reset0_cfg, BIT(AHB_RESET_OFFSET_GMAC));
 }
 
-static int sun8i_mdio_init(const char *name, struct  emac_eth_dev *priv)
+#if defined(CONFIG_DM_GPIO)
+static int sun8i_mdio_reset(struct mii_dev *bus)
+{
+       struct udevice *dev = bus->priv;
+       struct emac_eth_dev *priv = dev_get_priv(dev);
+       struct sun8i_eth_pdata *pdata = dev_get_platdata(dev);
+       int ret;
+
+       if (!dm_gpio_is_valid(&priv->reset_gpio))
+               return 0;
+
+       /* reset the phy */
+       ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+       if (ret)
+               return ret;
+
+       udelay(pdata->reset_delays[0]);
+
+       ret = dm_gpio_set_value(&priv->reset_gpio, 1);
+       if (ret)
+               return ret;
+
+       udelay(pdata->reset_delays[1]);
+
+       ret = dm_gpio_set_value(&priv->reset_gpio, 0);
+       if (ret)
+               return ret;
+
+       udelay(pdata->reset_delays[2]);
+
+       return 0;
+}
+#endif
+
+static int sun8i_mdio_init(const char *name, struct udevice *priv)
 {
        struct mii_dev *bus = mdio_alloc();
 
@@ -617,6 +669,9 @@ static int sun8i_mdio_init(const char *name, struct  emac_eth_dev *priv)
        bus->write = sun8i_mdio_write;
        snprintf(bus->name, sizeof(bus->name), name);
        bus->priv = (void *)priv;
+#if defined(CONFIG_DM_GPIO)
+       bus->reset = sun8i_mdio_reset;
+#endif
 
        return  mdio_register(bus);
 }
@@ -696,7 +751,7 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
        sun8i_emac_board_setup(priv);
        sun8i_emac_set_syscon(priv);
 
-       sun8i_mdio_init(dev->name, priv);
+       sun8i_mdio_init(dev->name, dev);
        priv->bus = miiphy_get_dev_by_name(dev->name);
 
        return sun8i_phy_init(priv, dev);
@@ -713,25 +768,31 @@ static const struct eth_ops sun8i_emac_eth_ops = {
 
 static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
 {
-       struct eth_pdata *pdata = dev_get_platdata(dev);
+       struct sun8i_eth_pdata *sun8i_pdata = dev_get_platdata(dev);
+       struct eth_pdata *pdata = &sun8i_pdata->eth_pdata;
        struct emac_eth_dev *priv = dev_get_priv(dev);
        const char *phy_mode;
+       int node = dev_of_offset(dev);
        int offset = 0;
+#ifdef CONFIG_DM_GPIO
+       int reset_flags = GPIOD_IS_OUT;
+       int ret = 0;
+#endif
 
-       pdata->iobase = dev_get_addr_name(dev, "emac");
-       priv->sysctl_reg = dev_get_addr_name(dev, "syscon");
+       pdata->iobase = devfdt_get_addr_name(dev, "emac");
+       priv->sysctl_reg = devfdt_get_addr_name(dev, "syscon");
 
        pdata->phy_interface = -1;
        priv->phyaddr = -1;
        priv->use_internal_phy = false;
 
-       offset = fdtdec_lookup_phandle(gd->fdt_blob, dev->of_offset,
+       offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
                                       "phy");
        if (offset > 0)
                priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "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);
@@ -751,7 +812,7 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
        }
 
        if (priv->variant == H3_EMAC) {
-               if (fdt_getprop(gd->fdt_blob, dev->of_offset,
+               if (fdt_getprop(gd->fdt_blob, node,
                                "allwinner,use-internal-phy", NULL))
                        priv->use_internal_phy = true;
        }
@@ -761,6 +822,23 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev)
        if (!priv->use_internal_phy)
                parse_phy_pins(dev);
 
+#ifdef CONFIG_DM_GPIO
+       if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
+                           "snps,reset-active-low"))
+               reset_flags |= GPIOD_ACTIVE_LOW;
+
+       ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
+                                  &priv->reset_gpio, reset_flags);
+
+       if (ret == 0) {
+               ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
+                                          "snps,reset-delays-us",
+                                          sun8i_pdata->reset_delays, 3);
+       } else if (ret == -ENOENT) {
+               ret = 0;
+       }
+#endif
+
        return 0;
 }
 
@@ -781,6 +859,6 @@ U_BOOT_DRIVER(eth_sun8i_emac) = {
        .probe  = sun8i_emac_eth_probe,
        .ops    = &sun8i_emac_eth_ops,
        .priv_auto_alloc_size = sizeof(struct emac_eth_dev),
-       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .platdata_auto_alloc_size = sizeof(struct sun8i_eth_pdata),
        .flags = DM_FLAG_ALLOC_PRIV_DMA,
 };