mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-11-03 22:44:27 -05:00 
			
		
		
		
	Ran update_kernel.sh in a fresh clone without any existing toolchains.
Manually rebased:
  pending-5.4/611-netfilter_match_bypass_default_table.patch
The upstream change affecting this patch is the revert of an earlier
kernel commit. Therefore, we just revert our corresponding changes
in [1].
Build system: x86_64
Build-tested: ipq806x/R7800
[1] 9b1b89229f ("kernel: bump 5.4 to 5.4.86")
Signed-off-by: John Audia <graysky@archlinux.us>
[adjust manually rebased patch, add explanation]
Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
		
	
			
		
			
				
	
	
		
			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
 | 
						|
@@ -369,6 +369,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);
 | 
						|
@@ -734,6 +772,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;
 | 
						|
@@ -996,6 +1036,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[] = {
 | 
						|
@@ -1020,6 +1061,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 */
 | 
						|
@@ -1130,6 +1172,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;
 | 
						|
 
 | 
						|
 	/* Auto-detection using standard registers will not work, so
 | 
						|
 	 * provide an indication of what kind of device we are for
 | 
						|
@@ -1184,6 +1227,8 @@ static int bcm_sf2_sw_probe(struct platf
 | 
						|
 		return ret;
 | 
						|
 	}
 | 
						|
 
 | 
						|
+	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
 | 
						|
@@ -70,6 +70,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 */
 |