+
+static int designware_eth_remove(struct udevice *dev)
+{
+ struct dw_eth_dev *priv = dev_get_priv(dev);
+
+ free(priv->phydev);
+ mdio_unregister(priv->bus);
+ mdio_free(priv->bus);
+
+ return 0;
+}
+
+static const struct eth_ops designware_eth_ops = {
+ .start = designware_eth_start,
+ .send = designware_eth_send,
+ .recv = designware_eth_recv,
+ .free_pkt = designware_eth_free_pkt,
+ .stop = designware_eth_stop,
+ .write_hwaddr = designware_eth_write_hwaddr,
+};
+
+static int designware_eth_ofdata_to_platdata(struct udevice *dev)
+{
+ struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev);
+#ifdef CONFIG_DM_GPIO
+ struct dw_eth_dev *priv = dev_get_priv(dev);
+#endif
+ struct eth_pdata *pdata = &dw_pdata->eth_pdata;
+ const char *phy_mode;
+ const fdt32_t *cell;
+#ifdef CONFIG_DM_GPIO
+ int reset_flags = GPIOD_IS_OUT;
+#endif
+ int ret = 0;
+
+ pdata->iobase = dev_get_addr(dev);
+ pdata->phy_interface = -1;
+ 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;
+ }
+
+ pdata->max_speed = 0;
+ cell = fdt_getprop(gd->fdt_blob, dev->of_offset, "max-speed", NULL);
+ if (cell)
+ pdata->max_speed = fdt32_to_cpu(*cell);
+
+#ifdef CONFIG_DM_GPIO
+ if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
+ "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,
+ "snps,reset-delays-us", dw_pdata->reset_delays, 3);
+ } else if (ret == -ENOENT) {
+ ret = 0;
+ }
+#endif
+
+ return ret;
+}
+
+static const struct udevice_id designware_eth_ids[] = {
+ { .compatible = "allwinner,sun7i-a20-gmac" },
+ { .compatible = "altr,socfpga-stmmac" },
+ { .compatible = "amlogic,meson6-dwmac" },
+ { }
+};
+
+U_BOOT_DRIVER(eth_designware) = {
+ .name = "eth_designware",
+ .id = UCLASS_ETH,
+ .of_match = designware_eth_ids,
+ .ofdata_to_platdata = designware_eth_ofdata_to_platdata,
+ .bind = designware_eth_bind,
+ .probe = designware_eth_probe,
+ .remove = designware_eth_remove,
+ .ops = &designware_eth_ops,
+ .priv_auto_alloc_size = sizeof(struct dw_eth_dev),
+ .platdata_auto_alloc_size = sizeof(struct dw_eth_pdata),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+
+static struct pci_device_id supported[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_EMAC) },
+ { }
+};
+
+U_BOOT_PCI_DEVICE(eth_designware, supported);
+#endif