137 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
		
		
			
		
	
	
			137 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 
								 | 
							
								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
							 | 
						||
| 
								 | 
							
								
							 |