[8/8] net: ethernet: ixp4xx: Support device tree probing

Message ID 20190524162023.9115-9-linus.walleij@linaro.org
State New
Headers show
Series
  • Xscale IXP4xx ethernet refurbishing
Related show

Commit Message

Linus Walleij May 24, 2019, 4:20 p.m.
This adds device tree probing to the IXP4xx ethernet
driver.

We need to drop the memory region request as part of
this since the OF core will request the memory for the
device.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

---
 drivers/net/ethernet/xscale/ixp4xx_eth.c | 80 +++++++++++++++++++-----
 1 file changed, 66 insertions(+), 14 deletions(-)

-- 
2.20.1

Comments

Andrew Lunn May 24, 2019, 8:21 p.m. | #1
> +	/* FIXME: get from MDIO handle */

> +	ret = of_property_read_u32(np, "phy", &val);

> +	if (ret) {

> +		dev_err(dev, "no phy\n");

> +		return NULL;

> +	}

> +	plat->phy = val;


Hi Linus

You might want to work on the MDIO code first. It is O.K. to do
something like:

np = NULL;

if (dev->of_node)
	np = of_get_child_by_name(dev->of_node, "mdio");

of_mdiobus_register(np, mdio_bus)

If np is NULL, it will fall back to mdiobus_register().

Then here you can do the correct

priv->phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0);

and later call 

       phy = of_phy_connect(ndev, priv->phy_node, &ixp4xx_adjust_link,
                           PHY_INTERFACE_MODE_MII);

You just need to watch out for the -EPROBE_DEFFERED.

    Andrew

Patch

diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c
index 8b883563a3d3..65fdc82d45a4 100644
--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -167,7 +167,6 @@  struct eth_regs {
 };
 
 struct port {
-	struct resource *mem_res;
 	struct eth_regs __iomem *regs;
 	struct npe *npe;
 	struct net_device *netdev;
@@ -1367,19 +1366,72 @@  static const struct net_device_ops ixp4xx_netdev_ops = {
 	.ndo_validate_addr = eth_validate_addr,
 };
 
+#ifdef CONFIG_OF
+static struct eth_plat_info *ixp4xx_of_get_platdata(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct of_phandle_args queue_spec;
+	struct eth_plat_info *plat;
+	u32 val;
+	int ret;
+
+	plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
+	if (!plat)
+		return NULL;
+
+	/* FIXME: get from MDIO handle */
+	ret = of_property_read_u32(np, "phy", &val);
+	if (ret) {
+		dev_err(dev, "no phy\n");
+		return NULL;
+	}
+	plat->phy = val;
+
+	/* Get the rx queue as a resource from queue manager */
+	ret = of_parse_phandle_with_fixed_args(np, "queue-rx", 1, 0,
+					       &queue_spec);
+	if (ret) {
+		dev_err(dev, "no rx queue phandle\n");
+		return NULL;
+	}
+	plat->rxq = queue_spec.args[0];
+
+	/* Get the txready queue as resource from queue manager */
+	ret = of_parse_phandle_with_fixed_args(np, "queue-txready", 1, 0,
+					       &queue_spec);
+	if (ret) {
+		dev_err(dev, "no txready queue phandle\n");
+		return NULL;
+	}
+	plat->txreadyq = queue_spec.args[0];
+
+	return plat;
+}
+#else
+static struct eth_plat_info *ixp4xx_of_get_platdata(struct device *dev)
+{
+	return NULL;
+}
+#endif
+
 static int ixp4xx_eth_probe(struct platform_device *pdev)
 {
 	char phy_id[MII_BUS_ID_SIZE + 3];
 	struct phy_device *phydev = NULL;
 	struct device *dev = &pdev->dev;
 	struct eth_plat_info *plat;
-	resource_size_t regs_phys;
 	struct net_device *ndev;
 	struct resource *res;
 	struct port *port;
 	int err;
 
-	plat = dev_get_platdata(dev);
+	if (dev->of_node)
+		plat = ixp4xx_of_get_platdata(dev);
+	else
+		plat = dev_get_platdata(dev);
+
+	if (!plat)
+		return -ENODEV;
 
 	if (!(ndev = devm_alloc_etherdev(dev, sizeof(struct port))))
 		return -ENOMEM;
@@ -1392,7 +1444,6 @@  static int ixp4xx_eth_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
-	regs_phys = res->start;
 	port->regs = devm_ioremap_resource(dev, res);
 
 	switch (res->start) {
@@ -1450,12 +1501,6 @@  static int ixp4xx_eth_probe(struct platform_device *pdev)
 	if (!(port->npe = npe_request(NPE_ID(port->id))))
 		return -EIO;
 
-	port->mem_res = request_mem_region(regs_phys, REGS_SIZE, ndev->name);
-	if (!port->mem_res) {
-		err = -EBUSY;
-		goto err_npe_rel;
-	}
-
 	port->plat = plat;
 	npe_port_tab[NPE_ID(port->id)] = port;
 	memcpy(ndev->dev_addr, plat->hwaddr, ETH_ALEN);
@@ -1491,8 +1536,6 @@  static int ixp4xx_eth_probe(struct platform_device *pdev)
 	phy_disconnect(phydev);
 err_free_mem:
 	npe_port_tab[NPE_ID(port->id)] = NULL;
-	release_resource(port->mem_res);
-err_npe_rel:
 	npe_release(port->npe);
 	return err;
 }
@@ -1508,12 +1551,21 @@  static int ixp4xx_eth_remove(struct platform_device *pdev)
 	ixp4xx_mdio_remove();
 	npe_port_tab[NPE_ID(port->id)] = NULL;
 	npe_release(port->npe);
-	release_resource(port->mem_res);
 	return 0;
 }
 
+static const struct of_device_id ixp4xx_eth_of_match[] = {
+	{
+		.compatible = "intel,ixp4xx-ethernet",
+	},
+	{ },
+};
+
 static struct platform_driver ixp4xx_eth_driver = {
-	.driver.name	= DRV_NAME,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = of_match_ptr(ixp4xx_eth_of_match),
+	},
 	.probe		= ixp4xx_eth_probe,
 	.remove		= ixp4xx_eth_remove,
 };