From e7415d1a43054155c694aa16c55bd4a046285c21 Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Tue, 2 May 2023 14:57:04 +0300 Subject: [PATCH] fixup! net: cirrus: add DT support for Cirrus EP93xx --- drivers/net/ethernet/cirrus/ep93xx_eth.c | 162 +++++++++++++++-------- 1 file changed, 106 insertions(+), 56 deletions(-) diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c index b156cc75daad6..ec3d15c9a3c3f 100644 --- a/drivers/net/ethernet/cirrus/ep93xx_eth.c +++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c @@ -11,17 +11,19 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include +#include #include #include #include +#include #include @@ -172,7 +174,11 @@ struct ep93xx_priv struct net_device *dev; struct napi_struct napi; - struct mii_if_info mii; + struct phy_device *phy_dev; + struct device_node *phy_node; + + struct mii_bus *mii_bus; + u8 mdc_divisor; }; @@ -183,9 +189,9 @@ struct ep93xx_priv #define wrw(ep, off, val) __raw_writew((val), (ep)->base_addr + (off)) #define wrl(ep, off, val) __raw_writel((val), (ep)->base_addr + (off)) -static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg) +static int ep93xx_mdio_read(struct mii_bus *bus, int phy_id, int reg) { - struct ep93xx_priv *ep = netdev_priv(dev); + struct ep93xx_priv *ep = bus->priv; int data; int i; @@ -207,9 +213,9 @@ static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg) return data; } -static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int data) +static int ep93xx_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data) { - struct ep93xx_priv *ep = netdev_priv(dev); + struct ep93xx_priv *ep = bus->priv; int i; wrl(ep, REG_MIIDATA, data); @@ -221,8 +227,12 @@ static void ep93xx_mdio_write(struct net_device *dev, int phy_id, int reg, int d msleep(1); } - if (i == 10) + if (i == 10) { pr_info("mdio write timed out\n"); + return -ETIMEDOUT; + } + + return 0; } static int ep93xx_rx(struct net_device *dev, int budget) @@ -551,7 +561,7 @@ static int ep93xx_start_hw(struct net_device *dev) wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9)); /* Does the PHY support preamble suppress? */ - if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0) + if ((phy_read(ep->phy_dev, MII_BMSR) & 0x0040) != 0) wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8)); /* Receive descriptor ring. */ @@ -683,10 +693,17 @@ static int ep93xx_close(struct net_device *dev) static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct ep93xx_priv *ep = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return generic_mii_ioctl(&ep->mii, data, cmd, NULL); + if (!dev->phydev || !netif_running(dev)) + return -EINVAL; + + switch (cmd) { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return phy_mii_ioctl(dev->phydev, ifr, cmd); + default: + return -EOPNOTSUPP; + } } static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) @@ -694,41 +711,11 @@ static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); } -static int ep93xx_get_link_ksettings(struct net_device *dev, - struct ethtool_link_ksettings *cmd) -{ - struct ep93xx_priv *ep = netdev_priv(dev); - - mii_ethtool_get_link_ksettings(&ep->mii, cmd); - - return 0; -} - -static int ep93xx_set_link_ksettings(struct net_device *dev, - const struct ethtool_link_ksettings *cmd) -{ - struct ep93xx_priv *ep = netdev_priv(dev); - return mii_ethtool_set_link_ksettings(&ep->mii, cmd); -} - -static int ep93xx_nway_reset(struct net_device *dev) -{ - struct ep93xx_priv *ep = netdev_priv(dev); - return mii_nway_restart(&ep->mii); -} - -static u32 ep93xx_get_link(struct net_device *dev) -{ - struct ep93xx_priv *ep = netdev_priv(dev); - return mii_link_ok(&ep->mii); -} - static const struct ethtool_ops ep93xx_ethtool_ops = { .get_drvinfo = ep93xx_get_drvinfo, - .nway_reset = ep93xx_nway_reset, - .get_link = ep93xx_get_link, - .get_link_ksettings = ep93xx_get_link_ksettings, - .set_link_ksettings = ep93xx_set_link_ksettings, + .get_link = ethtool_op_get_link, + .get_link_ksettings = phy_ethtool_get_link_ksettings, + .set_link_ksettings = phy_ethtool_set_link_ksettings, }; static const struct net_device_ops ep93xx_netdev_ops = { @@ -758,6 +745,76 @@ static struct net_device *ep93xx_dev_alloc(struct ep93xx_eth_data *data) return dev; } +static int ep93xx_mdio_setup(struct ep93xx_priv *ep, struct device *dev) +{ + struct mii_bus *bus; + struct resource res; + struct device_node *np = of_get_parent(ep->phy_node); + struct device_node *npp; + int rc, ret; + + /* Don't register the MDIO bus if the phy_node or its parent node + * can't be found. + */ + if (!np) { + dev_err(dev, "Failed to register mdio bus.\n"); + return -ENODEV; + } + + npp = of_get_parent(np); + ret = of_address_to_resource(npp, 0, &res); + of_node_put(npp); + if (ret) { + dev_err(dev, "%s resource error!\n", + dev->of_node->full_name); + of_node_put(np); + return ret; + } + + if (ep->dev->mem_start != res.start) { + struct phy_device *phydev; + + phydev = of_phy_find_device(ep->phy_node); + if (!phydev) + dev_info(dev, + "MDIO of the phy is not registered yet\n"); + else + put_device(&phydev->mdio.dev); + of_node_put(np); + return 0; + } + + bus = mdiobus_alloc(); + if (!bus) { + dev_err(dev, "Failed to allocate mdiobus\n"); + of_node_put(np); + return -ENOMEM; + } + + snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", + (unsigned long long)res.start); + bus->priv = ep; + bus->name = "Cirrus ep93xx MDIO"; + bus->read = ep93xx_mdio_read; + bus->write = ep93xx_mdio_write; + bus->parent = dev; + + rc = of_mdiobus_register(bus, np); + of_node_put(np); + if (rc) { + dev_err(dev, "Failed to register mdio bus.\n"); + goto err_register; + } + + ep->mii_bus = bus; + + return 0; + +err_register: + mdiobus_free(bus); + return rc; + +} static int ep93xx_eth_remove(struct platform_device *pdev) { @@ -823,10 +880,8 @@ static int ep93xx_eth_probe(struct platform_device *pdev) if (!data) return -ENOMEM; - if (of_property_read_bool(np, "copy_addr")) { - memcpy_fromio(data->dev_addr, base_addr + 0x50, 6); - dev_info(&pdev->dev, "MAC=%pM\n", data->dev_addr); - } + memcpy_fromio(data->dev_addr, base_addr + 0x50, 6); + dev_info(&pdev->dev, "MAC=%pM\n", data->dev_addr); if (of_property_read_u32(np, "phy_id", &phy_id)) { dev_err(&pdev->dev, "Failed to parse \"phy_id\"\n"); @@ -862,13 +917,8 @@ static int ep93xx_eth_probe(struct platform_device *pdev) ep->base_addr = base_addr; ep->irq = irq; - - ep->mii.phy_id = data->phy_id; - ep->mii.phy_id_mask = 0x1f; - ep->mii.reg_num_mask = 0x1f; - ep->mii.dev = dev; - ep->mii.mdio_read = ep93xx_mdio_read; - ep->mii.mdio_write = ep93xx_mdio_write; + ep->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); + ep93xx_mdio_setup(ep, &pdev->dev); ep->mdc_divisor = 40; /* Max HCLK 100 MHz, min MDIO clk 2.5 MHz. */ if (is_zero_ether_addr(dev->dev_addr)) -- 2.30.2