From 83ad4305da1128111b2f063e41a740d1e19836c8 Mon Sep 17 00:00:00 2001 From: Jay at Control Module Industries Date: Tue, 1 Jul 2014 14:49:52 -0500 Subject: [PATCH 7/7] cpsw: search for phy I have encountered the same issue(s) on A6A boards. I couldn't find a patch, so I wrote this patch to update the device tree in the davinci_mdio driver in the 3.15.1 tree, it seems to correct it. I would welcome any input on a different approach. https://groups.google.com/d/msg/beagleboard/9mctrG26Mc8/SRlnumt0LoMJ Signed-off-by: Robert Nelson --- drivers/net/ethernet/ti/davinci_mdio.c | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 0cca9de..0197edd 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -39,6 +39,7 @@ #include #include #include +#include /* * This timeout definition is a worst-case ultra defensive measure against @@ -97,6 +98,10 @@ struct davinci_mdio_data { unsigned long access_time; /* jiffies */ }; +#if IS_ENABLED(CONFIG_OF) +static void davinci_mdio_update_dt_from_phymask(u32 phy_mask); +#endif + static void __davinci_mdio_reset(struct davinci_mdio_data *data) { u32 mdio_in, div, mdio_out_khz, access_time; @@ -150,6 +155,11 @@ static int davinci_mdio_reset(struct mii_bus *bus) /* restrict mdio bus to live phys only */ dev_info(data->dev, "detected phy mask %x\n", ~phy_mask); phy_mask = ~phy_mask; + + #if IS_ENABLED(CONFIG_OF) + davinci_mdio_update_dt_from_phymask(phy_mask); + #endif + } else { /* desperately scan all phys */ dev_warn(data->dev, "no live phy, scanning all\n"); @@ -312,6 +322,79 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data, } #endif +#if IS_ENABLED(CONFIG_OF) +static void davinci_mdio_update_dt_from_phymask(u32 phy_mask) +{ + int i, len; + u32 addr; + __be32 *old_phy_p, *phy_id_p; + struct property *phy_id_property = NULL; + struct device_node *node_p, *slave_p; + + addr = 0; + + for (i = 0; i < PHY_MAX_ADDR; i++) { + if ((phy_mask & (1 << i)) == 0) { + addr = (u32) i; + break; + } + } + + for_each_compatible_node(node_p, NULL, "ti,cpsw") { + for_each_node_by_name(slave_p, "slave") { + + old_phy_p = (__be32 *) of_get_property(slave_p, "phy_id", &len); + + if (len != (sizeof(__be32 *) * 2)) + goto err_out; + + if (old_phy_p) { + + phy_id_property = kzalloc(sizeof(*phy_id_property), GFP_KERNEL); + + if (! phy_id_property) + goto err_out; + + phy_id_property->length = len; + phy_id_property->name = kstrdup("phy_id", GFP_KERNEL); + phy_id_property->value = kzalloc(len, GFP_KERNEL); + + if (! phy_id_property->name) + goto err_out; + + if (! phy_id_property->value) + goto err_out; + + memcpy(phy_id_property->value, old_phy_p, len); + + phy_id_p = (__be32 *) phy_id_property->value + 1; + + *phy_id_p = cpu_to_be32(addr); + + of_update_property(slave_p, phy_id_property); + + ++addr; + } + } + } + + return; + +err_out: + + if (phy_id_property) { + if (phy_id_property->name) + kfree(phy_id_property->name); + + if (phy_id_property->value) + kfree(phy_id_property->value); + + if (phy_id_property) + kfree(phy_id_property); + } +} +#endif + static int davinci_mdio_probe(struct platform_device *pdev) { struct mdio_platform_data *pdata = dev_get_platdata(&pdev->dev); -- 2.0.0