From 5ad826f48a4f3c3e08bd1da8c1504a53edd281a0 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Thu, 16 Jun 2022 22:15:13 +0200 Subject: [PATCH] ipq806x: 5.15: replace stmmac pcs fix with upstream version Replace stmmac pcs fix with upstream version. Signed-off-by: Christian Marangi --- ...-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch | 83 ---------- ...mac-add-missing-sgmii-configure-for-.patch | 151 ++++++++++++++++++ ...mac-reset-force-speed-bit-for-ipq806.patch | 110 +++++++++++++ 3 files changed, 261 insertions(+), 83 deletions(-) delete mode 100644 target/linux/ipq806x/patches-5.15/101-dwmac-ipq806x-qsgmii-pcs-all-ch-ctl.patch create mode 100644 target/linux/ipq806x/patches-5.15/101-v6.0-01-net-ethernet-stmmac-add-missing-sgmii-configure-for-.patch create mode 100644 target/linux/ipq806x/patches-5.15/101-v6.0-02-net-ethernet-stmmac-reset-force-speed-bit-for-ipq806.patch 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 +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 +Link: https://lore.kernel.org/r/20220614112228.1998-1-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + 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 + #include + #include ++#include ++#include + + #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 +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 +Co-developed-by: Mark Mentovai +Signed-off-by: Mark Mentovai +Signed-off-by: Christian 'Ansuel' Marangi +Link: https://lore.kernel.org/r/20220614112228.1998-2-ansuelsmth@gmail.com +Signed-off-by: Paolo Abeni +--- + .../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; -- 2.30.2