#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)
#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
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;
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;
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");
{
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));
/* 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));
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();
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);
}
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);
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);
}
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;
}
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;
}
.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,
};