All patches automatically rebased. Build system: x86_64 Build-tested: ipq806x/R7800 Signed-off-by: John Audia <therealgraysky@proton.me>
		
			
				
	
	
		
			153 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From a9349f08ec6c1251d41ef167d27a15cc39bc5b97 Mon Sep 17 00:00:00 2001
 | 
						|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
 | 
						|
Date: Fri, 12 Mar 2021 11:41:08 +0100
 | 
						|
Subject: [PATCH] net: dsa: bcm_sf2: setup BCM4908 internal crossbar
 | 
						|
MIME-Version: 1.0
 | 
						|
Content-Type: text/plain; charset=UTF-8
 | 
						|
Content-Transfer-Encoding: 8bit
 | 
						|
 | 
						|
On some SoCs (e.g. BCM4908, BCM631[345]8) SF2 has an integrated
 | 
						|
crossbar. It allows connecting its selected external ports to internal
 | 
						|
ports. It's used by vendors to handle custom Ethernet setups.
 | 
						|
 | 
						|
BCM4908 has following 3x2 crossbar. On Asus GT-AC5300 rgmii is used for
 | 
						|
connecting external BCM53134S switch. GPHY4 is usually used for WAN
 | 
						|
port. More fancy devices use SerDes for 2.5 Gbps Ethernet.
 | 
						|
 | 
						|
              ┌──────────┐
 | 
						|
SerDes ─── 0 ─┤          │
 | 
						|
              │   3x2    ├─ 0 ─── switch port 7
 | 
						|
 GPHY4 ─── 1 ─┤          │
 | 
						|
              │ crossbar ├─ 1 ─── runner (accelerator)
 | 
						|
 rgmii ─── 2 ─┤          │
 | 
						|
              └──────────┘
 | 
						|
 | 
						|
Use setup data based on DT info to configure BCM4908's switch port 7.
 | 
						|
Right now only GPHY and rgmii variants are supported. Handling SerDes
 | 
						|
can be implemented later.
 | 
						|
 | 
						|
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
 | 
						|
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
 | 
						|
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
						|
---
 | 
						|
 drivers/net/dsa/bcm_sf2.c      | 45 ++++++++++++++++++++++++++++++++++
 | 
						|
 drivers/net/dsa/bcm_sf2.h      |  1 +
 | 
						|
 drivers/net/dsa/bcm_sf2_regs.h |  7 ++++++
 | 
						|
 3 files changed, 53 insertions(+)
 | 
						|
 | 
						|
--- a/drivers/net/dsa/bcm_sf2.c
 | 
						|
+++ b/drivers/net/dsa/bcm_sf2.c
 | 
						|
@@ -435,6 +435,44 @@ static int bcm_sf2_sw_rst(struct bcm_sf2
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
+static void bcm_sf2_crossbar_setup(struct bcm_sf2_priv *priv)
 | 
						|
+{
 | 
						|
+	struct device *dev = priv->dev->ds->dev;
 | 
						|
+	int shift;
 | 
						|
+	u32 mask;
 | 
						|
+	u32 reg;
 | 
						|
+	int i;
 | 
						|
+
 | 
						|
+	mask = BIT(priv->num_crossbar_int_ports) - 1;
 | 
						|
+
 | 
						|
+	reg = reg_readl(priv, REG_CROSSBAR);
 | 
						|
+	switch (priv->type) {
 | 
						|
+	case BCM4908_DEVICE_ID:
 | 
						|
+		shift = CROSSBAR_BCM4908_INT_P7 * priv->num_crossbar_int_ports;
 | 
						|
+		reg &= ~(mask << shift);
 | 
						|
+		if (0) /* FIXME */
 | 
						|
+			reg |= CROSSBAR_BCM4908_EXT_SERDES << shift;
 | 
						|
+		else if (priv->int_phy_mask & BIT(7))
 | 
						|
+			reg |= CROSSBAR_BCM4908_EXT_GPHY4 << shift;
 | 
						|
+		else if (phy_interface_mode_is_rgmii(priv->port_sts[7].mode))
 | 
						|
+			reg |= CROSSBAR_BCM4908_EXT_RGMII << shift;
 | 
						|
+		else if (WARN(1, "Invalid port mode\n"))
 | 
						|
+			return;
 | 
						|
+		break;
 | 
						|
+	default:
 | 
						|
+		return;
 | 
						|
+	}
 | 
						|
+	reg_writel(priv, reg, REG_CROSSBAR);
 | 
						|
+
 | 
						|
+	reg = reg_readl(priv, REG_CROSSBAR);
 | 
						|
+	for (i = 0; i < priv->num_crossbar_int_ports; i++) {
 | 
						|
+		shift = i * priv->num_crossbar_int_ports;
 | 
						|
+
 | 
						|
+		dev_dbg(dev, "crossbar int port #%d - ext port #%d\n", i,
 | 
						|
+			(reg >> shift) & mask);
 | 
						|
+	}
 | 
						|
+}
 | 
						|
+
 | 
						|
 static void bcm_sf2_intr_disable(struct bcm_sf2_priv *priv)
 | 
						|
 {
 | 
						|
 	intrl2_0_mask_set(priv, 0xffffffff);
 | 
						|
@@ -880,6 +918,8 @@ static int bcm_sf2_sw_resume(struct dsa_
 | 
						|
 		return ret;
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	bcm_sf2_crossbar_setup(priv);
 | 
						|
+
 | 
						|
 	ret = bcm_sf2_cfp_resume(ds);
 | 
						|
 	if (ret)
 | 
						|
 		return ret;
 | 
						|
@@ -1151,6 +1191,7 @@ struct bcm_sf2_of_data {
 | 
						|
 	const u16 *reg_offsets;
 | 
						|
 	unsigned int core_reg_align;
 | 
						|
 	unsigned int num_cfp_rules;
 | 
						|
+	unsigned int num_crossbar_int_ports;
 | 
						|
 };
 | 
						|
 
 | 
						|
 static const u16 bcm_sf2_4908_reg_offsets[] = {
 | 
						|
@@ -1175,6 +1216,7 @@ static const struct bcm_sf2_of_data bcm_
 | 
						|
 	.core_reg_align	= 0,
 | 
						|
 	.reg_offsets	= bcm_sf2_4908_reg_offsets,
 | 
						|
 	.num_cfp_rules	= 0, /* FIXME */
 | 
						|
+	.num_crossbar_int_ports = 2,
 | 
						|
 };
 | 
						|
 
 | 
						|
 /* Register offsets for the SWITCH_REG_* block */
 | 
						|
@@ -1285,6 +1327,7 @@ static int bcm_sf2_sw_probe(struct platf
 | 
						|
 	priv->reg_offsets = data->reg_offsets;
 | 
						|
 	priv->core_reg_align = data->core_reg_align;
 | 
						|
 	priv->num_cfp_rules = data->num_cfp_rules;
 | 
						|
+	priv->num_crossbar_int_ports = data->num_crossbar_int_ports;
 | 
						|
 
 | 
						|
 	priv->rcdev = devm_reset_control_get_optional_exclusive(&pdev->dev,
 | 
						|
 								"switch");
 | 
						|
@@ -1358,6 +1401,8 @@ static int bcm_sf2_sw_probe(struct platf
 | 
						|
 		goto out_clk_mdiv;
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	bcm_sf2_crossbar_setup(priv);
 | 
						|
+
 | 
						|
 	bcm_sf2_gphy_enable_set(priv->dev->ds, true);
 | 
						|
 
 | 
						|
 	ret = bcm_sf2_mdio_register(ds);
 | 
						|
--- a/drivers/net/dsa/bcm_sf2.h
 | 
						|
+++ b/drivers/net/dsa/bcm_sf2.h
 | 
						|
@@ -74,6 +74,7 @@ struct bcm_sf2_priv {
 | 
						|
 	const u16			*reg_offsets;
 | 
						|
 	unsigned int			core_reg_align;
 | 
						|
 	unsigned int			num_cfp_rules;
 | 
						|
+	unsigned int			num_crossbar_int_ports;
 | 
						|
 
 | 
						|
 	/* spinlock protecting access to the indirect registers */
 | 
						|
 	spinlock_t			indir_lock;
 | 
						|
--- a/drivers/net/dsa/bcm_sf2_regs.h
 | 
						|
+++ b/drivers/net/dsa/bcm_sf2_regs.h
 | 
						|
@@ -48,6 +48,13 @@ enum bcm_sf2_reg_offs {
 | 
						|
 #define  PHY_PHYAD_SHIFT		8
 | 
						|
 #define  PHY_PHYAD_MASK			0x1F
 | 
						|
 
 | 
						|
+/* Relative to REG_CROSSBAR */
 | 
						|
+#define CROSSBAR_BCM4908_INT_P7		0
 | 
						|
+#define CROSSBAR_BCM4908_INT_RUNNER	1
 | 
						|
+#define CROSSBAR_BCM4908_EXT_SERDES	0
 | 
						|
+#define CROSSBAR_BCM4908_EXT_GPHY4	1
 | 
						|
+#define CROSSBAR_BCM4908_EXT_RGMII	2
 | 
						|
+
 | 
						|
 #define REG_RGMII_CNTRL_P(x)		(REG_RGMII_0_CNTRL + (x))
 | 
						|
 
 | 
						|
 /* Relative to REG_RGMII_CNTRL */
 |