This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.

137 lines
3.5 KiB
Diff
Raw Normal View History

From 83ad4305da1128111b2f063e41a740d1e19836c8 Mon Sep 17 00:00:00 2001
From: Jay at Control Module Industries <cmidroid@gmail.com>
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 <robertcnelson@gmail.com>
---
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 <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/phy.h>
/*
* 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