[openwrt/openwrt] ipq806x: 5.15: replace stmmac pcs fix with upstream version

LEDE Commits lede-commits at lists.infradead.org
Tue Oct 11 12:29:05 PDT 2022


ansuel pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/5ad826f48a4f3c3e08bd1da8c1504a53edd281a0

commit 5ad826f48a4f3c3e08bd1da8c1504a53edd281a0
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Thu Jun 16 22:15:13 2022 +0200

    ipq806x: 5.15: replace stmmac pcs fix with upstream version
    
    Replace stmmac pcs fix with upstream version.
    
    Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
 .../101-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch  |  83 -----------
 ...t-stmmac-add-missing-sgmii-configure-for-.patch | 151 +++++++++++++++++++++
 ...t-stmmac-reset-force-speed-bit-for-ipq806.patch | 110 +++++++++++++++
 3 files changed, 261 insertions(+), 83 deletions(-)

diff --git a/target/linux/ipq806x/patches-5.15/101-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch b/target/linux/ipq806x/patches-5.15/101-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch
deleted file mode 100644
index 2210f4e249..0000000000
--- a/target/linux/ipq806x/patches-5.15/101-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch
+++ /dev/null
@@ -1,83 +0,0 @@
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
-@@ -64,6 +64,17 @@
- #define NSS_COMMON_CLK_DIV_SGMII_100		4
- #define NSS_COMMON_CLK_DIV_SGMII_10		49
- 
-+#define QSGMII_PCS_ALL_CH_CTL			0x80
-+#define QSGMII_PCS_CH_SPEED_FORCE		0x2
-+#define QSGMII_PCS_CH_SPEED_10			0x0
-+#define QSGMII_PCS_CH_SPEED_100			0x4
-+#define QSGMII_PCS_CH_SPEED_1000		0x8
-+#define QSGMII_PCS_CH_SPEED_MASK		(QSGMII_PCS_CH_SPEED_FORCE | \
-+						 QSGMII_PCS_CH_SPEED_10 | \
-+						 QSGMII_PCS_CH_SPEED_100 | \
-+						 QSGMII_PCS_CH_SPEED_1000)
-+#define QSGMII_PCS_CH_SPEED_SHIFT(x)		(x * 4)
-+
- #define QSGMII_PCS_CAL_LCKDT_CTL		0x120
- #define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
- 
-@@ -242,6 +253,36 @@ static void ipq806x_gmac_fix_mac_speed(v
- 	ipq806x_gmac_set_speed(gmac, speed);
- }
- 
-+static int
-+ipq806x_gmac_get_qsgmii_pcs_speed_val(struct platform_device *pdev) {
-+	struct device_node *fixed_link_node;
-+	int rv;
-+	int fixed_link_speed;
-+
-+	if (!of_phy_is_fixed_link(pdev->dev.of_node))
-+		return 0;
-+
-+	fixed_link_node = of_get_child_by_name(pdev->dev.of_node, "fixed-link");
-+	if (!fixed_link_node)
-+		return -1;
-+
-+	rv = of_property_read_u32(fixed_link_node, "speed", &fixed_link_speed);
-+	of_node_put(fixed_link_node);
-+	if (rv)
-+		return -1;
-+
-+	switch (fixed_link_speed) {
-+	case SPEED_1000:
-+		return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_1000;
-+	case SPEED_100:
-+		return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_100;
-+	case SPEED_10:
-+		return QSGMII_PCS_CH_SPEED_FORCE | QSGMII_PCS_CH_SPEED_10;
-+	}
-+
-+	return -1;
-+}
-+
- static int ipq806x_gmac_probe(struct platform_device *pdev)
- {
- 	struct plat_stmmacenet_data *plat_dat;
-@@ -250,6 +291,7 @@ static int ipq806x_gmac_probe(struct pla
- 	struct ipq806x_gmac *gmac;
- 	int val;
- 	int err;
-+	int qsgmii_pcs_speed;
- 
- 	val = stmmac_get_platform_resources(pdev, &stmmac_res);
- 	if (val)
-@@ -339,6 +381,17 @@ static int ipq806x_gmac_probe(struct pla
- 			     0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
- 			     0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
- 			     0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
-+
-+		qsgmii_pcs_speed = ipq806x_gmac_get_qsgmii_pcs_speed_val(pdev);
-+		if (qsgmii_pcs_speed != -1) {
-+			regmap_update_bits(
-+			    gmac->qsgmii_csr,
-+			    QSGMII_PCS_ALL_CH_CTL,
-+			    QSGMII_PCS_CH_SPEED_MASK <<
-+				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id),
-+			    qsgmii_pcs_speed <<
-+				QSGMII_PCS_CH_SPEED_SHIFT(gmac->id));
-+		}
- 	}
- 
- 	plat_dat->has_gmac = true;
diff --git a/target/linux/ipq806x/patches-5.15/101-v6.0-01-net-ethernet-stmmac-add-missing-sgmii-configure-for-.patch b/target/linux/ipq806x/patches-5.15/101-v6.0-01-net-ethernet-stmmac-add-missing-sgmii-configure-for-.patch
new file mode 100644
index 0000000000..bd492ca1ec
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.15/101-v6.0-01-net-ethernet-stmmac-add-missing-sgmii-configure-for-.patch
@@ -0,0 +1,151 @@
+From 9ec092d2feb69045dd289845024301fb91c064ee Mon Sep 17 00:00:00 2001
+From: Christian 'Ansuel' Marangi <ansuelsmth at gmail.com>
+Date: Tue, 14 Jun 2022 13:22:27 +0200
+Subject: [PATCH 1/2] net: ethernet: stmmac: add missing sgmii configure for
+ ipq806x
+
+The different gmacid require different configuration based on the soc
+and on the gmac id. Add these missing configuration taken from the
+original driver.
+
+Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth at gmail.com>
+Link: https://lore.kernel.org/r/20220614112228.1998-1-ansuelsmth@gmail.com
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/ethernet/stmicro/stmmac/Kconfig   |  1 +
+ .../ethernet/stmicro/stmmac/dwmac-ipq806x.c   | 93 +++++++++++++++----
+ 2 files changed, 78 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -83,6 +83,7 @@ config DWMAC_IPQ806X
+ 	default ARCH_QCOM
+ 	depends on OF && (ARCH_QCOM || COMPILE_TEST)
+ 	select MFD_SYSCON
++	select QCOM_SOCINFO
+ 	help
+ 	  Support for QCA IPQ806X DWMAC Ethernet.
+ 
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+@@ -27,6 +27,8 @@
+ #include <linux/stmmac.h>
+ #include <linux/of_mdio.h>
+ #include <linux/module.h>
++#include <linux/sys_soc.h>
++#include <linux/bitfield.h>
+ 
+ #include "stmmac_platform.h"
+ 
+@@ -75,11 +77,20 @@
+ #define QSGMII_PHY_RX_SIGNAL_DETECT_EN		BIT(2)
+ #define QSGMII_PHY_TX_DRIVER_EN			BIT(3)
+ #define QSGMII_PHY_QSGMII_EN			BIT(7)
+-#define QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET	12
+-#define QSGMII_PHY_RX_DC_BIAS_OFFSET		18
+-#define QSGMII_PHY_RX_INPUT_EQU_OFFSET		20
+-#define QSGMII_PHY_CDR_PI_SLEW_OFFSET		22
+-#define QSGMII_PHY_TX_DRV_AMP_OFFSET		28
++#define QSGMII_PHY_DEEMPHASIS_LVL_MASK		GENMASK(11, 10)
++#define QSGMII_PHY_DEEMPHASIS_LVL(x)		FIELD_PREP(QSGMII_PHY_DEEMPHASIS_LVL_MASK, (x))
++#define QSGMII_PHY_PHASE_LOOP_GAIN_MASK		GENMASK(14, 12)
++#define QSGMII_PHY_PHASE_LOOP_GAIN(x)		FIELD_PREP(QSGMII_PHY_PHASE_LOOP_GAIN_MASK, (x))
++#define QSGMII_PHY_RX_DC_BIAS_MASK		GENMASK(19, 18)
++#define QSGMII_PHY_RX_DC_BIAS(x)		FIELD_PREP(QSGMII_PHY_RX_DC_BIAS_MASK, (x))
++#define QSGMII_PHY_RX_INPUT_EQU_MASK		GENMASK(21, 20)
++#define QSGMII_PHY_RX_INPUT_EQU(x)		FIELD_PREP(QSGMII_PHY_RX_INPUT_EQU_MASK, (x))
++#define QSGMII_PHY_CDR_PI_SLEW_MASK		GENMASK(23, 22)
++#define QSGMII_PHY_CDR_PI_SLEW(x)		FIELD_PREP(QSGMII_PHY_CDR_PI_SLEW_MASK, (x))
++#define QSGMII_PHY_TX_SLEW_MASK			GENMASK(27, 26)
++#define QSGMII_PHY_TX_SLEW(x)			FIELD_PREP(QSGMII_PHY_TX_SLEW_MASK, (x))
++#define QSGMII_PHY_TX_DRV_AMP_MASK		GENMASK(31, 28)
++#define QSGMII_PHY_TX_DRV_AMP(x)		FIELD_PREP(QSGMII_PHY_TX_DRV_AMP_MASK, (x))
+ 
+ struct ipq806x_gmac {
+ 	struct platform_device *pdev;
+@@ -242,6 +253,64 @@ static void ipq806x_gmac_fix_mac_speed(v
+ 	ipq806x_gmac_set_speed(gmac, speed);
+ }
+ 
++static const struct soc_device_attribute ipq806x_gmac_soc_v1[] = {
++	{
++		.revision = "1.*",
++	},
++	{
++		/* sentinel */
++	}
++};
++
++static int
++ipq806x_gmac_configure_qsgmii_params(struct ipq806x_gmac *gmac)
++{
++	struct platform_device *pdev = gmac->pdev;
++	const struct soc_device_attribute *soc;
++	struct device *dev = &pdev->dev;
++	u32 qsgmii_param;
++
++	switch (gmac->id) {
++	case 1:
++		soc = soc_device_match(ipq806x_gmac_soc_v1);
++
++		if (soc)
++			qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xc) |
++				       QSGMII_PHY_TX_SLEW(0x2) |
++				       QSGMII_PHY_DEEMPHASIS_LVL(0x2);
++		else
++			qsgmii_param = QSGMII_PHY_TX_DRV_AMP(0xd) |
++				       QSGMII_PHY_TX_SLEW(0x0) |
++				       QSGMII_PHY_DEEMPHASIS_LVL(0x0);
++
++		qsgmii_param |= QSGMII_PHY_RX_DC_BIAS(0x2);
++		break;
++	case 2:
++	case 3:
++		qsgmii_param = QSGMII_PHY_RX_DC_BIAS(0x3) |
++			       QSGMII_PHY_TX_DRV_AMP(0xc);
++		break;
++	default: /* gmac 0 can't be set in SGMII mode */
++		dev_err(dev, "gmac id %d can't be in SGMII mode", gmac->id);
++		return -EINVAL;
++	}
++
++	/* Common params across all gmac id */
++	qsgmii_param |= QSGMII_PHY_CDR_EN |
++			QSGMII_PHY_RX_FRONT_EN |
++			QSGMII_PHY_RX_SIGNAL_DETECT_EN |
++			QSGMII_PHY_TX_DRIVER_EN |
++			QSGMII_PHY_QSGMII_EN |
++			QSGMII_PHY_PHASE_LOOP_GAIN(0x4) |
++			QSGMII_PHY_RX_INPUT_EQU(0x1) |
++			QSGMII_PHY_CDR_PI_SLEW(0x2);
++
++	regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
++		     qsgmii_param);
++
++	return 0;
++}
++
+ static int ipq806x_gmac_probe(struct platform_device *pdev)
+ {
+ 	struct plat_stmmacenet_data *plat_dat;
+@@ -328,17 +397,9 @@ static int ipq806x_gmac_probe(struct pla
+ 	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
+ 
+ 	if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+-		regmap_write(gmac->qsgmii_csr, QSGMII_PHY_SGMII_CTL(gmac->id),
+-			     QSGMII_PHY_CDR_EN |
+-			     QSGMII_PHY_RX_FRONT_EN |
+-			     QSGMII_PHY_RX_SIGNAL_DETECT_EN |
+-			     QSGMII_PHY_TX_DRIVER_EN |
+-			     QSGMII_PHY_QSGMII_EN |
+-			     0x4ul << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET |
+-			     0x3ul << QSGMII_PHY_RX_DC_BIAS_OFFSET |
+-			     0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET |
+-			     0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET |
+-			     0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET);
++		err = ipq806x_gmac_configure_qsgmii_params(gmac);
++		if (err)
++			goto err_remove_config_dt;
+ 	}
+ 
+ 	plat_dat->has_gmac = true;
diff --git a/target/linux/ipq806x/patches-5.15/101-v6.0-02-net-ethernet-stmmac-reset-force-speed-bit-for-ipq806.patch b/target/linux/ipq806x/patches-5.15/101-v6.0-02-net-ethernet-stmmac-reset-force-speed-bit-for-ipq806.patch
new file mode 100644
index 0000000000..d444553452
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.15/101-v6.0-02-net-ethernet-stmmac-reset-force-speed-bit-for-ipq806.patch
@@ -0,0 +1,110 @@
+From 8bca458990dd8c6d001b2fb52063aa18e8ca7444 Mon Sep 17 00:00:00 2001
+From: Christian 'Ansuel' Marangi <ansuelsmth at gmail.com>
+Date: Tue, 14 Jun 2022 13:22:28 +0200
+Subject: [PATCH 2/2] net: ethernet: stmmac: reset force speed bit for ipq806x
+
+Some bootloader may set the force speed regs even if the actual
+interface should use autonegotiation between PCS and PHY.
+This cause the complete malfuction of the interface.
+
+To fix this correctly reset the force speed regs if a fixed-link is not
+defined in the DTS. With a fixed-link node correctly configure the
+forced speed regs to handle any misconfiguration by the bootloader.
+
+Reported-by: Mark Mentovai <mark at moxienet.com>
+Co-developed-by: Mark Mentovai <mark at moxienet.com>
+Signed-off-by: Mark Mentovai <mark at moxienet.com>
+Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth at gmail.com>
+Link: https://lore.kernel.org/r/20220614112228.1998-2-ansuelsmth@gmail.com
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ .../ethernet/stmicro/stmmac/dwmac-ipq806x.c   | 64 +++++++++++++++++++
+ 1 file changed, 64 insertions(+)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+@@ -66,6 +66,17 @@
+ #define NSS_COMMON_CLK_DIV_SGMII_100		4
+ #define NSS_COMMON_CLK_DIV_SGMII_10		49
+ 
++#define QSGMII_PCS_ALL_CH_CTL			0x80
++#define QSGMII_PCS_CH_SPEED_FORCE		BIT(1)
++#define QSGMII_PCS_CH_SPEED_10			0x0
++#define QSGMII_PCS_CH_SPEED_100			BIT(2)
++#define QSGMII_PCS_CH_SPEED_1000		BIT(3)
++#define QSGMII_PCS_CH_SPEED_MASK		(QSGMII_PCS_CH_SPEED_FORCE | \
++						 QSGMII_PCS_CH_SPEED_10 | \
++						 QSGMII_PCS_CH_SPEED_100 | \
++						 QSGMII_PCS_CH_SPEED_1000)
++#define QSGMII_PCS_CH_SPEED_SHIFT(x)		((x) * 4)
++
+ #define QSGMII_PCS_CAL_LCKDT_CTL		0x120
+ #define QSGMII_PCS_CAL_LCKDT_CTL_RST		BIT(19)
+ 
+@@ -253,6 +264,55 @@ static void ipq806x_gmac_fix_mac_speed(v
+ 	ipq806x_gmac_set_speed(gmac, speed);
+ }
+ 
++static int
++ipq806x_gmac_configure_qsgmii_pcs_speed(struct ipq806x_gmac *gmac)
++{
++	struct platform_device *pdev = gmac->pdev;
++	struct device *dev = &pdev->dev;
++	struct device_node *dn;
++	int link_speed;
++	int val = 0;
++	int ret;
++
++	/* Some bootloader may apply wrong configuration and cause
++	 * not functioning port. If fixed link is not set,
++	 * reset the force speed bit.
++	 */
++	if (!of_phy_is_fixed_link(pdev->dev.of_node))
++		goto write;
++
++	dn = of_get_child_by_name(pdev->dev.of_node, "fixed-link");
++	ret = of_property_read_u32(dn, "speed", &link_speed);
++	of_node_put(dn);
++	if (ret) {
++		dev_err(dev, "found fixed-link node with no speed");
++		return ret;
++	}
++
++	val = QSGMII_PCS_CH_SPEED_FORCE;
++
++	switch (link_speed) {
++	case SPEED_1000:
++		val |= QSGMII_PCS_CH_SPEED_1000;
++		break;
++	case SPEED_100:
++		val |= QSGMII_PCS_CH_SPEED_100;
++		break;
++	case SPEED_10:
++		val |= QSGMII_PCS_CH_SPEED_10;
++		break;
++	}
++
++write:
++	regmap_update_bits(gmac->qsgmii_csr, QSGMII_PCS_ALL_CH_CTL,
++			   QSGMII_PCS_CH_SPEED_MASK <<
++			   QSGMII_PCS_CH_SPEED_SHIFT(gmac->id),
++			   val <<
++			   QSGMII_PCS_CH_SPEED_SHIFT(gmac->id));
++
++	return 0;
++}
++
+ static const struct soc_device_attribute ipq806x_gmac_soc_v1[] = {
+ 	{
+ 		.revision = "1.*",
+@@ -400,6 +460,10 @@ static int ipq806x_gmac_probe(struct pla
+ 		err = ipq806x_gmac_configure_qsgmii_params(gmac);
+ 		if (err)
+ 			goto err_remove_config_dt;
++
++		err = ipq806x_gmac_configure_qsgmii_pcs_speed(gmac);
++		if (err)
++			goto err_remove_config_dt;
+ 	}
+ 
+ 	plat_dat->has_gmac = true;




More information about the lede-commits mailing list