[openwrt/openwrt] kernel: 5.10: backport qca8k feature additions

LEDE Commits lede-commits at lists.infradead.org
Sun Oct 24 08:35:28 PDT 2021


hauke pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/f97cafdd1d4de52f3254138524817980f27833cd

commit f97cafdd1d4de52f3254138524817980f27833cd
Author: Matthew Hagan <mnhagan88 at gmail.com>
AuthorDate: Thu Sep 9 19:40:21 2021 +0000

    kernel: 5.10: backport qca8k feature additions
    
    Backport Ansuel Smith's various qca8k feature additions:
    - mac-power-sel support
    - SGMII PLL explicit enable
    - tx/rx clock phase to falling edge
    - power-on-sel and LED open drain mode
    - cpu port 6
    - qca8328 support
    - sgmii internal delay
    - move port config to dedicated struct
    - convert to yaml schema
    
    Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
    Signed-off-by: Matthew Hagan <mnhagan88 at gmail.com>
---
 ...16-01-dsa-qca8k-add-mac-power-sel-support.patch |  80 +++
 ...-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch |  30 +
 ...-qca8k-add-support-for-sgmii-falling-edge.patch | 127 +++++
 ...-net-dsa-qca8k-Document-support-for-CPU-p.patch |  29 +
 ...-net-dsa-qca8k-add-support-for-cpu-port-6.patch | 153 +++++
 ...8k-rework-rgmii-delay-logic-and-scan-for-.patch | 295 ++++++++++
 ...-net-dsa-qca8k-Document-qca-sgmii-enable-.patch |  33 ++
 ...t-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch |  65 +++
 ...-net-dsa-qca8k-Document-qca-led-open-drai.patch |  37 ++
 ...-dsa-qca8k-add-support-for-pws-config-reg.patch |  92 +++
 ...-net-dsa-qca8k-document-support-for-qca83.patch |  32 ++
 ...-12-net-dsa-qca8k-add-support-for-QCA8328.patch |  78 +++
 ...a-qca8k-set-internal-delay-also-for-sgmii.patch | 159 ++++++
 ...ca8k-move-port-config-to-dedicated-struct.patch | 124 ++++
 ...-net-ipq8064-mdio-fix-warning-with-new-qc.patch |  26 +
 ...ings-net-dsa-qca8k-convert-to-YAML-schema.patch | 631 +++++++++++++++++++++
 16 files changed, 1991 insertions(+)

diff --git a/target/linux/generic/backport-5.10/797-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch b/target/linux/generic/backport-5.10/797-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch
new file mode 100644
index 0000000000..c8d424de38
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-01-dsa-qca8k-add-mac-power-sel-support.patch
@@ -0,0 +1,80 @@
+From d8b6f5bae6d3b648a67b6958cb98e4e97256d652 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:06 +0200
+Subject: dsa: qca8k: add mac_power_sel support
+
+Add missing mac power sel support needed for ipq8064/5 SoC that require
+1.8v for the internal regulator port instead of the default 1.5v.
+If other device needs this, consider adding a dedicated binding to
+support this.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 31 +++++++++++++++++++++++++++++++
+ drivers/net/dsa/qca8k.h |  5 +++++
+ 2 files changed, 36 insertions(+)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -951,6 +951,33 @@ qca8k_setup_of_rgmii_delay(struct qca8k_
+ }
+ 
+ static int
++qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv)
++{
++	u32 mask = 0;
++	int ret = 0;
++
++	/* SoC specific settings for ipq8064.
++	 * If more device require this consider adding
++	 * a dedicated binding.
++	 */
++	if (of_machine_is_compatible("qcom,ipq8064"))
++		mask |= QCA8K_MAC_PWR_RGMII0_1_8V;
++
++	/* SoC specific settings for ipq8065 */
++	if (of_machine_is_compatible("qcom,ipq8065"))
++		mask |= QCA8K_MAC_PWR_RGMII1_1_8V;
++
++	if (mask) {
++		ret = qca8k_rmw(priv, QCA8K_REG_MAC_PWR_SEL,
++				QCA8K_MAC_PWR_RGMII0_1_8V |
++				QCA8K_MAC_PWR_RGMII1_1_8V,
++				mask);
++	}
++
++	return ret;
++}
++
++static int
+ qca8k_setup(struct dsa_switch *ds)
+ {
+ 	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+@@ -979,6 +1006,10 @@ qca8k_setup(struct dsa_switch *ds)
+ 	if (ret)
+ 		return ret;
+ 
++	ret = qca8k_setup_mac_pwr_sel(priv);
++	if (ret)
++		return ret;
++
+ 	/* Enable CPU Port */
+ 	ret = qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
+ 			    QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -100,6 +100,11 @@
+ #define   QCA8K_SGMII_MODE_CTRL_PHY			(1 << 22)
+ #define   QCA8K_SGMII_MODE_CTRL_MAC			(2 << 22)
+ 
++/* MAC_PWR_SEL registers */
++#define QCA8K_REG_MAC_PWR_SEL				0x0e4
++#define   QCA8K_MAC_PWR_RGMII1_1_8V			BIT(18)
++#define   QCA8K_MAC_PWR_RGMII0_1_8V			BIT(19)
++
+ /* EEE control registers */
+ #define QCA8K_REG_EEE_CTRL				0x100
+ #define  QCA8K_REG_EEE_CTRL_LPI_EN(_i)			((_i + 1) * 2)
diff --git a/target/linux/generic/backport-5.10/797-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch b/target/linux/generic/backport-5.10/797-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch
new file mode 100644
index 0000000000..bd768ec27d
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-02-dt-bindings-net-dsa-qca8k-Add-SGMII-clock-phase-prop.patch
@@ -0,0 +1,30 @@
+From fdbf35df9c091db9c46e57e9938e3f7a4f603a7c Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:07 +0200
+Subject: dt-bindings: net: dsa: qca8k: Add SGMII clock phase properties
+
+Add names and descriptions of additional PORT0_PAD_CTRL properties.
+qca,sgmii-(rx|tx)clk-falling-edge are for setting the respective clock
+phase to failling edge.
+
+Co-developed-by: Matthew Hagan <mnhagan88 at gmail.com>
+Signed-off-by: Matthew Hagan <mnhagan88 at gmail.com>
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ Documentation/devicetree/bindings/net/dsa/qca8k.txt | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+@@ -37,6 +37,10 @@ A CPU port node has the following option
+                           managed entity. See
+                           Documentation/devicetree/bindings/net/fixed-link.txt
+                           for details.
++- qca,sgmii-rxclk-falling-edge: Set the receive clock phase to falling edge.
++                                Mostly used in qca8327 with CPU port 0 set to
++                                sgmii.
++- qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge.
+ 
+ For QCA8K the 'fixed-link' sub-node supports only the following properties:
+ 
diff --git a/target/linux/generic/backport-5.10/797-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch b/target/linux/generic/backport-5.10/797-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch
new file mode 100644
index 0000000000..e464452d82
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-03-net-dsa-qca8k-add-support-for-sgmii-falling-edge.patch
@@ -0,0 +1,127 @@
+From 6c43809bf1bee76c434e365a26546a92a5fbec14 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:08 +0200
+Subject: net: dsa: qca8k: add support for sgmii falling edge
+
+Add support for this in the qca8k driver. Also add support for SGMII
+rx/tx clock falling edge. This is only present for pad0, pad5 and
+pad6 have these bit reserved from Documentation. Add a comment that this
+is hardcoded to PAD0 as qca8327/28/34/37 have an unique sgmii line and
+setting falling in port0 applies to both configuration with sgmii used
+for port0 or port6.
+
+Co-developed-by: Matthew Hagan <mnhagan88 at gmail.com>
+Signed-off-by: Matthew Hagan <mnhagan88 at gmail.com>
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/qca8k.h |  4 ++++
+ 2 files changed, 67 insertions(+)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -978,6 +978,42 @@ qca8k_setup_mac_pwr_sel(struct qca8k_pri
+ }
+ 
+ static int
++qca8k_parse_port_config(struct qca8k_priv *priv)
++{
++	struct device_node *port_dn;
++	phy_interface_t mode;
++	struct dsa_port *dp;
++	int port, ret;
++
++	/* We have 2 CPU port. Check them */
++	for (port = 0; port < QCA8K_NUM_PORTS; port++) {
++		/* Skip every other port */
++		if (port != 0 && port != 6)
++			continue;
++
++		dp = dsa_to_port(priv->ds, port);
++		port_dn = dp->dn;
++
++		if (!of_device_is_available(port_dn))
++			continue;
++
++		ret = of_get_phy_mode(port_dn, &mode);
++		if (ret)
++			continue;
++
++		if (mode == PHY_INTERFACE_MODE_SGMII) {
++			if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge"))
++				priv->sgmii_tx_clk_falling_edge = true;
++
++			if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge"))
++				priv->sgmii_rx_clk_falling_edge = true;
++		}
++	}
++
++	return 0;
++}
++
++static int
+ qca8k_setup(struct dsa_switch *ds)
+ {
+ 	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+@@ -990,6 +1026,11 @@ qca8k_setup(struct dsa_switch *ds)
+ 		return -EINVAL;
+ 	}
+ 
++	/* Parse CPU port config to be later used in phy_link mac_config */
++	ret = qca8k_parse_port_config(priv);
++	if (ret)
++		return ret;
++
+ 	mutex_init(&priv->reg_mutex);
+ 
+ 	/* Start by setting up the register mapping */
+@@ -1274,6 +1315,28 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 		}
+ 
+ 		qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val);
++
++		/* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and
++		 * falling edge is set writing in the PORT0 PAD reg
++		 */
++		if (priv->switch_id == QCA8K_ID_QCA8327 ||
++		    priv->switch_id == QCA8K_ID_QCA8337)
++			reg = QCA8K_REG_PORT0_PAD_CTRL;
++
++		val = 0;
++
++		/* SGMII Clock phase configuration */
++		if (priv->sgmii_rx_clk_falling_edge)
++			val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE;
++
++		if (priv->sgmii_tx_clk_falling_edge)
++			val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE;
++
++		if (val)
++			ret = qca8k_rmw(priv, reg,
++					QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE |
++					QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE,
++					val);
+ 		break;
+ 	default:
+ 		dev_err(ds->dev, "xMII mode %s not supported for port %d\n",
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -35,6 +35,8 @@
+ #define   QCA8K_MASK_CTRL_DEVICE_ID_MASK		GENMASK(15, 8)
+ #define   QCA8K_MASK_CTRL_DEVICE_ID(x)			((x) >> 8)
+ #define QCA8K_REG_PORT0_PAD_CTRL			0x004
++#define   QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE	BIT(19)
++#define   QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE	BIT(18)
+ #define QCA8K_REG_PORT5_PAD_CTRL			0x008
+ #define QCA8K_REG_PORT6_PAD_CTRL			0x00c
+ #define   QCA8K_PORT_PAD_RGMII_EN			BIT(26)
+@@ -260,6 +262,8 @@ struct qca8k_priv {
+ 	u8 switch_revision;
+ 	u8 rgmii_tx_delay;
+ 	u8 rgmii_rx_delay;
++	bool sgmii_rx_clk_falling_edge;
++	bool sgmii_tx_clk_falling_edge;
+ 	bool legacy_phy_port_mapping;
+ 	struct regmap *regmap;
+ 	struct mii_bus *bus;
diff --git a/target/linux/generic/backport-5.10/797-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch b/target/linux/generic/backport-5.10/797-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch
new file mode 100644
index 0000000000..606ac0af3d
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-04-dt-bindings-net-dsa-qca8k-Document-support-for-CPU-p.patch
@@ -0,0 +1,29 @@
+From 731d613338ec6de482053ffa3f71be2325b0f8eb Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:09 +0200
+Subject: dt-bindings: net: dsa: qca8k: Document support for CPU port 6
+
+The switch now support CPU port to be set 6 instead of be hardcoded to
+0. Document support for it and describe logic selection.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ Documentation/devicetree/bindings/net/dsa/qca8k.txt | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+@@ -29,7 +29,11 @@ the mdio MASTER is used as communication
+ Don't use mixed external and internal mdio-bus configurations, as this is
+ not supported by the hardware.
+ 
+-The CPU port of this switch is always port 0.
++This switch support 2 CPU port. Normally and advised configuration is with
++CPU port set to port 0. It is also possible to set the CPU port to port 6
++if the device requires it. The driver will configure the switch to the defined
++port. With both CPU port declared the first CPU port is selected as primary
++and the secondary CPU ignored.
+ 
+ A CPU port node has the following optional node:
+ 
diff --git a/target/linux/generic/backport-5.10/797-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch b/target/linux/generic/backport-5.10/797-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch
new file mode 100644
index 0000000000..320db8fa9f
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-05-net-dsa-qca8k-add-support-for-cpu-port-6.patch
@@ -0,0 +1,153 @@
+From 3fcf734aa482487df83cf8f18608438fcf59127f Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:10 +0200
+Subject: net: dsa: qca8k: add support for cpu port 6
+
+Currently CPU port is always hardcoded to port 0. This switch have 2 CPU
+ports. The original intention of this driver seems to be use the
+mac06_exchange bit to swap MAC0 with MAC6 in the strange configuration
+where device have connected only the CPU port 6. To skip the
+introduction of a new binding, rework the driver to address the
+secondary CPU port as primary and drop any reference of hardcoded port.
+With configuration of mac06 exchange, just skip the definition of port0
+and define the CPU port as a secondary. The driver will autoconfigure
+the switch to use that as the primary CPU port.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 51 ++++++++++++++++++++++++++++++++++---------------
+ drivers/net/dsa/qca8k.h |  2 --
+ 2 files changed, 36 insertions(+), 17 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -977,6 +977,22 @@ qca8k_setup_mac_pwr_sel(struct qca8k_pri
+ 	return ret;
+ }
+ 
++static int qca8k_find_cpu_port(struct dsa_switch *ds)
++{
++	struct qca8k_priv *priv = ds->priv;
++
++	/* Find the connected cpu port. Valid port are 0 or 6 */
++	if (dsa_is_cpu_port(ds, 0))
++		return 0;
++
++	dev_dbg(priv->dev, "port 0 is not the CPU port. Checking port 6");
++
++	if (dsa_is_cpu_port(ds, 6))
++		return 6;
++
++	return -EINVAL;
++}
++
+ static int
+ qca8k_parse_port_config(struct qca8k_priv *priv)
+ {
+@@ -1017,13 +1033,13 @@ static int
+ qca8k_setup(struct dsa_switch *ds)
+ {
+ 	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+-	int ret, i;
++	int cpu_port, ret, i;
+ 	u32 mask;
+ 
+-	/* Make sure that port 0 is the cpu port */
+-	if (!dsa_is_cpu_port(ds, 0)) {
+-		dev_err(priv->dev, "port 0 is not the CPU port");
+-		return -EINVAL;
++	cpu_port = qca8k_find_cpu_port(ds);
++	if (cpu_port < 0) {
++		dev_err(priv->dev, "No cpu port configured in both cpu port0 and port6");
++		return cpu_port;
+ 	}
+ 
+ 	/* Parse CPU port config to be later used in phy_link mac_config */
+@@ -1065,7 +1081,7 @@ qca8k_setup(struct dsa_switch *ds)
+ 		dev_warn(priv->dev, "mib init failed");
+ 
+ 	/* Enable QCA header mode on the cpu port */
+-	ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
++	ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(cpu_port),
+ 			  QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
+ 			  QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
+ 	if (ret) {
+@@ -1087,10 +1103,10 @@ qca8k_setup(struct dsa_switch *ds)
+ 
+ 	/* Forward all unknown frames to CPU port for Linux processing */
+ 	ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
+-			  BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
+-			  BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
+-			  BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
+-			  BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
++			  BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
++			  BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
++			  BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
++			  BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -1098,7 +1114,7 @@ qca8k_setup(struct dsa_switch *ds)
+ 	for (i = 0; i < QCA8K_NUM_PORTS; i++) {
+ 		/* CPU port gets connected to all user ports of the switch */
+ 		if (dsa_is_cpu_port(ds, i)) {
+-			ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
++			ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(cpu_port),
+ 					QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds));
+ 			if (ret)
+ 				return ret;
+@@ -1110,7 +1126,7 @@ qca8k_setup(struct dsa_switch *ds)
+ 
+ 			ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
+ 					QCA8K_PORT_LOOKUP_MEMBER,
+-					BIT(QCA8K_CPU_PORT));
++					BIT(cpu_port));
+ 			if (ret)
+ 				return ret;
+ 
+@@ -1616,9 +1632,12 @@ static int
+ qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
+ {
+ 	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+-	int port_mask = BIT(QCA8K_CPU_PORT);
++	int port_mask, cpu_port;
+ 	int i, ret;
+ 
++	cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
++	port_mask = BIT(cpu_port);
++
+ 	for (i = 1; i < QCA8K_NUM_PORTS; i++) {
+ 		if (dsa_to_port(ds, i)->bridge_dev != br)
+ 			continue;
+@@ -1645,7 +1664,9 @@ static void
+ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
+ {
+ 	struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
+-	int i;
++	int cpu_port, i;
++
++	cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
+ 
+ 	for (i = 1; i < QCA8K_NUM_PORTS; i++) {
+ 		if (dsa_to_port(ds, i)->bridge_dev != br)
+@@ -1662,7 +1683,7 @@ qca8k_port_bridge_leave(struct dsa_switc
+ 	 * this port
+ 	 */
+ 	qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
+-		  QCA8K_PORT_LOOKUP_MEMBER, BIT(QCA8K_CPU_PORT));
++		  QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
+ }
+ 
+ static int
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -24,8 +24,6 @@
+ 
+ #define QCA8K_NUM_FDB_RECORDS				2048
+ 
+-#define QCA8K_CPU_PORT					0
+-
+ #define QCA8K_PORT_VID_DEF				1
+ 
+ /* Global control registers */
diff --git a/target/linux/generic/backport-5.10/797-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch b/target/linux/generic/backport-5.10/797-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch
new file mode 100644
index 0000000000..de201764f9
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-06-net-dsa-qca8k-rework-rgmii-delay-logic-and-scan-for-.patch
@@ -0,0 +1,295 @@
+From 5654ec78dd7e64b1e04777b24007344329e6a63b Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:11 +0200
+Subject: net: dsa: qca8k: rework rgmii delay logic and scan for cpu port 6
+
+Future proof commit. This switch have 2 CPU ports and one valid
+configuration is first CPU port set to sgmii and second CPU port set to
+rgmii-id. The current implementation detects delay only for CPU port
+zero set to rgmii and doesn't count any delay set in a secondary CPU
+port. Drop the current delay scan function and move it to the sgmii
+parser function to generalize and implicitly add support for secondary
+CPU port set to rgmii-id. Introduce new logic where delay is enabled
+also with internal delay binding declared and rgmii set as PHY mode.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 165 ++++++++++++++++++++++++------------------------
+ drivers/net/dsa/qca8k.h |  10 ++-
+ 2 files changed, 89 insertions(+), 86 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -889,68 +889,6 @@ qca8k_setup_mdio_bus(struct qca8k_priv *
+ }
+ 
+ static int
+-qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv)
+-{
+-	struct device_node *port_dn;
+-	phy_interface_t mode;
+-	struct dsa_port *dp;
+-	u32 val;
+-
+-	/* CPU port is already checked */
+-	dp = dsa_to_port(priv->ds, 0);
+-
+-	port_dn = dp->dn;
+-
+-	/* Check if port 0 is set to the correct type */
+-	of_get_phy_mode(port_dn, &mode);
+-	if (mode != PHY_INTERFACE_MODE_RGMII_ID &&
+-	    mode != PHY_INTERFACE_MODE_RGMII_RXID &&
+-	    mode != PHY_INTERFACE_MODE_RGMII_TXID) {
+-		return 0;
+-	}
+-
+-	switch (mode) {
+-	case PHY_INTERFACE_MODE_RGMII_ID:
+-	case PHY_INTERFACE_MODE_RGMII_RXID:
+-		if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val))
+-			val = 2;
+-		else
+-			/* Switch regs accept value in ns, convert ps to ns */
+-			val = val / 1000;
+-
+-		if (val > QCA8K_MAX_DELAY) {
+-			dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
+-			val = 3;
+-		}
+-
+-		priv->rgmii_rx_delay = val;
+-		/* Stop here if we need to check only for rx delay */
+-		if (mode != PHY_INTERFACE_MODE_RGMII_ID)
+-			break;
+-
+-		fallthrough;
+-	case PHY_INTERFACE_MODE_RGMII_TXID:
+-		if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val))
+-			val = 1;
+-		else
+-			/* Switch regs accept value in ns, convert ps to ns */
+-			val = val / 1000;
+-
+-		if (val > QCA8K_MAX_DELAY) {
+-			dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
+-			val = 3;
+-		}
+-
+-		priv->rgmii_tx_delay = val;
+-		break;
+-	default:
+-		return 0;
+-	}
+-
+-	return 0;
+-}
+-
+-static int
+ qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv)
+ {
+ 	u32 mask = 0;
+@@ -996,19 +934,21 @@ static int qca8k_find_cpu_port(struct ds
+ static int
+ qca8k_parse_port_config(struct qca8k_priv *priv)
+ {
++	int port, cpu_port_index = 0, ret;
+ 	struct device_node *port_dn;
+ 	phy_interface_t mode;
+ 	struct dsa_port *dp;
+-	int port, ret;
++	u32 delay;
+ 
+ 	/* We have 2 CPU port. Check them */
+-	for (port = 0; port < QCA8K_NUM_PORTS; port++) {
++	for (port = 0; port < QCA8K_NUM_PORTS && cpu_port_index < QCA8K_NUM_CPU_PORTS; port++) {
+ 		/* Skip every other port */
+ 		if (port != 0 && port != 6)
+ 			continue;
+ 
+ 		dp = dsa_to_port(priv->ds, port);
+ 		port_dn = dp->dn;
++		cpu_port_index++;
+ 
+ 		if (!of_device_is_available(port_dn))
+ 			continue;
+@@ -1017,12 +957,54 @@ qca8k_parse_port_config(struct qca8k_pri
+ 		if (ret)
+ 			continue;
+ 
+-		if (mode == PHY_INTERFACE_MODE_SGMII) {
++		switch (mode) {
++		case PHY_INTERFACE_MODE_RGMII:
++		case PHY_INTERFACE_MODE_RGMII_ID:
++		case PHY_INTERFACE_MODE_RGMII_TXID:
++		case PHY_INTERFACE_MODE_RGMII_RXID:
++			delay = 0;
++
++			if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay))
++				/* Switch regs accept value in ns, convert ps to ns */
++				delay = delay / 1000;
++			else if (mode == PHY_INTERFACE_MODE_RGMII_ID ||
++				 mode == PHY_INTERFACE_MODE_RGMII_TXID)
++				delay = 1;
++
++			if (delay > QCA8K_MAX_DELAY) {
++				dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
++				delay = 3;
++			}
++
++			priv->rgmii_tx_delay[cpu_port_index] = delay;
++
++			delay = 0;
++
++			if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay))
++				/* Switch regs accept value in ns, convert ps to ns */
++				delay = delay / 1000;
++			else if (mode == PHY_INTERFACE_MODE_RGMII_ID ||
++				 mode == PHY_INTERFACE_MODE_RGMII_RXID)
++				delay = 2;
++
++			if (delay > QCA8K_MAX_DELAY) {
++				dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
++				delay = 3;
++			}
++
++			priv->rgmii_rx_delay[cpu_port_index] = delay;
++
++			break;
++		case PHY_INTERFACE_MODE_SGMII:
+ 			if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge"))
+ 				priv->sgmii_tx_clk_falling_edge = true;
+ 
+ 			if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge"))
+ 				priv->sgmii_rx_clk_falling_edge = true;
++
++			break;
++		default:
++			continue;
+ 		}
+ 	}
+ 
+@@ -1059,10 +1041,6 @@ qca8k_setup(struct dsa_switch *ds)
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = qca8k_setup_of_rgmii_delay(priv);
+-	if (ret)
+-		return ret;
+-
+ 	ret = qca8k_setup_mac_pwr_sel(priv);
+ 	if (ret)
+ 		return ret;
+@@ -1229,8 +1207,8 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 			 const struct phylink_link_state *state)
+ {
+ 	struct qca8k_priv *priv = ds->priv;
+-	u32 reg, val;
+-	int ret;
++	int cpu_port_index, ret;
++	u32 reg, val, delay;
+ 
+ 	switch (port) {
+ 	case 0: /* 1st CPU port */
+@@ -1242,6 +1220,7 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 			return;
+ 
+ 		reg = QCA8K_REG_PORT0_PAD_CTRL;
++		cpu_port_index = QCA8K_CPU_PORT0;
+ 		break;
+ 	case 1:
+ 	case 2:
+@@ -1260,6 +1239,7 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 			return;
+ 
+ 		reg = QCA8K_REG_PORT6_PAD_CTRL;
++		cpu_port_index = QCA8K_CPU_PORT6;
+ 		break;
+ 	default:
+ 		dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
+@@ -1274,23 +1254,40 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 
+ 	switch (state->interface) {
+ 	case PHY_INTERFACE_MODE_RGMII:
+-		/* RGMII mode means no delay so don't enable the delay */
+-		qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
+-		break;
+ 	case PHY_INTERFACE_MODE_RGMII_ID:
+ 	case PHY_INTERFACE_MODE_RGMII_TXID:
+ 	case PHY_INTERFACE_MODE_RGMII_RXID:
+-		/* RGMII_ID needs internal delay. This is enabled through
+-		 * PORT5_PAD_CTRL for all ports, rather than individual port
+-		 * registers
++		val = QCA8K_PORT_PAD_RGMII_EN;
++
++		/* Delay can be declared in 3 different way.
++		 * Mode to rgmii and internal-delay standard binding defined
++		 * rgmii-id or rgmii-tx/rx phy mode set.
++		 * The parse logic set a delay different than 0 only when one
++		 * of the 3 different way is used. In all other case delay is
++		 * not enabled. With ID or TX/RXID delay is enabled and set
++		 * to the default and recommended value.
++		 */
++		if (priv->rgmii_tx_delay[cpu_port_index]) {
++			delay = priv->rgmii_tx_delay[cpu_port_index];
++
++			val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) |
++			       QCA8K_PORT_PAD_RGMII_TX_DELAY_EN;
++		}
++
++		if (priv->rgmii_rx_delay[cpu_port_index]) {
++			delay = priv->rgmii_rx_delay[cpu_port_index];
++
++			val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) |
++			       QCA8K_PORT_PAD_RGMII_RX_DELAY_EN;
++		}
++
++		/* Set RGMII delay based on the selected values */
++		qca8k_write(priv, reg, val);
++
++		/* QCA8337 requires to set rgmii rx delay for all ports.
++		 * This is enabled through PORT5_PAD_CTRL for all ports,
++		 * rather than individual port registers.
+ 		 */
+-		qca8k_write(priv, reg,
+-			    QCA8K_PORT_PAD_RGMII_EN |
+-			    QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) |
+-			    QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) |
+-			    QCA8K_PORT_PAD_RGMII_TX_DELAY_EN |
+-			    QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
+-		/* QCA8337 requires to set rgmii rx delay */
+ 		if (priv->switch_id == QCA8K_ID_QCA8337)
+ 			qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
+ 				    QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -13,6 +13,7 @@
+ #include <linux/gpio.h>
+ 
+ #define QCA8K_NUM_PORTS					7
++#define QCA8K_NUM_CPU_PORTS				2
+ #define QCA8K_MAX_MTU					9000
+ 
+ #define PHY_ID_QCA8327					0x004dd034
+@@ -255,13 +256,18 @@ struct qca8k_match_data {
+ 	u8 id;
+ };
+ 
++enum {
++	QCA8K_CPU_PORT0,
++	QCA8K_CPU_PORT6,
++};
++
+ struct qca8k_priv {
+ 	u8 switch_id;
+ 	u8 switch_revision;
+-	u8 rgmii_tx_delay;
+-	u8 rgmii_rx_delay;
+ 	bool sgmii_rx_clk_falling_edge;
+ 	bool sgmii_tx_clk_falling_edge;
++	u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
++	u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
+ 	bool legacy_phy_port_mapping;
+ 	struct regmap *regmap;
+ 	struct mii_bus *bus;
diff --git a/target/linux/generic/backport-5.10/797-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch b/target/linux/generic/backport-5.10/797-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch
new file mode 100644
index 0000000000..8abd264e79
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-07-dt-bindings-net-dsa-qca8k-Document-qca-sgmii-enable-.patch
@@ -0,0 +1,33 @@
+From 13ad5ccc093ff448b99ac7e138e91e78796adb48 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:12 +0200
+Subject: dt-bindings: net: dsa: qca8k: Document qca,sgmii-enable-pll
+
+Document qca,sgmii-enable-pll binding used in the CPU nodes to
+enable SGMII PLL on MAC config.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ Documentation/devicetree/bindings/net/dsa/qca8k.txt | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+@@ -45,6 +45,16 @@ A CPU port node has the following option
+                                 Mostly used in qca8327 with CPU port 0 set to
+                                 sgmii.
+ - qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge.
++- qca,sgmii-enable-pll  : For SGMII CPU port, explicitly enable PLL, TX and RX
++                          chain along with Signal Detection.
++                          This should NOT be enabled for qca8327. If enabled with
++                          qca8327 the sgmii port won't correctly init and an err
++                          is printed.
++                          This can be required for qca8337 switch with revision 2.
++                          A warning is displayed when used with revision greater
++                          2.
++                          With CPU port set to sgmii and qca8337 it is advised
++                          to set this unless a communication problem is observed.
+ 
+ For QCA8K the 'fixed-link' sub-node supports only the following properties:
+ 
diff --git a/target/linux/generic/backport-5.10/797-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch b/target/linux/generic/backport-5.10/797-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch
new file mode 100644
index 0000000000..2b5a84a1b0
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-08-net-dsa-qca8k-add-explicit-SGMII-PLL-enable.patch
@@ -0,0 +1,65 @@
+From bbc4799e8bb6c397e3b3fec13de68e179f5db9ff Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:13 +0200
+Subject: net: dsa: qca8k: add explicit SGMII PLL enable
+
+Support enabling PLL on the SGMII CPU port. Some device require this
+special configuration or no traffic is transmitted and the switch
+doesn't work at all. A dedicated binding is added to the CPU node
+port to apply the correct reg on mac config.
+Fail to correctly configure sgmii with qca8327 switch and warn if pll is
+used on qca8337 with a revision greater than 1.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 19 +++++++++++++++++--
+ drivers/net/dsa/qca8k.h |  1 +
+ 2 files changed, 18 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -1002,6 +1002,18 @@ qca8k_parse_port_config(struct qca8k_pri
+ 			if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge"))
+ 				priv->sgmii_rx_clk_falling_edge = true;
+ 
++			if (of_property_read_bool(port_dn, "qca,sgmii-enable-pll")) {
++				priv->sgmii_enable_pll = true;
++
++				if (priv->switch_id == QCA8K_ID_QCA8327) {
++					dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling");
++					priv->sgmii_enable_pll = false;
++				}
++
++				if (priv->switch_revision < 2)
++					dev_warn(priv->dev, "SGMII PLL should NOT be enabled for qca8337 with revision 2 or more.");
++			}
++
+ 			break;
+ 		default:
+ 			continue;
+@@ -1312,8 +1324,11 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 		if (ret)
+ 			return;
+ 
+-		val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
+-			QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD;
++		val |= QCA8K_SGMII_EN_SD;
++
++		if (priv->sgmii_enable_pll)
++			val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
++			       QCA8K_SGMII_EN_TX;
+ 
+ 		if (dsa_is_cpu_port(ds, port)) {
+ 			/* CPU port, we're talking to the CPU MAC, be a PHY */
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -266,6 +266,7 @@ struct qca8k_priv {
+ 	u8 switch_revision;
+ 	bool sgmii_rx_clk_falling_edge;
+ 	bool sgmii_tx_clk_falling_edge;
++	bool sgmii_enable_pll;
+ 	u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
+ 	u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
+ 	bool legacy_phy_port_mapping;
diff --git a/target/linux/generic/backport-5.10/797-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch b/target/linux/generic/backport-5.10/797-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch
new file mode 100644
index 0000000000..38dc954e8c
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-09-dt-bindings-net-dsa-qca8k-Document-qca-led-open-drai.patch
@@ -0,0 +1,37 @@
+From 924087c5c3d41553700b0eb83ca2a53b91643dca Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:14 +0200
+Subject: dt-bindings: net: dsa: qca8k: Document qca,led-open-drain binding
+
+Document new binding qca,ignore-power-on-sel used to ignore
+power on strapping and use sw regs instead.
+Document qca,led-open.drain to set led to open drain mode, the
+qca,ignore-power-on-sel is mandatory with this enabled or an error will
+be reported.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ Documentation/devicetree/bindings/net/dsa/qca8k.txt | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+@@ -13,6 +13,17 @@ Required properties:
+ Optional properties:
+ 
+ - reset-gpios: GPIO to be used to reset the whole device
++- qca,ignore-power-on-sel: Ignore power on pin strapping to configure led open
++                           drain or eeprom presence. This is needed for broken
++                           devices that have wrong configuration or when the oem
++                           decided to not use pin strapping and fallback to sw
++                           regs.
++- qca,led-open-drain: Set leds to open-drain mode. This requires the
++                      qca,ignore-power-on-sel to be set or the driver will fail
++                      to probe. This is needed if the oem doesn't use pin
++                      strapping to set this mode and prefers to set it using sw
++                      regs. The pin strapping related to led open drain mode is
++                      the pin B68 for QCA832x and B49 for QCA833x
+ 
+ Subnodes:
+ 
diff --git a/target/linux/generic/backport-5.10/797-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch b/target/linux/generic/backport-5.10/797-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch
new file mode 100644
index 0000000000..aa5d92a4fd
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-10-net-dsa-qca8k-add-support-for-pws-config-reg.patch
@@ -0,0 +1,92 @@
+From 362bb238d8bf1470424214a8a5968d9c6cce68fa Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:15 +0200
+Subject: net: dsa: qca8k: add support for pws config reg
+
+Some qca8327 switch require to force the ignore of power on sel
+strapping. Some switch require to set the led open drain mode in regs
+instead of using strapping. While most of the device implements this
+using the correct way using pin strapping, there are still some broken
+device that require to be set using sw regs.
+Introduce a new binding and support these special configuration.
+As led open drain require to ignore pin strapping to work, the probe
+fails with EINVAL error with incorrect configuration.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 39 +++++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/qca8k.h |  6 ++++++
+ 2 files changed, 45 insertions(+)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -932,6 +932,41 @@ static int qca8k_find_cpu_port(struct ds
+ }
+ 
+ static int
++qca8k_setup_of_pws_reg(struct qca8k_priv *priv)
++{
++	struct device_node *node = priv->dev->of_node;
++	u32 val = 0;
++	int ret;
++
++	/* QCA8327 require to set to the correct mode.
++	 * His bigger brother QCA8328 have the 172 pin layout.
++	 * Should be applied by default but we set this just to make sure.
++	 */
++	if (priv->switch_id == QCA8K_ID_QCA8327) {
++		ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN,
++				QCA8327_PWS_PACKAGE148_EN);
++		if (ret)
++			return ret;
++	}
++
++	if (of_property_read_bool(node, "qca,ignore-power-on-sel"))
++		val |= QCA8K_PWS_POWER_ON_SEL;
++
++	if (of_property_read_bool(node, "qca,led-open-drain")) {
++		if (!(val & QCA8K_PWS_POWER_ON_SEL)) {
++			dev_err(priv->dev, "qca,led-open-drain require qca,ignore-power-on-sel to be set.");
++			return -EINVAL;
++		}
++
++		val |= QCA8K_PWS_LED_OPEN_EN_CSR;
++	}
++
++	return qca8k_rmw(priv, QCA8K_REG_PWS,
++			QCA8K_PWS_LED_OPEN_EN_CSR | QCA8K_PWS_POWER_ON_SEL,
++			val);
++}
++
++static int
+ qca8k_parse_port_config(struct qca8k_priv *priv)
+ {
+ 	int port, cpu_port_index = 0, ret;
+@@ -1053,6 +1088,10 @@ qca8k_setup(struct dsa_switch *ds)
+ 	if (ret)
+ 		return ret;
+ 
++	ret = qca8k_setup_of_pws_reg(priv);
++	if (ret)
++		return ret;
++
+ 	ret = qca8k_setup_mac_pwr_sel(priv);
+ 	if (ret)
+ 		return ret;
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -46,6 +46,12 @@
+ #define   QCA8K_MAX_DELAY				3
+ #define   QCA8K_PORT_PAD_SGMII_EN			BIT(7)
+ #define QCA8K_REG_PWS					0x010
++#define   QCA8K_PWS_POWER_ON_SEL			BIT(31)
++/* This reg is only valid for QCA832x and toggle the package
++ * type from 176 pin (by default) to 148 pin used on QCA8327
++ */
++#define   QCA8327_PWS_PACKAGE148_EN			BIT(30)
++#define   QCA8K_PWS_LED_OPEN_EN_CSR			BIT(24)
+ #define   QCA8K_PWS_SERDES_AEN_DIS			BIT(7)
+ #define QCA8K_REG_MODULE_EN				0x030
+ #define   QCA8K_MODULE_EN_MIB				BIT(0)
diff --git a/target/linux/generic/backport-5.10/797-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch b/target/linux/generic/backport-5.10/797-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch
new file mode 100644
index 0000000000..1bfb00c5b2
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-11-dt-bindings-net-dsa-qca8k-document-support-for-qca83.patch
@@ -0,0 +1,32 @@
+From ed7988d77fbfb79366b68f9e7fa60a6080da23d4 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:16 +0200
+Subject: dt-bindings: net: dsa: qca8k: document support for qca8328
+
+QCA8328 is the bigger brother of qca8327. Document the new compatible
+binding and add some information to understand the various switch
+compatible.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ Documentation/devicetree/bindings/net/dsa/qca8k.txt | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.txt
+@@ -3,9 +3,10 @@
+ Required properties:
+ 
+ - compatible: should be one of:
+-    "qca,qca8327"
+-    "qca,qca8334"
+-    "qca,qca8337"
++    "qca,qca8328": referenced as AR8328(N)-AK1(A/B) QFN 176 pin package
++    "qca,qca8327": referenced as AR8327(N)-AL1A DR-QFN 148 pin package
++    "qca,qca8334": referenced as QCA8334-AL3C QFN 88 pin package
++    "qca,qca8337": referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package
+ 
+ - #size-cells: must be 0
+ - #address-cells: must be 1
diff --git a/target/linux/generic/backport-5.10/797-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch b/target/linux/generic/backport-5.10/797-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch
new file mode 100644
index 0000000000..6e118f5a14
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-12-net-dsa-qca8k-add-support-for-QCA8328.patch
@@ -0,0 +1,78 @@
+From f477d1c8bdbef4f400718238e350f16f521d2a3e Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:17 +0200
+Subject: net: dsa: qca8k: add support for QCA8328
+
+QCA8328 switch is the bigger brother of the qca8327. Same regs different
+chip. Change the function to set the correct pin layout and introduce a
+new match_data to differentiate the 2 switch as they have the same ID
+and their internal PHY have the same ID.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 19 ++++++++++++++++---
+ drivers/net/dsa/qca8k.h |  1 +
+ 2 files changed, 17 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -935,6 +935,7 @@ static int
+ qca8k_setup_of_pws_reg(struct qca8k_priv *priv)
+ {
+ 	struct device_node *node = priv->dev->of_node;
++	const struct qca8k_match_data *data;
+ 	u32 val = 0;
+ 	int ret;
+ 
+@@ -943,8 +944,14 @@ qca8k_setup_of_pws_reg(struct qca8k_priv
+ 	 * Should be applied by default but we set this just to make sure.
+ 	 */
+ 	if (priv->switch_id == QCA8K_ID_QCA8327) {
++		data = of_device_get_match_data(priv->dev);
++
++		/* Set the correct package of 148 pin for QCA8327 */
++		if (data->reduced_package)
++			val |= QCA8327_PWS_PACKAGE148_EN;
++
+ 		ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN,
+-				QCA8327_PWS_PACKAGE148_EN);
++				val);
+ 		if (ret)
+ 			return ret;
+ 	}
+@@ -2098,7 +2105,12 @@ static int qca8k_resume(struct device *d
+ static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
+ 			 qca8k_suspend, qca8k_resume);
+ 
+-static const struct qca8k_match_data qca832x = {
++static const struct qca8k_match_data qca8327 = {
++	.id = QCA8K_ID_QCA8327,
++	.reduced_package = true,
++};
++
++static const struct qca8k_match_data qca8328 = {
+ 	.id = QCA8K_ID_QCA8327,
+ };
+ 
+@@ -2107,7 +2119,8 @@ static const struct qca8k_match_data qca
+ };
+ 
+ static const struct of_device_id qca8k_of_match[] = {
+-	{ .compatible = "qca,qca8327", .data = &qca832x },
++	{ .compatible = "qca,qca8327", .data = &qca8327 },
++	{ .compatible = "qca,qca8328", .data = &qca8328 },
+ 	{ .compatible = "qca,qca8334", .data = &qca833x },
+ 	{ .compatible = "qca,qca8337", .data = &qca833x },
+ 	{ /* sentinel */ },
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -260,6 +260,7 @@ struct ar8xxx_port_status {
+ 
+ struct qca8k_match_data {
+ 	u8 id;
++	bool reduced_package;
+ };
+ 
+ enum {
diff --git a/target/linux/generic/backport-5.10/797-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch b/target/linux/generic/backport-5.10/797-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch
new file mode 100644
index 0000000000..27f94dca02
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-13-net-dsa-qca8k-set-internal-delay-also-for-sgmii.patch
@@ -0,0 +1,159 @@
+From cef08115846e581f80ff99abf7bf218da1840616 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:18 +0200
+Subject: net: dsa: qca8k: set internal delay also for sgmii
+
+QCA original code report port instability and sa that SGMII also require
+to set internal delay. Generalize the rgmii delay function and apply the
+advised value if they are not defined in DT.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 88 +++++++++++++++++++++++++++++++++----------------
+ drivers/net/dsa/qca8k.h |  2 ++
+ 2 files changed, 62 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -1004,6 +1004,7 @@ qca8k_parse_port_config(struct qca8k_pri
+ 		case PHY_INTERFACE_MODE_RGMII_ID:
+ 		case PHY_INTERFACE_MODE_RGMII_TXID:
+ 		case PHY_INTERFACE_MODE_RGMII_RXID:
++		case PHY_INTERFACE_MODE_SGMII:
+ 			delay = 0;
+ 
+ 			if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay))
+@@ -1036,8 +1037,13 @@ qca8k_parse_port_config(struct qca8k_pri
+ 
+ 			priv->rgmii_rx_delay[cpu_port_index] = delay;
+ 
+-			break;
+-		case PHY_INTERFACE_MODE_SGMII:
++			/* Skip sgmii parsing for rgmii* mode */
++			if (mode == PHY_INTERFACE_MODE_RGMII ||
++			    mode == PHY_INTERFACE_MODE_RGMII_ID ||
++			    mode == PHY_INTERFACE_MODE_RGMII_TXID ||
++			    mode == PHY_INTERFACE_MODE_RGMII_RXID)
++				break;
++
+ 			if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge"))
+ 				priv->sgmii_tx_clk_falling_edge = true;
+ 
+@@ -1261,12 +1267,53 @@ qca8k_setup(struct dsa_switch *ds)
+ }
+ 
+ static void
++qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_index,
++				      u32 reg)
++{
++	u32 delay, val = 0;
++	int ret;
++
++	/* Delay can be declared in 3 different way.
++	 * Mode to rgmii and internal-delay standard binding defined
++	 * rgmii-id or rgmii-tx/rx phy mode set.
++	 * The parse logic set a delay different than 0 only when one
++	 * of the 3 different way is used. In all other case delay is
++	 * not enabled. With ID or TX/RXID delay is enabled and set
++	 * to the default and recommended value.
++	 */
++	if (priv->rgmii_tx_delay[cpu_port_index]) {
++		delay = priv->rgmii_tx_delay[cpu_port_index];
++
++		val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) |
++			QCA8K_PORT_PAD_RGMII_TX_DELAY_EN;
++	}
++
++	if (priv->rgmii_rx_delay[cpu_port_index]) {
++		delay = priv->rgmii_rx_delay[cpu_port_index];
++
++		val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) |
++			QCA8K_PORT_PAD_RGMII_RX_DELAY_EN;
++	}
++
++	/* Set RGMII delay based on the selected values */
++	ret = qca8k_rmw(priv, reg,
++			QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK |
++			QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK |
++			QCA8K_PORT_PAD_RGMII_TX_DELAY_EN |
++			QCA8K_PORT_PAD_RGMII_RX_DELAY_EN,
++			val);
++	if (ret)
++		dev_err(priv->dev, "Failed to set internal delay for CPU port%d",
++			cpu_port_index == QCA8K_CPU_PORT0 ? 0 : 6);
++}
++
++static void
+ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ 			 const struct phylink_link_state *state)
+ {
+ 	struct qca8k_priv *priv = ds->priv;
+ 	int cpu_port_index, ret;
+-	u32 reg, val, delay;
++	u32 reg, val;
+ 
+ 	switch (port) {
+ 	case 0: /* 1st CPU port */
+@@ -1315,32 +1362,10 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 	case PHY_INTERFACE_MODE_RGMII_ID:
+ 	case PHY_INTERFACE_MODE_RGMII_TXID:
+ 	case PHY_INTERFACE_MODE_RGMII_RXID:
+-		val = QCA8K_PORT_PAD_RGMII_EN;
+-
+-		/* Delay can be declared in 3 different way.
+-		 * Mode to rgmii and internal-delay standard binding defined
+-		 * rgmii-id or rgmii-tx/rx phy mode set.
+-		 * The parse logic set a delay different than 0 only when one
+-		 * of the 3 different way is used. In all other case delay is
+-		 * not enabled. With ID or TX/RXID delay is enabled and set
+-		 * to the default and recommended value.
+-		 */
+-		if (priv->rgmii_tx_delay[cpu_port_index]) {
+-			delay = priv->rgmii_tx_delay[cpu_port_index];
+-
+-			val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) |
+-			       QCA8K_PORT_PAD_RGMII_TX_DELAY_EN;
+-		}
+-
+-		if (priv->rgmii_rx_delay[cpu_port_index]) {
+-			delay = priv->rgmii_rx_delay[cpu_port_index];
+-
+-			val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) |
+-			       QCA8K_PORT_PAD_RGMII_RX_DELAY_EN;
+-		}
++		qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
+ 
+-		/* Set RGMII delay based on the selected values */
+-		qca8k_write(priv, reg, val);
++		/* Configure rgmii delay */
++		qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg);
+ 
+ 		/* QCA8337 requires to set rgmii rx delay for all ports.
+ 		 * This is enabled through PORT5_PAD_CTRL for all ports,
+@@ -1411,6 +1436,13 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 					QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE |
+ 					QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE,
+ 					val);
++
++		/* From original code is reported port instability as SGMII also
++		 * require delay set. Apply advised values here or take them from DT.
++		 */
++		if (state->interface == PHY_INTERFACE_MODE_SGMII)
++			qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg);
++
+ 		break;
+ 	default:
+ 		dev_err(ds->dev, "xMII mode %s not supported for port %d\n",
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -39,7 +39,9 @@
+ #define QCA8K_REG_PORT5_PAD_CTRL			0x008
+ #define QCA8K_REG_PORT6_PAD_CTRL			0x00c
+ #define   QCA8K_PORT_PAD_RGMII_EN			BIT(26)
++#define   QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK		GENMASK(23, 22)
+ #define   QCA8K_PORT_PAD_RGMII_TX_DELAY(x)		((x) << 22)
++#define   QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK		GENMASK(21, 20)
+ #define   QCA8K_PORT_PAD_RGMII_RX_DELAY(x)		((x) << 20)
+ #define	  QCA8K_PORT_PAD_RGMII_TX_DELAY_EN		BIT(25)
+ #define   QCA8K_PORT_PAD_RGMII_RX_DELAY_EN		BIT(24)
diff --git a/target/linux/generic/backport-5.10/797-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch b/target/linux/generic/backport-5.10/797-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch
new file mode 100644
index 0000000000..b991798c87
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-14-net-dsa-qca8k-move-port-config-to-dedicated-struct.patch
@@ -0,0 +1,124 @@
+From fd0bb28c547f7c8affb1691128cece38f5b626a1 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:19 +0200
+Subject: net: dsa: qca8k: move port config to dedicated struct
+
+Move ports related config to dedicated struct to keep things organized.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 26 +++++++++++++-------------
+ drivers/net/dsa/qca8k.h | 10 +++++++---
+ 2 files changed, 20 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -1019,7 +1019,7 @@ qca8k_parse_port_config(struct qca8k_pri
+ 				delay = 3;
+ 			}
+ 
+-			priv->rgmii_tx_delay[cpu_port_index] = delay;
++			priv->ports_config.rgmii_tx_delay[cpu_port_index] = delay;
+ 
+ 			delay = 0;
+ 
+@@ -1035,7 +1035,7 @@ qca8k_parse_port_config(struct qca8k_pri
+ 				delay = 3;
+ 			}
+ 
+-			priv->rgmii_rx_delay[cpu_port_index] = delay;
++			priv->ports_config.rgmii_rx_delay[cpu_port_index] = delay;
+ 
+ 			/* Skip sgmii parsing for rgmii* mode */
+ 			if (mode == PHY_INTERFACE_MODE_RGMII ||
+@@ -1045,17 +1045,17 @@ qca8k_parse_port_config(struct qca8k_pri
+ 				break;
+ 
+ 			if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge"))
+-				priv->sgmii_tx_clk_falling_edge = true;
++				priv->ports_config.sgmii_tx_clk_falling_edge = true;
+ 
+ 			if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge"))
+-				priv->sgmii_rx_clk_falling_edge = true;
++				priv->ports_config.sgmii_rx_clk_falling_edge = true;
+ 
+ 			if (of_property_read_bool(port_dn, "qca,sgmii-enable-pll")) {
+-				priv->sgmii_enable_pll = true;
++				priv->ports_config.sgmii_enable_pll = true;
+ 
+ 				if (priv->switch_id == QCA8K_ID_QCA8327) {
+ 					dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling");
+-					priv->sgmii_enable_pll = false;
++					priv->ports_config.sgmii_enable_pll = false;
+ 				}
+ 
+ 				if (priv->switch_revision < 2)
+@@ -1281,15 +1281,15 @@ qca8k_mac_config_setup_internal_delay(st
+ 	 * not enabled. With ID or TX/RXID delay is enabled and set
+ 	 * to the default and recommended value.
+ 	 */
+-	if (priv->rgmii_tx_delay[cpu_port_index]) {
+-		delay = priv->rgmii_tx_delay[cpu_port_index];
++	if (priv->ports_config.rgmii_tx_delay[cpu_port_index]) {
++		delay = priv->ports_config.rgmii_tx_delay[cpu_port_index];
+ 
+ 		val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) |
+ 			QCA8K_PORT_PAD_RGMII_TX_DELAY_EN;
+ 	}
+ 
+-	if (priv->rgmii_rx_delay[cpu_port_index]) {
+-		delay = priv->rgmii_rx_delay[cpu_port_index];
++	if (priv->ports_config.rgmii_rx_delay[cpu_port_index]) {
++		delay = priv->ports_config.rgmii_rx_delay[cpu_port_index];
+ 
+ 		val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) |
+ 			QCA8K_PORT_PAD_RGMII_RX_DELAY_EN;
+@@ -1397,7 +1397,7 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 
+ 		val |= QCA8K_SGMII_EN_SD;
+ 
+-		if (priv->sgmii_enable_pll)
++		if (priv->ports_config.sgmii_enable_pll)
+ 			val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
+ 			       QCA8K_SGMII_EN_TX;
+ 
+@@ -1425,10 +1425,10 @@ qca8k_phylink_mac_config(struct dsa_swit
+ 		val = 0;
+ 
+ 		/* SGMII Clock phase configuration */
+-		if (priv->sgmii_rx_clk_falling_edge)
++		if (priv->ports_config.sgmii_rx_clk_falling_edge)
+ 			val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE;
+ 
+-		if (priv->sgmii_tx_clk_falling_edge)
++		if (priv->ports_config.sgmii_tx_clk_falling_edge)
+ 			val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE;
+ 
+ 		if (val)
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -270,15 +270,19 @@ enum {
+ 	QCA8K_CPU_PORT6,
+ };
+ 
+-struct qca8k_priv {
+-	u8 switch_id;
+-	u8 switch_revision;
++struct qca8k_ports_config {
+ 	bool sgmii_rx_clk_falling_edge;
+ 	bool sgmii_tx_clk_falling_edge;
+ 	bool sgmii_enable_pll;
+ 	u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
+ 	u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
++};
++
++struct qca8k_priv {
++	u8 switch_id;
++	u8 switch_revision;
+ 	bool legacy_phy_port_mapping;
++	struct qca8k_ports_config ports_config;
+ 	struct regmap *regmap;
+ 	struct mii_bus *bus;
+ 	struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
diff --git a/target/linux/generic/backport-5.10/797-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch b/target/linux/generic/backport-5.10/797-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch
new file mode 100644
index 0000000000..f7cb514176
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-15-dt-bindings-net-ipq8064-mdio-fix-warning-with-new-qc.patch
@@ -0,0 +1,26 @@
+From e52073a8e3086046a098b8a7cbeb282ff0cdb424 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:20 +0200
+Subject: dt-bindings: net: ipq8064-mdio: fix warning with new qca8k switch
+
+Fix warning now that we have qca8k switch Documentation using yaml.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ Documentation/devicetree/bindings/net/qcom,ipq8064-mdio.yaml | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/Documentation/devicetree/bindings/net/qcom,ipq8064-mdio.yaml
++++ b/Documentation/devicetree/bindings/net/qcom,ipq8064-mdio.yaml
+@@ -51,6 +51,9 @@ examples:
+         switch at 10 {
+             compatible = "qca,qca8337";
+             reg = <0x10>;
+-            /* ... */
++
++            ports {
++              /* ... */
++            };
+         };
+     };
diff --git a/target/linux/generic/backport-5.10/797-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch b/target/linux/generic/backport-5.10/797-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch
new file mode 100644
index 0000000000..b9bce97dd3
--- /dev/null
+++ b/target/linux/generic/backport-5.10/797-v5.16-16-dt-bindings-net-dsa-qca8k-convert-to-YAML-schema.patch
@@ -0,0 +1,631 @@
+From d291fbb8245d5ba04979fed85575860a5cea7196 Mon Sep 17 00:00:00 2001
+From: Matthew Hagan <mnhagan88 at gmail.com>
+Date: Thu, 14 Oct 2021 00:39:21 +0200
+Subject: dt-bindings: net: dsa: qca8k: convert to YAML schema
+
+Convert the qca8k bindings to YAML format.
+
+Signed-off-by: Matthew Hagan <mnhagan88 at gmail.com>
+Co-developed-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ .../devicetree/bindings/net/dsa/qca8k.txt          | 245 --------------
+ .../devicetree/bindings/net/dsa/qca8k.yaml         | 362 +++++++++++++++++++++
+ 2 files changed, 362 insertions(+), 245 deletions(-)
+ delete mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.txt
+ create mode 100644 Documentation/devicetree/bindings/net/dsa/qca8k.yaml
+
+--- a/Documentation/devicetree/bindings/net/dsa/qca8k.txt
++++ /dev/null
+@@ -1,245 +0,0 @@
+-* Qualcomm Atheros QCA8xxx switch family
+-
+-Required properties:
+-
+-- compatible: should be one of:
+-    "qca,qca8328": referenced as AR8328(N)-AK1(A/B) QFN 176 pin package
+-    "qca,qca8327": referenced as AR8327(N)-AL1A DR-QFN 148 pin package
+-    "qca,qca8334": referenced as QCA8334-AL3C QFN 88 pin package
+-    "qca,qca8337": referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package
+-
+-- #size-cells: must be 0
+-- #address-cells: must be 1
+-
+-Optional properties:
+-
+-- reset-gpios: GPIO to be used to reset the whole device
+-- qca,ignore-power-on-sel: Ignore power on pin strapping to configure led open
+-                           drain or eeprom presence. This is needed for broken
+-                           devices that have wrong configuration or when the oem
+-                           decided to not use pin strapping and fallback to sw
+-                           regs.
+-- qca,led-open-drain: Set leds to open-drain mode. This requires the
+-                      qca,ignore-power-on-sel to be set or the driver will fail
+-                      to probe. This is needed if the oem doesn't use pin
+-                      strapping to set this mode and prefers to set it using sw
+-                      regs. The pin strapping related to led open drain mode is
+-                      the pin B68 for QCA832x and B49 for QCA833x
+-
+-Subnodes:
+-
+-The integrated switch subnode should be specified according to the binding
+-described in dsa/dsa.txt. If the QCA8K switch is connect to a SoC's external
+-mdio-bus each subnode describing a port needs to have a valid phandle
+-referencing the internal PHY it is connected to. This is because there's no
+-N:N mapping of port and PHY id.
+-To declare the internal mdio-bus configuration, declare a mdio node in the
+-switch node and declare the phandle for the port referencing the internal
+-PHY is connected to. In this config a internal mdio-bus is registered and
+-the mdio MASTER is used as communication.
+-
+-Don't use mixed external and internal mdio-bus configurations, as this is
+-not supported by the hardware.
+-
+-This switch support 2 CPU port. Normally and advised configuration is with
+-CPU port set to port 0. It is also possible to set the CPU port to port 6
+-if the device requires it. The driver will configure the switch to the defined
+-port. With both CPU port declared the first CPU port is selected as primary
+-and the secondary CPU ignored.
+-
+-A CPU port node has the following optional node:
+-
+-- fixed-link            : Fixed-link subnode describing a link to a non-MDIO
+-                          managed entity. See
+-                          Documentation/devicetree/bindings/net/fixed-link.txt
+-                          for details.
+-- qca,sgmii-rxclk-falling-edge: Set the receive clock phase to falling edge.
+-                                Mostly used in qca8327 with CPU port 0 set to
+-                                sgmii.
+-- qca,sgmii-txclk-falling-edge: Set the transmit clock phase to falling edge.
+-- qca,sgmii-enable-pll  : For SGMII CPU port, explicitly enable PLL, TX and RX
+-                          chain along with Signal Detection.
+-                          This should NOT be enabled for qca8327. If enabled with
+-                          qca8327 the sgmii port won't correctly init and an err
+-                          is printed.
+-                          This can be required for qca8337 switch with revision 2.
+-                          A warning is displayed when used with revision greater
+-                          2.
+-                          With CPU port set to sgmii and qca8337 it is advised
+-                          to set this unless a communication problem is observed.
+-
+-For QCA8K the 'fixed-link' sub-node supports only the following properties:
+-
+-- 'speed' (integer, mandatory), to indicate the link speed. Accepted
+-  values are 10, 100 and 1000
+-- 'full-duplex' (boolean, optional), to indicate that full duplex is
+-  used. When absent, half duplex is assumed.
+-
+-Examples:
+-
+-for the external mdio-bus configuration:
+-
+-	&mdio0 {
+-		phy_port1: phy at 0 {
+-			reg = <0>;
+-		};
+-
+-		phy_port2: phy at 1 {
+-			reg = <1>;
+-		};
+-
+-		phy_port3: phy at 2 {
+-			reg = <2>;
+-		};
+-
+-		phy_port4: phy at 3 {
+-			reg = <3>;
+-		};
+-
+-		phy_port5: phy at 4 {
+-			reg = <4>;
+-		};
+-
+-		switch at 10 {
+-			compatible = "qca,qca8337";
+-			#address-cells = <1>;
+-			#size-cells = <0>;
+-
+-			reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
+-			reg = <0x10>;
+-
+-			ports {
+-				#address-cells = <1>;
+-				#size-cells = <0>;
+-				port at 0 {
+-					reg = <0>;
+-					label = "cpu";
+-					ethernet = <&gmac1>;
+-					phy-mode = "rgmii";
+-					fixed-link {
+-						speed = 1000;
+-						full-duplex;
+-					};
+-				};
+-
+-				port at 1 {
+-					reg = <1>;
+-					label = "lan1";
+-					phy-handle = <&phy_port1>;
+-				};
+-
+-				port at 2 {
+-					reg = <2>;
+-					label = "lan2";
+-					phy-handle = <&phy_port2>;
+-				};
+-
+-				port at 3 {
+-					reg = <3>;
+-					label = "lan3";
+-					phy-handle = <&phy_port3>;
+-				};
+-
+-				port at 4 {
+-					reg = <4>;
+-					label = "lan4";
+-					phy-handle = <&phy_port4>;
+-				};
+-
+-				port at 5 {
+-					reg = <5>;
+-					label = "wan";
+-					phy-handle = <&phy_port5>;
+-				};
+-			};
+-		};
+-	};
+-
+-for the internal master mdio-bus configuration:
+-
+-	&mdio0 {
+-		switch at 10 {
+-			compatible = "qca,qca8337";
+-			#address-cells = <1>;
+-			#size-cells = <0>;
+-
+-			reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
+-			reg = <0x10>;
+-
+-			ports {
+-				#address-cells = <1>;
+-				#size-cells = <0>;
+-
+-				port at 0 {
+-					reg = <0>;
+-					label = "cpu";
+-					ethernet = <&gmac1>;
+-					phy-mode = "rgmii";
+-					fixed-link {
+-						speed = 1000;
+-						full-duplex;
+-					};
+-				};
+-
+-				port at 1 {
+-					reg = <1>;
+-					label = "lan1";
+-					phy-mode = "internal";
+-					phy-handle = <&phy_port1>;
+-				};
+-
+-				port at 2 {
+-					reg = <2>;
+-					label = "lan2";
+-					phy-mode = "internal";
+-					phy-handle = <&phy_port2>;
+-				};
+-
+-				port at 3 {
+-					reg = <3>;
+-					label = "lan3";
+-					phy-mode = "internal";
+-					phy-handle = <&phy_port3>;
+-				};
+-
+-				port at 4 {
+-					reg = <4>;
+-					label = "lan4";
+-					phy-mode = "internal";
+-					phy-handle = <&phy_port4>;
+-				};
+-
+-				port at 5 {
+-					reg = <5>;
+-					label = "wan";
+-					phy-mode = "internal";
+-					phy-handle = <&phy_port5>;
+-				};
+-			};
+-
+-			mdio {
+-				#address-cells = <1>;
+-				#size-cells = <0>;
+-
+-				phy_port1: phy at 0 {
+-					reg = <0>;
+-				};
+-
+-				phy_port2: phy at 1 {
+-					reg = <1>;
+-				};
+-
+-				phy_port3: phy at 2 {
+-					reg = <2>;
+-				};
+-
+-				phy_port4: phy at 3 {
+-					reg = <3>;
+-				};
+-
+-				phy_port5: phy at 4 {
+-					reg = <4>;
+-				};
+-			};
+-		};
+-	};
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/dsa/qca8k.yaml
+@@ -0,0 +1,362 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/net/dsa/qca8k.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Qualcomm Atheros QCA83xx switch family
++
++maintainers:
++  - John Crispin <john at phrozen.org>
++
++description:
++  If the QCA8K switch is connect to an SoC's external mdio-bus, each subnode
++  describing a port needs to have a valid phandle referencing the internal PHY
++  it is connected to. This is because there is no N:N mapping of port and PHY
++  ID. To declare the internal mdio-bus configuration, declare an MDIO node in
++  the switch node and declare the phandle for the port, referencing the internal
++  PHY it is connected to. In this config, an internal mdio-bus is registered and
++  the MDIO master is used for communication. Mixed external and internal
++  mdio-bus configurations are not supported by the hardware.
++
++properties:
++  compatible:
++    oneOf:
++      - enum:
++          - qca,qca8327
++          - qca,qca8328
++          - qca,qca8334
++          - qca,qca8337
++    description: |
++      qca,qca8328: referenced as AR8328(N)-AK1(A/B) QFN 176 pin package
++      qca,qca8327: referenced as AR8327(N)-AL1A DR-QFN 148 pin package
++      qca,qca8334: referenced as QCA8334-AL3C QFN 88 pin package
++      qca,qca8337: referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package
++
++  reg:
++    maxItems: 1
++
++  reset-gpios:
++    description:
++      GPIO to be used to reset the whole device
++    maxItems: 1
++
++  qca,ignore-power-on-sel:
++    $ref: /schemas/types.yaml#/definitions/flag
++    description:
++      Ignore power-on pin strapping to configure LED open-drain or EEPROM
++      presence. This is needed for devices with incorrect configuration or when
++      the OEM has decided not to use pin strapping and falls back to SW regs.
++
++  qca,led-open-drain:
++    $ref: /schemas/types.yaml#/definitions/flag
++    description:
++      Set LEDs to open-drain mode. This requires the qca,ignore-power-on-sel to
++      be set, otherwise the driver will fail at probe. This is required if the
++      OEM does not use pin strapping to set this mode and prefers to set it
++      using SW regs. The pin strappings related to LED open-drain mode are
++      B68 on the QCA832x and B49 on the QCA833x.
++
++  mdio:
++    type: object
++    description: Qca8k switch have an internal mdio to access switch port.
++                 If this is not present, the legacy mapping is used and the
++                 internal mdio access is used.
++                 With the legacy mapping the reg corresponding to the internal
++                 mdio is the switch reg with an offset of -1.
++
++    properties:
++      '#address-cells':
++        const: 1
++      '#size-cells':
++        const: 0
++
++    patternProperties:
++      "^(ethernet-)?phy@[0-4]$":
++        type: object
++
++        allOf:
++          - $ref: "http://devicetree.org/schemas/net/mdio.yaml#"
++
++        properties:
++          reg:
++            maxItems: 1
++
++        required:
++          - reg
++
++patternProperties:
++  "^(ethernet-)?ports$":
++    type: object
++    properties:
++      '#address-cells':
++        const: 1
++      '#size-cells':
++        const: 0
++
++    patternProperties:
++      "^(ethernet-)?port@[0-6]$":
++        type: object
++        description: Ethernet switch ports
++
++        properties:
++          reg:
++            description: Port number
++
++          label:
++            description:
++              Describes the label associated with this port, which will become
++              the netdev name
++            $ref: /schemas/types.yaml#/definitions/string
++
++          link:
++            description:
++              Should be a list of phandles to other switch's DSA port. This
++              port is used as the outgoing port towards the phandle ports. The
++              full routing information must be given, not just the one hop
++              routes to neighbouring switches
++            $ref: /schemas/types.yaml#/definitions/phandle-array
++
++          ethernet:
++            description:
++              Should be a phandle to a valid Ethernet device node.  This host
++              device is what the switch port is connected to
++            $ref: /schemas/types.yaml#/definitions/phandle
++
++          phy-handle: true
++
++          phy-mode: true
++
++          fixed-link: true
++
++          mac-address: true
++
++          sfp: true
++
++          qca,sgmii-rxclk-falling-edge:
++            $ref: /schemas/types.yaml#/definitions/flag
++            description:
++              Set the receive clock phase to falling edge. Mostly commonly used on
++              the QCA8327 with CPU port 0 set to SGMII.
++
++          qca,sgmii-txclk-falling-edge:
++            $ref: /schemas/types.yaml#/definitions/flag
++            description:
++              Set the transmit clock phase to falling edge.
++
++          qca,sgmii-enable-pll:
++            $ref: /schemas/types.yaml#/definitions/flag
++            description:
++              For SGMII CPU port, explicitly enable PLL, TX and RX chain along with
++              Signal Detection. On the QCA8327 this should not be enabled, otherwise
++              the SGMII port will not initialize. When used on the QCA8337, revision 3
++              or greater, a warning will be displayed. When the CPU port is set to
++              SGMII on the QCA8337, it is advised to set this unless a communication
++              issue is observed.
++
++        required:
++          - reg
++
++        additionalProperties: false
++
++oneOf:
++  - required:
++      - ports
++  - required:
++      - ethernet-ports
++
++required:
++  - compatible
++  - reg
++
++additionalProperties: true
++
++examples:
++  - |
++    #include <dt-bindings/gpio/gpio.h>
++
++    mdio {
++        #address-cells = <1>;
++        #size-cells = <0>;
++
++        external_phy_port1: ethernet-phy at 0 {
++            reg = <0>;
++        };
++
++        external_phy_port2: ethernet-phy at 1 {
++            reg = <1>;
++        };
++
++        external_phy_port3: ethernet-phy at 2 {
++            reg = <2>;
++        };
++
++        external_phy_port4: ethernet-phy at 3 {
++            reg = <3>;
++        };
++
++        external_phy_port5: ethernet-phy at 4 {
++            reg = <4>;
++        };
++
++        switch at 10 {
++            compatible = "qca,qca8337";
++            #address-cells = <1>;
++            #size-cells = <0>;
++            reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
++            reg = <0x10>;
++
++            ports {
++                #address-cells = <1>;
++                #size-cells = <0>;
++
++                port at 0 {
++                    reg = <0>;
++                    label = "cpu";
++                    ethernet = <&gmac1>;
++                    phy-mode = "rgmii";
++
++                    fixed-link {
++                        speed = <1000>;
++                        full-duplex;
++                    };
++                };
++
++                port at 1 {
++                    reg = <1>;
++                    label = "lan1";
++                    phy-handle = <&external_phy_port1>;
++                };
++
++                port at 2 {
++                    reg = <2>;
++                    label = "lan2";
++                    phy-handle = <&external_phy_port2>;
++                };
++
++                port at 3 {
++                    reg = <3>;
++                    label = "lan3";
++                    phy-handle = <&external_phy_port3>;
++                };
++
++                port at 4 {
++                    reg = <4>;
++                    label = "lan4";
++                    phy-handle = <&external_phy_port4>;
++                };
++
++                port at 5 {
++                    reg = <5>;
++                    label = "wan";
++                    phy-handle = <&external_phy_port5>;
++                };
++            };
++        };
++    };
++  - |
++    #include <dt-bindings/gpio/gpio.h>
++
++    mdio {
++        #address-cells = <1>;
++        #size-cells = <0>;
++
++        switch at 10 {
++            compatible = "qca,qca8337";
++            #address-cells = <1>;
++            #size-cells = <0>;
++            reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
++            reg = <0x10>;
++
++            ports {
++                #address-cells = <1>;
++                #size-cells = <0>;
++
++                port at 0 {
++                    reg = <0>;
++                    label = "cpu";
++                    ethernet = <&gmac1>;
++                    phy-mode = "rgmii";
++
++                    fixed-link {
++                        speed = <1000>;
++                        full-duplex;
++                    };
++                };
++
++                port at 1 {
++                    reg = <1>;
++                    label = "lan1";
++                    phy-mode = "internal";
++                    phy-handle = <&internal_phy_port1>;
++                };
++
++                port at 2 {
++                    reg = <2>;
++                    label = "lan2";
++                    phy-mode = "internal";
++                    phy-handle = <&internal_phy_port2>;
++                };
++
++                port at 3 {
++                    reg = <3>;
++                    label = "lan3";
++                    phy-mode = "internal";
++                    phy-handle = <&internal_phy_port3>;
++                };
++
++                port at 4 {
++                    reg = <4>;
++                    label = "lan4";
++                    phy-mode = "internal";
++                    phy-handle = <&internal_phy_port4>;
++                };
++
++                port at 5 {
++                    reg = <5>;
++                    label = "wan";
++                    phy-mode = "internal";
++                    phy-handle = <&internal_phy_port5>;
++                };
++
++                port at 6 {
++                    reg = <0>;
++                    label = "cpu";
++                    ethernet = <&gmac1>;
++                    phy-mode = "sgmii";
++
++                    qca,sgmii-rxclk-falling-edge;
++
++                    fixed-link {
++                        speed = <1000>;
++                        full-duplex;
++                    };
++                };
++            };
++
++            mdio {
++                #address-cells = <1>;
++                #size-cells = <0>;
++
++                internal_phy_port1: ethernet-phy at 0 {
++                    reg = <0>;
++                };
++
++                internal_phy_port2: ethernet-phy at 1 {
++                    reg = <1>;
++                };
++
++                internal_phy_port3: ethernet-phy at 2 {
++                    reg = <2>;
++                };
++
++                internal_phy_port4: ethernet-phy at 3 {
++                    reg = <3>;
++                };
++
++                internal_phy_port5: ethernet-phy at 4 {
++                    reg = <4>;
++                };
++            };
++        };
++    };



More information about the lede-commits mailing list