[source] b53: allow configuration through device tree

LEDE Commits lede-commits at lists.infradead.org
Sun Jun 11 03:01:47 PDT 2017


jogo pushed a commit to source.git, branch master:
https://git.lede-project.org/5df15c06ccd105a19431bc32bd1d158b3ff3325e

commit 5df15c06ccd105a19431bc32bd1d158b3ff3325e
Author: Jonas Gorski <jonas.gorski at gmail.com>
AuthorDate: Thu Feb 9 21:20:41 2017 +0100

    b53: allow configuration through device tree
    
    Add support for the same binding as upstream b53 to allow an
    easy switch.
    
    Signed-off-by: Jonas Gorski <jonas.gorski at gmail.com>
---
 .../generic/files/drivers/net/phy/b53/b53_common.c | 177 ++++++++++++++++++---
 .../generic/files/drivers/net/phy/b53/b53_priv.h   |   8 +
 .../generic/files/drivers/net/phy/b53/b53_spi.c    |  14 ++
 3 files changed, 180 insertions(+), 19 deletions(-)

diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
index b884010..482966a 100644
--- a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
+++ b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
@@ -24,6 +24,8 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/switch.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
 #include <linux/platform_data/b53.h>
 
 #include "b53_regs.h"
@@ -478,35 +480,88 @@ static void b53_switch_reset_gpio(struct b53_device *dev)
 	dev->current_page = 0xff;
 }
 
-static int b53_switch_reset(struct b53_device *dev)
+static int b53_configure_ports_of(struct b53_device *dev)
 {
-	u8 cpu_port = dev->sw_dev.cpu_port;
-	u8 mgmt;
+	struct device_node *dn, *pn;
+	u32 port_num;
 
-	b53_switch_reset_gpio(dev);
+	dn = of_get_child_by_name(dev_of_node(dev->dev), "ports");
 
-	if (is539x(dev)) {
-		b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x83);
-		b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x00);
-	}
+	for_each_available_child_of_node(dn, pn) {
+		struct device_node *fixed_link;
 
-	b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+		if (of_property_read_u32(pn, "reg", &port_num))
+			continue;
 
-	if (!(mgmt & SM_SW_FWD_EN)) {
-		mgmt &= ~SM_SW_FWD_MODE;
-		mgmt |= SM_SW_FWD_EN;
+		if (port_num > B53_CPU_PORT)
+			continue;
 
-		b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
-		b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+		fixed_link = of_get_child_by_name(pn, "fixed-link");
+		if (fixed_link) {
+			u32 spd;
+			u8 po = GMII_PO_LINK;
+			int mode = of_get_phy_mode(pn);
+
+			if (!of_property_read_u32(fixed_link, "speed", &spd)) {
+				switch (spd) {
+				case 10:
+					po |= GMII_PO_SPEED_10M;
+					break;
+				case 100:
+					po |= GMII_PO_SPEED_100M;
+					break;
+				case 2000:
+					if (is_imp_port(dev, port_num))
+						po |= PORT_OVERRIDE_SPEED_2000M;
+					else
+						po |= GMII_PO_SPEED_2000M;
+					/* fall through */
+				case 1000:
+					po |= GMII_PO_SPEED_1000M;
+					break;
+				}
+			}
 
-		if (!(mgmt & SM_SW_FWD_EN)) {
-			pr_err("Failed to enable switch!\n");
-			return -EINVAL;
+			if (of_property_read_bool(fixed_link, "full-duplex"))
+				po |= PORT_OVERRIDE_FULL_DUPLEX;
+			if (of_property_read_bool(fixed_link, "pause"))
+				po |= GMII_PO_RX_FLOW;
+			if (of_property_read_bool(fixed_link, "asym-pause"))
+				po |= GMII_PO_TX_FLOW;
+
+			if (is_imp_port(dev, port_num)) {
+				po |= PORT_OVERRIDE_EN;
+
+				if (is5325(dev) &&
+				    mode == PHY_INTERFACE_MODE_REVMII)
+					po |= PORT_OVERRIDE_RV_MII_25;
+
+				b53_write8(dev, B53_CTRL_PAGE,
+					   B53_PORT_OVERRIDE_CTRL, po);
+
+				if (is5325(dev) &&
+				    mode == PHY_INTERFACE_MODE_REVMII) {
+					b53_read8(dev, B53_CTRL_PAGE,
+						  B53_PORT_OVERRIDE_CTRL, &po);
+					if (!(po & PORT_OVERRIDE_RV_MII_25))
+					pr_err("Failed to enable reverse MII mode\n");
+					return -EINVAL;
+				}
+			} else {
+				po |= GMII_PO_EN;
+				b53_write8(dev, B53_CTRL_PAGE,
+					   B53_GMII_PORT_OVERRIDE_CTRL(port_num),
+					   po);
+			}
 		}
 	}
 
-	/* enable all ports */
-	b53_enable_ports(dev);
+	return 0;
+}
+
+static int b53_configure_ports(struct b53_device *dev)
+{
+	u8 cpu_port = dev->sw_dev.cpu_port;
 
 	/* configure MII port if necessary */
 	if (is5325(dev)) {
@@ -576,6 +631,47 @@ static int b53_switch_reset(struct b53_device *dev)
 		}
 	}
 
+	return 0;
+}
+
+static int b53_switch_reset(struct b53_device *dev)
+{
+	int ret = 0;
+	u8 mgmt;
+
+	b53_switch_reset_gpio(dev);
+
+	if (is539x(dev)) {
+		b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x83);
+		b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x00);
+	}
+
+	b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+
+	if (!(mgmt & SM_SW_FWD_EN)) {
+		mgmt &= ~SM_SW_FWD_MODE;
+		mgmt |= SM_SW_FWD_EN;
+
+		b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
+		b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+
+		if (!(mgmt & SM_SW_FWD_EN)) {
+			pr_err("Failed to enable switch!\n");
+			return -EINVAL;
+		}
+	}
+
+	/* enable all ports */
+	b53_enable_ports(dev);
+
+	if (dev->dev->of_node)
+		ret = b53_configure_ports_of(dev);
+	else
+		ret = b53_configure_ports(dev);
+
+	if (ret)
+		return ret;
+
 	b53_enable_mib(dev);
 
 	return b53_flush_arl(dev);
@@ -1320,6 +1416,43 @@ static const struct b53_chip_data b53_switch_chips[] = {
 	},
 };
 
+static int b53_switch_init_of(struct b53_device *dev)
+{
+	struct device_node *dn, *pn;
+	const char *alias;
+	u32 port_num;
+	u16 ports = 0;
+
+	dn = of_get_child_by_name(dev_of_node(dev->dev), "ports");
+	if (!dn)
+		return -EINVAL;
+
+	for_each_available_child_of_node(dn, pn) {
+		const char *label;
+		int len;
+
+		if (of_property_read_u32(pn, "reg", &port_num))
+			continue;
+
+		if (port_num > B53_CPU_PORT)
+			continue;
+
+		ports |= BIT(port_num);
+
+		label = of_get_property(pn, "label", &len);
+		if (label && !strcmp(label, "cpu"))
+			dev->sw_dev.cpu_port = port_num;
+	}
+
+	dev->enabled_ports = ports;
+
+	if (!of_property_read_string(dev_of_node(dev->dev), "lede,alias",
+						 &alias))
+		dev->sw_dev.alias = devm_kstrdup(dev->dev, alias, GFP_KERNEL);
+
+	return 0;
+}
+
 static int b53_switch_init(struct b53_device *dev)
 {
 	struct switch_dev *sw_dev = &dev->sw_dev;
@@ -1383,6 +1516,12 @@ static int b53_switch_init(struct b53_device *dev)
 			sw_dev->cpu_port = 5;
 	}
 
+	if (dev_of_node(dev->dev)) {
+		ret = b53_switch_init_of(dev);
+		if (ret)
+			return ret;
+	}
+
 	dev->enabled_ports |= BIT(sw_dev->cpu_port);
 	sw_dev->ports = fls(dev->enabled_ports);
 
diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h b/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h
index 53da97e..277c75d 100644
--- a/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h
+++ b/target/linux/generic/files/drivers/net/phy/b53/b53_priv.h
@@ -170,6 +170,14 @@ static inline int is_cpu_port(struct b53_device *dev, int port)
 	return dev->sw_dev.cpu_port == port;
 }
 
+static inline int is_imp_port(struct b53_device *dev, int port)
+{
+	if (is5325(dev) || is5365(dev))
+		return port == B53_CPU_PORT_25;
+	else
+		return port == B53_CPU_PORT;
+}
+
 static inline struct b53_device *sw_to_b53(struct switch_dev *sw)
 {
 	return container_of(sw, struct b53_device, sw_dev);
diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c b/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c
index 469a8dd..efc8f7e 100644
--- a/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c
+++ b/target/linux/generic/files/drivers/net/phy/b53/b53_spi.c
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/of.h>
 #include <linux/platform_data/b53.h>
 
 #include "b53_priv.h"
@@ -313,11 +314,24 @@ static int b53_spi_remove(struct spi_device *spi)
 	return 0;
 }
 
+static const struct of_device_id b53_of_match[] = {
+	{ .compatible = "brcm,bcm5325" },
+	{ .compatible = "brcm,bcm53115" },
+	{ .compatible = "brcm,bcm53125" },
+	{ .compatible = "brcm,bcm53128" },
+	{ .compatible = "brcm,bcm5365" },
+	{ .compatible = "brcm,bcm5395" },
+	{ .compatible = "brcm,bcm5397" },
+	{ .compatible = "brcm,bcm5398" },
+	{ /* sentinel */ },
+};
+
 static struct spi_driver b53_spi_driver = {
 	.driver = {
 		.name	= "b53-switch",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.of_match_table = b53_of_match,
 	},
 	.probe	= b53_spi_probe,
 	.remove	= b53_spi_remove,



More information about the lede-commits mailing list