From 95bd7a76a138d533c9b6b37bf91c4a006d94b22f Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Thu, 6 Nov 2025 21:52:11 -0600 Subject: [PATCH] qualcommbe: update ipq9574 PCS driver Update the ipq9574 PCS driver the version provided by Qualcomm via github. The updated driver simplifies link up handling by removing unnecessary clock rate changes. Signed-off-by: Alexandru Gagniuc Link: https://github.com/openwrt/openwrt/pull/20993 Signed-off-by: Robert Marko --- ...9574-Add-PCS-instantiation-and-phyli.patch | 17 +- ...9574-remove-neg_mode-argument-from-i.patch | 29 -- ...9574-delay-mii-clock-probing-until-i.patch | 82 ---- ...9574-add-changes-not-submitted-upstr.patch | 362 ------------------ ...ts-qcom-ipq9574-add-PCS-uniphy-nodes.patch | 30 +- ...ASER-interface-mode-support-to-IPQ-U.patch | 94 ++--- ...BASEX-interface-mode-support-to-IPQ-.patch | 130 +++---- ...BASEX-interface-mode-support-to-IPQ-.patch | 71 ++-- ...QXGMII-interface-mode-support-to-IPQ.patch | 224 +++++------ ...hy-control-MISC2-register-for-2.5G-s.patch | 42 +- ...hy-keep-autoneg-enabled-in-SGMII-mod.patch | 25 -- ...q-uniphy-fix-USXGMII-link-up-failure.patch | 4 +- ...om-ipq9574-Update-IPQ9574-PCS-driver.patch | 282 ++++++++++++++ 13 files changed, 557 insertions(+), 835 deletions(-) delete mode 100644 target/linux/qualcommbe/patches-6.12/0319-net-pcs-qcom-ipq9574-remove-neg_mode-argument-from-i.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0320-net-pcs-qcom-ipq9574-delay-mii-clock-probing-until-i.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0321-net-pcs-qcom-ipq9574-add-changes-not-submitted-upstr.patch delete mode 100644 target/linux/qualcommbe/patches-6.12/0366-net-pcs-ipq-uniphy-keep-autoneg-enabled-in-SGMII-mod.patch create mode 100644 target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch diff --git a/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch b/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch index 1e7453a35c..7d071c2e25 100644 --- a/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch +++ b/target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch @@ -1,4 +1,4 @@ -From 240ae5e0ca2ed858e25d7da6d5291d9c1f2c660a Mon Sep 17 00:00:00 2001 +From 10b609ddbf4d369c80098efa39451ef3973759b5 Mon Sep 17 00:00:00 2001 From: Lei Wei Date: Fri, 7 Feb 2025 23:53:14 +0800 Subject: [PATCH] net: pcs: qcom-ipq9574: Add PCS instantiation and phylink @@ -14,10 +14,12 @@ MAC. c.) PCS phylink operations for SGMII/QSGMII interface modes. Signed-off-by: Lei Wei +Alex G: remove phylink_pcs .neg_mode boolean +Signed-off-by: Alexandru Gagniuc --- - drivers/net/pcs/pcs-qcom-ipq9574.c | 469 +++++++++++++++++++++++++++ + drivers/net/pcs/pcs-qcom-ipq9574.c | 468 +++++++++++++++++++++++++++ include/linux/pcs/pcs-qcom-ipq9574.h | 15 + - 2 files changed, 484 insertions(+) + 2 files changed, 483 insertions(+) create mode 100644 include/linux/pcs/pcs-qcom-ipq9574.h --- a/drivers/net/pcs/pcs-qcom-ipq9574.c @@ -88,7 +90,7 @@ Signed-off-by: Lei Wei /* PCS private data */ struct ipq_pcs { struct device *dev; -@@ -31,8 +77,359 @@ struct ipq_pcs { +@@ -31,8 +77,358 @@ struct ipq_pcs { struct clk_hw rx_hw; /* TX clock supplied to NSSCC */ struct clk_hw tx_hw; @@ -310,7 +312,7 @@ Signed-off-by: Lei Wei + clk_disable_unprepare(qpcs_mii->tx_clk); +} + -+static void ipq_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, ++static void ipq_pcs_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) +{ + struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); @@ -422,7 +424,6 @@ Signed-off-by: Lei Wei + qpcs_mii->qpcs = qpcs; + qpcs_mii->index = index; + qpcs_mii->pcs.ops = &ipq_pcs_phylink_ops; -+ qpcs_mii->pcs.neg_mode = true; + qpcs_mii->pcs.poll = true; + + qpcs_mii->rx_clk = devm_get_clk_from_child(dev, mii_np, "rx"); @@ -448,7 +449,7 @@ Signed-off-by: Lei Wei static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) { switch (qpcs->interface) { -@@ -219,6 +616,10 @@ static int ipq9574_pcs_probe(struct plat +@@ -219,6 +615,10 @@ static int ipq9574_pcs_probe(struct plat if (ret) return ret; @@ -459,7 +460,7 @@ Signed-off-by: Lei Wei platform_set_drvdata(pdev, qpcs); return 0; -@@ -230,6 +631,74 @@ static const struct of_device_id ipq9574 +@@ -230,6 +630,74 @@ static const struct of_device_id ipq9574 }; MODULE_DEVICE_TABLE(of, ipq9574_pcs_of_mtable); diff --git a/target/linux/qualcommbe/patches-6.12/0319-net-pcs-qcom-ipq9574-remove-neg_mode-argument-from-i.patch b/target/linux/qualcommbe/patches-6.12/0319-net-pcs-qcom-ipq9574-remove-neg_mode-argument-from-i.patch deleted file mode 100644 index 6fc9652f08..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0319-net-pcs-qcom-ipq9574-remove-neg_mode-argument-from-i.patch +++ /dev/null @@ -1,29 +0,0 @@ -From ffe2a80fb76ccdc1781f817f6bbc9a8aa919816e Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Mon, 12 May 2025 09:11:05 -0500 -Subject: [PATCH] net: pcs: qcom-ipq9574: remove "neg_mode" argument from - ipq_pcs_get_state - -Since commit c6739623c91bb ("net: phylink: pass neg_mode into -.pcs_get_state() method"), the "neg_mode" parameter is part of the -argument list of .pcs_get_state(). This is available starting with -v6.14. However, we want to use the backported IPQ9574 driver on v6.12. -Remove this parameter from ipq_pcs_get_state(), as it is not part of -.pcs_get_state() in v6.12. - -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -457,7 +457,7 @@ static void ipq_pcs_disable(struct phyli - clk_disable_unprepare(qpcs_mii->tx_clk); - } - --static void ipq_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, -+static void ipq_pcs_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) - { - struct ipq_pcs_mii *qpcs_mii = phylink_pcs_to_qpcs_mii(pcs); diff --git a/target/linux/qualcommbe/patches-6.12/0320-net-pcs-qcom-ipq9574-delay-mii-clock-probing-until-i.patch b/target/linux/qualcommbe/patches-6.12/0320-net-pcs-qcom-ipq9574-delay-mii-clock-probing-until-i.patch deleted file mode 100644 index ac4c44a720..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0320-net-pcs-qcom-ipq9574-delay-mii-clock-probing-until-i.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 5b2f02ccca7b9496f0a8da6ade063b82810c75e7 Mon Sep 17 00:00:00 2001 -From: Alexandru Gagniuc -Date: Mon, 12 May 2025 09:27:17 -0500 -Subject: [PATCH] net: pcs: qcom-ipq9574: delay mii clock probing until - ipq_pcs_get() - -NSSCC generates the SYS and AHB clocks for the PCS block The PCS then -feeds the uniphy clocks back to the NSSCC, which are in turn, used to -feed the PCS MII clocks. This works fine in hardware: - - GCC -> NSSCC -> PCS -> NSSCC -> PCS(MII) - -However, when the PCS MII clocks are probed within the .probe() of -the PCS block, it creates a circular dependency. The MII clocks depend -on the uniphy clocks, which depend on the PCS block being probed. -Since we are in the process of probing the PCS block, this results in -both blocks returning with -EPROBE_DEFER: - - platform 39b00000.clock-controller: deferred probe pending: platform: supplier 7a00000.ethernet-pcs not ready - mdio_bus 90000.mdio-1:18: deferred probe pending: mdio_bus: supplier 7a20000.ethernet-pcs not ready - mdio_bus 90000.mdio-1:00: deferred probe pending: mdio_bus: supplier 90000.mdio-1:18 not ready - mdio_bus 90000.mdio-1:01: deferred probe pending: mdio_bus: supplier 90000.mdio-1:18 not ready - mdio_bus 90000.mdio-1:02: deferred probe pending: mdio_bus: supplier 90000.mdio-1:18 not ready - mdio_bus 90000.mdio-1:03: deferred probe pending: mdio_bus: supplier 90000.mdio-1:18 not ready - platform 7a00000.ethernet-pcs: deferred probe pending: ipq9574_pcs: Failed to get MII 0 RX clock - platform 7a20000.ethernet-pcs: deferred probe pending: ipq9574_pcs: Failed to get MII 0 RX clock - platform 3a000000.qcom-ppe: deferred probe pending: platform: supplier 39b00000.clock-controller not ready - -To break this dependency, let the PCS block probe, and only probe the -PCS MII clocks from ipq_pcs_get(). - -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 30 ++++++++++++++++-------------- - 1 file changed, 16 insertions(+), 14 deletions(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -580,20 +580,6 @@ static int ipq_pcs_create_miis(struct ip - qpcs_mii->pcs.neg_mode = true; - qpcs_mii->pcs.poll = true; - -- qpcs_mii->rx_clk = devm_get_clk_from_child(dev, mii_np, "rx"); -- if (IS_ERR(qpcs_mii->rx_clk)) { -- of_node_put(mii_np); -- return dev_err_probe(dev, PTR_ERR(qpcs_mii->rx_clk), -- "Failed to get MII %d RX clock\n", index); -- } -- -- qpcs_mii->tx_clk = devm_get_clk_from_child(dev, mii_np, "tx"); -- if (IS_ERR(qpcs_mii->tx_clk)) { -- of_node_put(mii_np); -- return dev_err_probe(dev, PTR_ERR(qpcs_mii->tx_clk), -- "Failed to get MII %d TX clock\n", index); -- } -- - qpcs->qpcs_mii[index] = qpcs_mii; - } - -@@ -848,6 +834,22 @@ struct phylink_pcs *ipq_pcs_get(struct d - return ERR_PTR(-ENOENT); - } - -+ qpcs_mii->rx_clk = devm_get_clk_from_child(&pdev->dev, np, "rx"); -+ if (IS_ERR(qpcs_mii->rx_clk)) { -+ put_device(&pdev->dev); -+ return dev_err_ptr_probe(&pdev->dev, PTR_ERR(qpcs_mii->rx_clk), -+ "Failed to get MII %d RX clock\n", -+ index); -+ } -+ -+ qpcs_mii->tx_clk = devm_get_clk_from_child(&pdev->dev, np, "tx"); -+ if (IS_ERR(qpcs_mii->tx_clk)) { -+ put_device(&pdev->dev); -+ return dev_err_ptr_probe(&pdev->dev, PTR_ERR(qpcs_mii->tx_clk), -+ "Failed to get MII %d TX clock\n", -+ index); -+ } -+ - return &qpcs_mii->pcs; - } - EXPORT_SYMBOL(ipq_pcs_get); diff --git a/target/linux/qualcommbe/patches-6.12/0321-net-pcs-qcom-ipq9574-add-changes-not-submitted-upstr.patch b/target/linux/qualcommbe/patches-6.12/0321-net-pcs-qcom-ipq9574-add-changes-not-submitted-upstr.patch deleted file mode 100644 index 64a5bf6229..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0321-net-pcs-qcom-ipq9574-add-changes-not-submitted-upstr.patch +++ /dev/null @@ -1,362 +0,0 @@ -From 7de372abe7a4b5b380fdbeedd268445f234990c8 Mon Sep 17 00:00:00 2001 -From: Lei Wei -Date: Mon, 29 Jan 2024 11:39:36 +0800 -Subject: [PATCH] net: pcs: qcom-ipq9574: add changes not submitted upstream - -Was ("net: pcs: Add driver for Qualcomm IPQ UNIPHY PCS"). - -The UNIPHY hardware block in Qualcomm's IPQ SoC based boards enables -PCS and XPCS functions, and helps in interfacing the Ethernet MAC in -IPQ SoC to external PHYs. - -This patch adds the PCS driver support for the UNIPHY hardware used in -IPQ SoC based boards. Support for SGMII/QSGMII/PSGMII and USXGMII -interface modes are added in the driver. - -Change-Id: Id2c8f993f121098f7b02186b53770b75bb539a93 -Signed-off-by: Lei Wei -Alex G: Rebase original patch on top of 20250207 uniphy submission - Remove mutex that is not required according to - https://lore.kernel.org/lkml/Z3ZwURgIErzpzpEr@shell.armlinux.org.uk/ -Signed-off-by: Alexandru Gagniuc ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 180 +++++++++++++++++++++++- - include/linux/pcs/pcs-qcom-ipq-uniphy.h | 13 ++ - 2 files changed, 192 insertions(+), 1 deletion(-) - create mode 100644 include/linux/pcs/pcs-qcom-ipq-uniphy.h - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -9,10 +9,12 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include - - #include - -@@ -26,6 +28,7 @@ - #define PCS_MODE_SEL_MASK GENMASK(12, 8) - #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) - #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) -+#define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2) - #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) - - #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) -@@ -43,6 +46,8 @@ - #define PCS_MII_STS_SPEED_10 0 - #define PCS_MII_STS_SPEED_100 1 - #define PCS_MII_STS_SPEED_1000 2 -+#define PCS_MII_STS_PAUSE_TX_EN BIT(1) -+#define PCS_MII_STS_PAUSE_RX_EN BIT(0) - - #define PCS_PLL_RESET 0x780 - #define PCS_ANA_SW_RESET BIT(6) -@@ -95,12 +100,35 @@ struct ipq_pcs_mii { - struct clk *tx_clk; - }; - -+/* UNIPHY PCS reset ID */ -+enum { -+ PCS_SYS_RESET, -+ PCS_AHB_RESET, -+ XPCS_RESET, -+ PCS_RESET_MAX -+}; -+ -+/* UNIPHY PCS reset name */ -+static const char *const pcs_reset_name[PCS_RESET_MAX] = { -+ "sys", -+ "ahb", -+ "xpcs", -+}; -+ -+/* UNIPHY PCS channel clock ID */ -+enum { -+ PCS_CH_RX_CLK, -+ PCS_CH_TX_CLK, -+ PCS_CH_CLK_MAX -+}; -+ - /* PCS private data */ - struct ipq_pcs { - struct device *dev; - void __iomem *base; - struct regmap *regmap; - phy_interface_t interface; -+ struct reset_control *reset[PCS_RESET_MAX]; - - /* RX clock supplied to NSSCC */ - struct clk_hw rx_hw; -@@ -150,6 +178,11 @@ static void ipq_pcs_get_state_sgmii(stru - state->duplex = DUPLEX_FULL; - else - state->duplex = DUPLEX_HALF; -+ -+ if (val & PCS_MII_STS_PAUSE_TX_EN) -+ state->pause |= MLO_PAUSE_TX; -+ if (val & PCS_MII_STS_PAUSE_RX_EN) -+ state->pause |= MLO_PAUSE_RX; - } - - static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, -@@ -203,6 +236,9 @@ static int ipq_pcs_config_mode(struct ip - unsigned int val; - int ret; - -+ /* Assert XPCS reset */ -+ reset_control_assert(qpcs->reset[XPCS_RESET]); -+ - /* Configure PCS interface mode */ - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: -@@ -211,11 +247,16 @@ static int ipq_pcs_config_mode(struct ip - case PHY_INTERFACE_MODE_QSGMII: - val = PCS_MODE_QSGMII; - break; -+ case PHY_INTERFACE_MODE_PSGMII: -+ val = PCS_MODE_PSGMII; -+ break; - case PHY_INTERFACE_MODE_USXGMII: - val = PCS_MODE_XPCS; - rate = 312500000; - break; - default: -+ dev_err(qpcs->dev, -+ "interface %s not supported\n", phy_modes(interface)); - return -EOPNOTSUPP; - } - -@@ -300,6 +341,9 @@ static int ipq_pcs_config_usxgmii(struct - if (ret) - return ret; - -+ /* Deassert XPCS and configure XPCS USXGMII */ -+ reset_control_deassert(qpcs->reset[XPCS_RESET]); -+ - ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); - if (ret) - return ret; -@@ -311,6 +355,91 @@ static int ipq_pcs_config_usxgmii(struct - return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); - } - -+static unsigned long ipq_unipcs_clock_rate_get_gmii(int speed) -+{ -+ unsigned long rate = 0; -+ -+ switch (speed) { -+ case SPEED_1000: -+ rate = 125000000; -+ break; -+ case SPEED_100: -+ rate = 25000000; -+ break; -+ case SPEED_10: -+ rate = 2500000; -+ break; -+ default: -+ break; -+ } -+ -+ return rate; -+} -+ -+static unsigned long ipq_unipcs_clock_rate_get_xgmii(int speed) -+{ -+ unsigned long rate = 0; -+ -+ switch (speed) { -+ case SPEED_10000: -+ rate = 312500000; -+ break; -+ case SPEED_5000: -+ rate = 156250000; -+ break; -+ case SPEED_2500: -+ rate = 78125000; -+ break; -+ case SPEED_1000: -+ rate = 125000000; -+ break; -+ case SPEED_100: -+ rate = 12500000; -+ break; -+ case SPEED_10: -+ rate = 1250000; -+ break; -+ default: -+ break; -+ } -+ -+ return rate; -+} -+ -+static void -+ipq_unipcs_link_up_clock_rate_set(struct ipq_pcs_mii *qunipcs_ch, -+ phy_interface_t interface, -+ int speed) -+{ -+ struct ipq_pcs *qpcs = qunipcs_ch->qpcs; -+ unsigned long rate = 0; -+ -+ switch (interface) { -+ case PHY_INTERFACE_MODE_SGMII: -+ case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: -+ rate = ipq_unipcs_clock_rate_get_gmii(speed); -+ break; -+ case PHY_INTERFACE_MODE_USXGMII: -+ rate = ipq_unipcs_clock_rate_get_xgmii(speed); -+ break; -+ default: -+ dev_err(qpcs->dev, -+ "interface %s not supported\n", phy_modes(interface)); -+ return; -+ } -+ -+ if (rate == 0) { -+ dev_err(qpcs->dev, "Invalid PCS clock rate\n"); -+ return; -+ } -+ -+ clk_set_rate(qunipcs_ch->rx_clk, rate); -+ clk_set_rate(qunipcs_ch->tx_clk, rate); -+ -+ fsleep(10000); -+} -+ - static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, - int index, - unsigned int neg_mode, -@@ -467,6 +596,7 @@ static void ipq_pcs_get_state(struct phy - switch (state->interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - ipq_pcs_get_state_sgmii(qpcs, index, state); - break; - case PHY_INTERFACE_MODE_USXGMII: -@@ -497,10 +627,13 @@ static int ipq_pcs_config(struct phylink - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); - case PHY_INTERFACE_MODE_USXGMII: - return ipq_pcs_config_usxgmii(qpcs); - default: -+ dev_err(qpcs->dev, -+ "interface %s not supported\n", phy_modes(interface)); - return -EOPNOTSUPP; - }; - } -@@ -515,9 +648,14 @@ static void ipq_pcs_link_up(struct phyli - int index = qpcs_mii->index; - int ret; - -+ /* Configure PCS channel interface clock rate */ -+ ipq_unipcs_link_up_clock_rate_set(qpcs_mii, interface, speed); -+ -+ /* Configure PCS speed and reset PCS adapter */ - switch (interface) { - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_QSGMII: -+ case PHY_INTERFACE_MODE_PSGMII: - ret = ipq_pcs_link_up_config_sgmii(qpcs, index, - neg_mode, speed); - break; -@@ -525,6 +663,8 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); - break; - default: -+ dev_err(qpcs->dev, -+ "interface %s not supported\n", phy_modes(interface)); - return; - } - -@@ -735,12 +875,38 @@ static const struct regmap_config ipq_pc - .fast_io = true, - }; - -+/** -+ * ipq_unipcs_create() - Create Qualcomm IPQ UNIPHY PCS -+ * @np: Device tree node to the PCS -+ * -+ * Description: Create a phylink PCS instance for a PCS node @np. -+ * -+ * Return: A pointer to the phylink PCS instance or an error-pointer value. -+ */ -+struct phylink_pcs *ipq_unipcs_create(struct device_node *np) -+{ -+ return ipq_pcs_get(np); -+} -+EXPORT_SYMBOL(ipq_unipcs_create); -+ -+/** -+ * ipq_unipcs_destroy() - Destroy Qualcomm IPQ UNIPHY PCS -+ * @pcs: PCS instance -+ * -+ * Description: Destroy a phylink PCS instance. -+ */ -+void ipq_unipcs_destroy(struct phylink_pcs *pcs) -+{ -+ ipq_pcs_put(pcs); -+} -+EXPORT_SYMBOL(ipq_unipcs_destroy); -+ - static int ipq9574_pcs_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - struct ipq_pcs *qpcs; - struct clk *clk; -- int ret; -+ int i, ret; - - qpcs = devm_kzalloc(dev, sizeof(*qpcs), GFP_KERNEL); - if (!qpcs) -@@ -762,11 +928,23 @@ static int ipq9574_pcs_probe(struct plat - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "Failed to enable SYS clock\n"); -+ clk_set_rate(clk, 24000000); - - clk = devm_clk_get_enabled(dev, "ahb"); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "Failed to enable AHB clock\n"); -+ clk_set_rate(clk, 100000000); -+ -+ for (i = 0; i < PCS_RESET_MAX; i++) { -+ qpcs->reset[i] = -+ devm_reset_control_get_optional_exclusive(dev, -+ pcs_reset_name[i]); -+ -+ if (IS_ERR(qpcs->reset[i])) -+ dev_err(dev, "Failed to get the reset ID %s\n", -+ pcs_reset_name[i]); -+ } - - ret = ipq_pcs_clk_register(qpcs); - if (ret) ---- /dev/null -+++ b/include/linux/pcs/pcs-qcom-ipq-uniphy.h -@@ -0,0 +1,13 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ * -+ */ -+ -+#ifndef __LINUX_PCS_QCOM_IPQ_UNIPHY_H -+#define __LINUX_PCS_QCOM_IPQ_UNIPHY_H -+ -+struct phylink_pcs *ipq_unipcs_create(struct device_node *np); -+void ipq_unipcs_destroy(struct phylink_pcs *pcs); -+ -+#endif /* __LINUX_PCS_QCOM_IPQ_UNIPHY_H */ diff --git a/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch b/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch index 29c20a240a..8196ff601c 100644 --- a/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch +++ b/target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch @@ -1,4 +1,4 @@ -From 8c02b6438167e1b73b908040c4ec3d4877c16f83 Mon Sep 17 00:00:00 2001 +From d6f184181b076cbb54f152994f5bc73ce524a67e Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Sun, 11 May 2025 18:21:00 -0500 Subject: [PATCH] arm64: dts: qcom: ipq9574: add PCS uniphy nodes @@ -11,8 +11,8 @@ feed back to the NSSCC node. Signed-off-by: Alexandru Gagniuc --- - arch/arm64/boot/dts/qcom/ipq9574.dtsi | 116 ++++++++++++++++++++++++-- - 1 file changed, 110 insertions(+), 6 deletions(-) + arch/arm64/boot/dts/qcom/ipq9574.dtsi | 100 ++++++++++++++++++++++++-- + 1 file changed, 94 insertions(+), 6 deletions(-) --- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi +++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi @@ -43,7 +43,7 @@ Signed-off-by: Alexandru Gagniuc <&gcc GCC_NSSCC_CLK>; clock-names = "xo", "nss_1200", -@@ -1269,6 +1270,109 @@ +@@ -1269,6 +1270,93 @@ #reset-cells = <1>; #interconnect-cells = <1>; }; @@ -57,13 +57,7 @@ Signed-off-by: Alexandru Gagniuc + <&gcc GCC_UNIPHY0_AHB_CLK>; + clock-names = "sys", + "ahb"; -+ resets = <&gcc GCC_UNIPHY0_SYS_RESET>, -+ <&gcc GCC_UNIPHY0_AHB_RESET>, -+ <&gcc GCC_UNIPHY0_XPCS_RESET>; -+ reset-names = "sys", -+ "ahb", -+ "xpcs"; -+ ++ resets = <&gcc GCC_UNIPHY0_XPCS_RESET>; + #clock-cells = <1>; + + pcs0_ch0: pcs-mii@0 { @@ -108,12 +102,7 @@ Signed-off-by: Alexandru Gagniuc + <&gcc GCC_UNIPHY1_AHB_CLK>; + clock-names = "sys", + "ahb"; -+ resets = <&gcc GCC_UNIPHY1_SYS_RESET>, -+ <&gcc GCC_UNIPHY1_AHB_RESET>, -+ <&gcc GCC_UNIPHY1_XPCS_RESET>; -+ reset-names = "sys", -+ "ahb", -+ "xpcs"; ++ resets = <&gcc GCC_UNIPHY1_XPCS_RESET>; + #clock-cells = <1>; + + pcs1_ch0: pcs-mii@0 { @@ -134,12 +123,7 @@ Signed-off-by: Alexandru Gagniuc + <&gcc GCC_UNIPHY2_AHB_CLK>; + clock-names = "sys", + "ahb"; -+ resets = <&gcc GCC_UNIPHY2_SYS_RESET>, -+ <&gcc GCC_UNIPHY2_AHB_RESET>, -+ <&gcc GCC_UNIPHY2_XPCS_RESET>; -+ reset-names = "sys", -+ "ahb", -+ "xpcs"; ++ resets = <&gcc GCC_UNIPHY2_XPCS_RESET>; + #clock-cells = <1>; + + pcs2_ch0: pcs-mii@0 { diff --git a/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch b/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch index 157f5b62c6..5bdf3e9299 100644 --- a/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch +++ b/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch @@ -1,4 +1,4 @@ -From e770b36f0353fd11c4628360fe412acb7f02f346 Mon Sep 17 00:00:00 2001 +From 432c2a2da1e0f4a8e2c0fea191361832a7f90f36 Mon Sep 17 00:00:00 2001 From: Lei Wei Date: Wed, 6 Mar 2024 17:40:52 +0800 Subject: [PATCH] net: pcs: Add 10GBASER interface mode support to IPQ UNIPHY @@ -9,40 +9,41 @@ Subject: [PATCH] net: pcs: Add 10GBASER interface mode support to IPQ UNIPHY Change-Id: Ifc3c3bb23811807a9b34e88771aab2c830c2327c Signed-off-by: Lei Wei Alex G: Use regmap to read/write registers + Remove xpcs_reset deassert logic (to be implemented later) Signed-off-by: Alexandru Gagniuc --- - drivers/net/pcs/pcs-qcom-ipq9574.c | 57 ++++++++++++++++++++++++++++++ - 1 file changed, 57 insertions(+) + drivers/net/pcs/pcs-qcom-ipq9574.c | 47 ++++++++++++++++++++++++++++++ + 1 file changed, 47 insertions(+) --- a/drivers/net/pcs/pcs-qcom-ipq9574.c +++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -60,6 +60,9 @@ +@@ -55,6 +55,9 @@ FIELD_PREP(GENMASK(9, 2), \ FIELD_GET(XPCS_INDIRECT_ADDR_L, reg))) -+#define XPCS_10GBASER_STS 0x30020 -+#define XPCS_10GBASER_LINK_STS BIT(12) ++#define XPCS_KR_STS 0x30020 ++#define XPCS_KR_LINK_STS BIT(12) + #define XPCS_DIG_CTRL 0x38000 #define XPCS_USXG_ADPT_RESET BIT(10) #define XPCS_USXG_EN BIT(9) -@@ -229,6 +232,28 @@ static void ipq_pcs_get_state_usxgmii(st +@@ -196,6 +199,28 @@ static void ipq_pcs_get_state_usxgmii(st state->duplex = DUPLEX_FULL; } -+static void ipq_unipcs_get_state_10gbaser(struct ipq_pcs *qpcs, -+ struct phylink_link_state *state) ++static void ipq_pcs_get_state_10gbaser(struct ipq_pcs *qpcs, ++ struct phylink_link_state *state) +{ + unsigned int val; + int ret; + -+ ret = regmap_read(qpcs->regmap, XPCS_10GBASER_STS, &val); ++ ret = regmap_read(qpcs->regmap, XPCS_KR_STS, &val); + if (ret) { + state->link = 0; + return; + } + -+ state->link = !!(val & XPCS_10GBASER_LINK_STS); ++ state->link = !!(val & XPCS_KR_LINK_STS); + + if (!state->link) + return; @@ -55,49 +56,31 @@ Signed-off-by: Alexandru Gagniuc static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, phy_interface_t interface) { -@@ -251,6 +276,7 @@ static int ipq_pcs_config_mode(struct ip - val = PCS_MODE_PSGMII; +@@ -212,6 +237,7 @@ static int ipq_pcs_config_mode(struct ip + val = PCS_MODE_QSGMII; break; case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: val = PCS_MODE_XPCS; rate = 312500000; break; -@@ -355,6 +381,25 @@ static int ipq_pcs_config_usxgmii(struct +@@ -311,6 +337,15 @@ static int ipq_pcs_config_usxgmii(struct return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); } -+static int ipq_unipcs_config_10gbaser(struct ipq_pcs *qpcs, -+ phy_interface_t interface) ++static int ipq_pcs_config_10gbaser(struct ipq_pcs *qpcs) +{ -+ int ret; -+ -+ if (qpcs->interface != interface) { -+ ret = ipq_pcs_config_mode(qpcs, interface); -+ if (ret) -+ return ret; -+ -+ /* Deassert XPCS */ -+ reset_control_deassert(qpcs->reset[XPCS_RESET]); -+ -+ qpcs->interface = interface; -+ } ++ /* Configure 10GBASER mode if required */ ++ if (qpcs->interface == PHY_INTERFACE_MODE_10GBASER) ++ return 0; + -+ return 0; ++ return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_10GBASER); +} + - static unsigned long ipq_unipcs_clock_rate_get_gmii(int speed) - { - unsigned long rate = 0; -@@ -421,6 +466,7 @@ ipq_unipcs_link_up_clock_rate_set(struct - rate = ipq_unipcs_clock_rate_get_gmii(speed); - break; - case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: - rate = ipq_unipcs_clock_rate_get_xgmii(speed); - break; - default: -@@ -528,6 +574,7 @@ static int ipq_pcs_validate(struct phyli + static int ipq_pcs_link_up_config_sgmii(struct ipq_pcs *qpcs, + int index, + unsigned int neg_mode, +@@ -399,6 +434,7 @@ static int ipq_pcs_validate(struct phyli switch (state->interface) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: @@ -105,44 +88,45 @@ Signed-off-by: Alexandru Gagniuc return 0; case PHY_INTERFACE_MODE_USXGMII: /* USXGMII only supports full duplex mode */ -@@ -546,6 +593,7 @@ static unsigned int ipq_pcs_inband_caps( - case PHY_INTERFACE_MODE_SGMII: +@@ -418,6 +454,8 @@ static unsigned int ipq_pcs_inband_caps( case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_USXGMII: -+ case PHY_INTERFACE_MODE_10GBASER: return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ case PHY_INTERFACE_MODE_10GBASER: ++ return LINK_INBAND_DISABLE; default: return 0; -@@ -602,6 +650,9 @@ static void ipq_pcs_get_state(struct phy + } +@@ -472,6 +510,9 @@ static void ipq_pcs_get_state(struct phy case PHY_INTERFACE_MODE_USXGMII: ipq_pcs_get_state_usxgmii(qpcs, state); break; + case PHY_INTERFACE_MODE_10GBASER: -+ ipq_unipcs_get_state_10gbaser(qpcs, state); ++ ipq_pcs_get_state_10gbaser(qpcs, state); + break; default: break; } -@@ -631,6 +682,8 @@ static int ipq_pcs_config(struct phylink +@@ -500,6 +541,8 @@ static int ipq_pcs_config(struct phylink return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); case PHY_INTERFACE_MODE_USXGMII: return ipq_pcs_config_usxgmii(qpcs); + case PHY_INTERFACE_MODE_10GBASER: -+ return ipq_unipcs_config_10gbaser(qpcs, interface); ++ return ipq_pcs_config_10gbaser(qpcs); default: - dev_err(qpcs->dev, - "interface %s not supported\n", phy_modes(interface)); -@@ -662,6 +715,9 @@ static void ipq_pcs_link_up(struct phyli + return -EOPNOTSUPP; + }; +@@ -524,6 +567,9 @@ static void ipq_pcs_link_up(struct phyli case PHY_INTERFACE_MODE_USXGMII: ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); break; + case PHY_INTERFACE_MODE_10GBASER: + /* Nothing to do here */ -+ break; ++ return; default: - dev_err(qpcs->dev, - "interface %s not supported\n", phy_modes(interface)); -@@ -730,6 +786,7 @@ static unsigned long ipq_pcs_clk_rate_ge + return; + } +@@ -603,6 +649,7 @@ static unsigned long ipq_pcs_clk_rate_ge { switch (qpcs->interface) { case PHY_INTERFACE_MODE_USXGMII: diff --git a/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch b/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch index dff74f0224..fbdebec13a 100644 --- a/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch +++ b/target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch @@ -1,4 +1,4 @@ -From a2e687df29e457621616d5d769688e6c972f9ac6 Mon Sep 17 00:00:00 2001 +From 0d3a93e3a5544daec59d8f10ac5ccab39849536e Mon Sep 17 00:00:00 2001 From: Lei Wei Date: Tue, 2 Apr 2024 18:28:42 +0800 Subject: [PATCH] net: pcs: Add 2500BASEX interface mode support to IPQ UNIPHY @@ -12,33 +12,33 @@ connects with a 2.5G SFP module. Change-Id: I3fe61113c1b3685debc20659736a9488216a029d Signed-off-by: Lei Wei Alex G: use regmap to read/write registers + 's/ipq_unipcs/ipq_pcs/' in function names as suggested by Luo Jie Signed-off-by: Alexandru Gagniuc --- - drivers/net/pcs/pcs-qcom-ipq9574.c | 95 ++++++++++++++++++++++++++++++ - 1 file changed, 95 insertions(+) + drivers/net/pcs/pcs-qcom-ipq9574.c | 67 ++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) --- a/drivers/net/pcs/pcs-qcom-ipq9574.c +++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -29,6 +29,7 @@ +@@ -26,6 +26,7 @@ + #define PCS_MODE_SEL_MASK GENMASK(12, 8) #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) - #define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2) -+#define PCS_MODE_SGMII_PLUS FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) ++#define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) -@@ -188,6 +189,30 @@ static void ipq_pcs_get_state_sgmii(stru - state->pause |= MLO_PAUSE_RX; +@@ -155,6 +156,29 @@ static void ipq_pcs_get_state_sgmii(stru + state->duplex = DUPLEX_HALF; } -+static void ipq_unipcs_get_state_2500basex(struct ipq_pcs *qpcs, -+ int index, -+ struct phylink_link_state *state) ++static void ipq_pcs_get_state_2500basex(struct ipq_pcs *qpcs, ++ struct phylink_link_state *state) +{ -+ unsigned int val; ++ unsigned int val; + int ret; + -+ ret = regmap_read(qpcs->regmap, PCS_MII_STS(index), &val); ++ ret = regmap_read(qpcs->regmap, PCS_MII_STS(0), &val); + if (ret) { + state->link = 0; + return; @@ -58,99 +58,57 @@ Signed-off-by: Alexandru Gagniuc static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, struct phylink_link_state *state) { -@@ -272,6 +297,10 @@ static int ipq_pcs_config_mode(struct ip +@@ -236,6 +260,10 @@ static int ipq_pcs_config_mode(struct ip case PHY_INTERFACE_MODE_QSGMII: val = PCS_MODE_QSGMII; break; + case PHY_INTERFACE_MODE_2500BASEX: -+ val = PCS_MODE_SGMII_PLUS; ++ val = PCS_MODE_2500BASEX; + rate = 312500000; + break; - case PHY_INTERFACE_MODE_PSGMII: - val = PCS_MODE_PSGMII; - break; -@@ -355,6 +384,22 @@ static int ipq_pcs_config_sgmii(struct i + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10GBASER: + val = PCS_MODE_XPCS; +@@ -314,6 +342,15 @@ static int ipq_pcs_config_sgmii(struct i PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); } -+static int ipq_unipcs_config_2500basex(struct ipq_pcs *qpcs, -+ phy_interface_t interface) ++static int ipq_pcs_config_2500basex(struct ipq_pcs *qpcs) +{ -+ int ret; -+ -+ if (qpcs->interface != interface) { -+ ret = ipq_pcs_config_mode(qpcs, interface); -+ if (ret) -+ return ret; -+ -+ qpcs->interface = interface; -+ } ++ /* Configure PCS for 2500BASEX mode if required */ ++ if (qpcs->interface == PHY_INTERFACE_MODE_2500BASEX) ++ return 0; + -+ return 0; ++ return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_2500BASEX); +} + static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) { int ret; -@@ -421,6 +466,21 @@ static unsigned long ipq_unipcs_clock_ra - return rate; - } - -+static unsigned long ipq_unipcs_clock_rate_get_gmiiplus(int speed) -+{ -+ unsigned long rate = 0; -+ -+ switch (speed) { -+ case SPEED_2500: -+ rate = 312500000; -+ break; -+ default: -+ break; -+ } -+ -+ return rate; -+} -+ - static unsigned long ipq_unipcs_clock_rate_get_xgmii(int speed) - { - unsigned long rate = 0; -@@ -465,6 +525,9 @@ ipq_unipcs_link_up_clock_rate_set(struct - case PHY_INTERFACE_MODE_PSGMII: - rate = ipq_unipcs_clock_rate_get_gmii(speed); - break; -+ case PHY_INTERFACE_MODE_2500BASEX: -+ rate = ipq_unipcs_clock_rate_get_gmiiplus(speed); -+ break; - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10GBASER: - rate = ipq_unipcs_clock_rate_get_xgmii(speed); -@@ -528,6 +591,25 @@ static int ipq_pcs_link_up_config_sgmii( +@@ -388,6 +425,22 @@ static int ipq_pcs_link_up_config_sgmii( PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); } -+static int ipq_unipcs_link_up_config_2500basex(struct ipq_pcs *qpcs, -+ int index, -+ int speed) ++static int ipq_pcs_link_up_config_2500basex(struct ipq_pcs *qpcs, int speed) +{ -+ unsigned int val; + int ret; + -+ /* 2500BASEX do not support autoneg and do not need to -+ * configure PCS speed, only reset PCS adapter here. ++ /* 2500BASEX does not support autoneg and does not need to ++ * configure PCS speed. Only reset PCS adapter here. + */ + ret = regmap_clear_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); ++ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); + if (ret) + return ret; + + return regmap_set_bits(qpcs->regmap, -+ PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); ++ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); +} + static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) { unsigned int val; -@@ -576,6 +658,10 @@ static int ipq_pcs_validate(struct phyli +@@ -436,6 +489,10 @@ static int ipq_pcs_validate(struct phyli case PHY_INTERFACE_MODE_QSGMII: case PHY_INTERFACE_MODE_10GBASER: return 0; @@ -161,36 +119,44 @@ Signed-off-by: Alexandru Gagniuc case PHY_INTERFACE_MODE_USXGMII: /* USXGMII only supports full duplex mode */ phylink_clear(supported, 100baseT_Half); -@@ -647,6 +733,9 @@ static void ipq_pcs_get_state(struct phy - case PHY_INTERFACE_MODE_PSGMII: +@@ -454,6 +511,7 @@ static unsigned int ipq_pcs_inband_caps( + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_USXGMII: + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_10GBASER: + return LINK_INBAND_DISABLE; + default: +@@ -507,6 +565,9 @@ static void ipq_pcs_get_state(struct phy + case PHY_INTERFACE_MODE_QSGMII: ipq_pcs_get_state_sgmii(qpcs, index, state); break; + case PHY_INTERFACE_MODE_2500BASEX: -+ ipq_unipcs_get_state_2500basex(qpcs, index, state); ++ ipq_pcs_get_state_2500basex(qpcs, state); + break; case PHY_INTERFACE_MODE_USXGMII: ipq_pcs_get_state_usxgmii(qpcs, state); break; -@@ -680,6 +769,8 @@ static int ipq_pcs_config(struct phylink +@@ -539,6 +600,8 @@ static int ipq_pcs_config(struct phylink + case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_PSGMII: return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); + case PHY_INTERFACE_MODE_2500BASEX: -+ return ipq_unipcs_config_2500basex(qpcs, interface); ++ return ipq_pcs_config_2500basex(qpcs); case PHY_INTERFACE_MODE_USXGMII: return ipq_pcs_config_usxgmii(qpcs); case PHY_INTERFACE_MODE_10GBASER: -@@ -712,6 +803,9 @@ static void ipq_pcs_link_up(struct phyli +@@ -564,6 +627,9 @@ static void ipq_pcs_link_up(struct phyli ret = ipq_pcs_link_up_config_sgmii(qpcs, index, neg_mode, speed); break; + case PHY_INTERFACE_MODE_2500BASEX: -+ ret = ipq_unipcs_link_up_config_2500basex(qpcs, index, speed); ++ ret = ipq_pcs_link_up_config_2500basex(qpcs, speed); + break; case PHY_INTERFACE_MODE_USXGMII: ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); break; -@@ -785,6 +879,7 @@ static int ipq_pcs_create_miis(struct ip +@@ -648,6 +714,7 @@ static int ipq_pcs_create_miis(struct ip static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs) { switch (qpcs->interface) { diff --git a/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch b/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch index 9c6bfabc45..37aa60d8ff 100644 --- a/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch +++ b/target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch @@ -1,4 +1,4 @@ -From 07f9bb8eb006e9664d651089a1f422d045e093e3 Mon Sep 17 00:00:00 2001 +From d82953614a4f09dd7479e1d3904351ff85d1d088 Mon Sep 17 00:00:00 2001 From: Lei Wei Date: Tue, 9 Apr 2024 01:07:22 +0800 Subject: [PATCH] net: pcs: Add 1000BASEX interface mode support to IPQ UNIPHY @@ -10,70 +10,75 @@ Change-Id: Ied7298de3c1ecba74e6457a07fdd6b3ceab79728 Signed-off-by: Lei Wei Signed-off-by: Alexandru Gagniuc --- - drivers/net/pcs/pcs-qcom-ipq9574.c | 19 +++++++++++++++++-- - 1 file changed, 17 insertions(+), 2 deletions(-) + drivers/net/pcs/pcs-qcom-ipq9574.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) --- a/drivers/net/pcs/pcs-qcom-ipq9574.c +++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -31,6 +31,9 @@ - #define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2) - #define PCS_MODE_SGMII_PLUS FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) +@@ -28,6 +28,9 @@ + #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) + #define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) -+#define PCS_MODE_SGMII_CTRL_MASK GENMASK(6, 4) -+#define PCS_MODE_SGMII_CTRL_1000BASEX FIELD_PREP(PCS_MODE_SGMII_CTRL_MASK, \ ++#define PCS_MODE_SGMII_MODE_MASK GENMASK(6, 4) ++#define PCS_MODE_SGMII_MODE_1000BASEX FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ + 0x0) #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x)) #define PCS_MII_ADPT_RESET BIT(11) -@@ -283,7 +286,7 @@ static int ipq_pcs_config_mode(struct ip +@@ -249,10 +252,11 @@ static int ipq_pcs_config_mode(struct ip phy_interface_t interface) { unsigned long rate = 125000000; - unsigned int val; -+ unsigned int val, mask = PCS_MODE_SEL_MASK; ++ unsigned int val, mask; int ret; - /* Assert XPCS reset */ -@@ -297,6 +300,10 @@ static int ipq_pcs_config_mode(struct ip + /* Configure PCS interface mode */ ++ mask = PCS_MODE_SEL_MASK; + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + val = PCS_MODE_SGMII; +@@ -260,6 +264,10 @@ static int ipq_pcs_config_mode(struct ip case PHY_INTERFACE_MODE_QSGMII: val = PCS_MODE_QSGMII; break; + case PHY_INTERFACE_MODE_1000BASEX: -+ mask |= PCS_MODE_SGMII_CTRL_MASK; -+ val = PCS_MODE_SGMII | PCS_MODE_SGMII_CTRL_1000BASEX; ++ mask |= PCS_MODE_SGMII_MODE_MASK; ++ val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_1000BASEX; + break; case PHY_INTERFACE_MODE_2500BASEX: - val = PCS_MODE_SGMII_PLUS; + val = PCS_MODE_2500BASEX; rate = 312500000; -@@ -316,7 +323,7 @@ static int ipq_pcs_config_mode(struct ip +@@ -273,8 +281,7 @@ static int ipq_pcs_config_mode(struct ip + return -EOPNOTSUPP; } - ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, +- ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, - PCS_MODE_SEL_MASK, val); -+ mask, val); ++ ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, mask, val); if (ret) return ret; -@@ -523,6 +530,7 @@ ipq_unipcs_link_up_clock_rate_set(struct +@@ -487,6 +494,7 @@ static int ipq_pcs_validate(struct phyli + switch (state->interface) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: - rate = ipq_unipcs_clock_rate_get_gmii(speed); - break; + case PHY_INTERFACE_MODE_10GBASER: + return 0; case PHY_INTERFACE_MODE_2500BASEX: -@@ -657,6 +665,7 @@ static int ipq_pcs_validate(struct phyli +@@ -509,6 +517,7 @@ static unsigned int ipq_pcs_inband_caps( + switch (interface) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_1000BASEX: - return 0; + case PHY_INTERFACE_MODE_USXGMII: + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; case PHY_INTERFACE_MODE_2500BASEX: - /* In-band autoneg is not supported for 2500BASEX */ -@@ -731,6 +740,10 @@ static void ipq_pcs_get_state(struct phy +@@ -563,6 +572,10 @@ static void ipq_pcs_get_state(struct phy + switch (state->interface) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: + /* SGMII and 1000BASEX in-band autoneg word format are decoded + * by PCS hardware and both placed to the same status register. @@ -81,18 +86,18 @@ Signed-off-by: Alexandru Gagniuc ipq_pcs_get_state_sgmii(qpcs, index, state); break; case PHY_INTERFACE_MODE_2500BASEX: -@@ -768,6 +781,7 @@ static int ipq_pcs_config(struct phylink +@@ -599,6 +612,7 @@ static int ipq_pcs_config(struct phylink + switch (interface) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); case PHY_INTERFACE_MODE_2500BASEX: - return ipq_unipcs_config_2500basex(qpcs, interface); -@@ -800,6 +814,7 @@ static void ipq_pcs_link_up(struct phyli + return ipq_pcs_config_2500basex(qpcs); +@@ -624,6 +638,7 @@ static void ipq_pcs_link_up(struct phyli + switch (interface) { case PHY_INTERFACE_MODE_SGMII: case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: ret = ipq_pcs_link_up_config_sgmii(qpcs, index, neg_mode, speed); diff --git a/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch b/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch index 03fa4dffef..2563ac8396 100644 --- a/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch +++ b/target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch @@ -1,4 +1,4 @@ -From 77462c0d74e51a24408062b93c3fcc0256909d33 Mon Sep 17 00:00:00 2001 +From fc26c6f6c69149ce87c88d6878ae929b2a138063 Mon Sep 17 00:00:00 2001 From: Lei Wei Date: Mon, 15 Apr 2024 11:06:02 +0800 Subject: [PATCH] net: pcs: Add 10G_QXGMII interface mode support to IPQ UNIPHY @@ -11,14 +11,14 @@ Change-Id: If3dc92a07ac3e51f7c9473fb05fa0668617916fb Signed-off-by: Lei Wei Signed-off-by: Alexandru Gagniuc --- - drivers/net/pcs/pcs-qcom-ipq9574.c | 112 +++++++++++++++++++++++------ - 1 file changed, 91 insertions(+), 21 deletions(-) + drivers/net/pcs/pcs-qcom-ipq9574.c | 109 +++++++++++++++++++++++------ + 1 file changed, 87 insertions(+), 22 deletions(-) --- a/drivers/net/pcs/pcs-qcom-ipq9574.c +++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -53,6 +53,9 @@ - #define PCS_MII_STS_PAUSE_TX_EN BIT(1) - #define PCS_MII_STS_PAUSE_RX_EN BIT(0) +@@ -48,6 +48,9 @@ + #define PCS_MII_STS_SPEED_100 1 + #define PCS_MII_STS_SPEED_1000 2 +#define PCS_QP_USXG_OPTION 0x584 +#define PCS_QP_USXG_GMII_SRC_XPCS BIT(0) @@ -26,8 +26,8 @@ Signed-off-by: Alexandru Gagniuc #define PCS_PLL_RESET 0x780 #define PCS_ANA_SW_RESET BIT(6) -@@ -68,10 +71,22 @@ - #define XPCS_10GBASER_LINK_STS BIT(12) +@@ -63,10 +66,23 @@ + #define XPCS_KR_LINK_STS BIT(12) #define XPCS_DIG_CTRL 0x38000 +#define XPCS_SOFT_RESET BIT(15) @@ -41,82 +41,89 @@ Signed-off-by: Alexandru Gagniuc +#define XPCS_DIG_STS 0x3800a +#define XPCS_DIG_STS_AM_COUNT GENMASK(14, 0) + -+#define XPCS_CHANNEL_DIG_CTRL(x) (0x1a8000 + 0x10000 * ((x) - 1)) -+#define XPCS_CHANNEL_USXG_ADPT_RESET BIT(5) ++/* DIG control for MII1 - MII3 */ ++#define XPCS_MII1_DIG_CTRL(x) (0x1a8000 + 0x10000 * ((x) - 1)) ++#define XPCS_MII1_USXG_ADPT_RESET BIT(5) + #define XPCS_MII_CTRL 0x1f0000 -+#define XPCS_CHANNEL_MII_CTRL(x) (0x1a0000 + 0x10000 * ((x) - 1)) ++#define XPCS_MII1_CTRL(x) (0x1a0000 + 0x10000 * ((x) - 1)) #define XPCS_MII_AN_EN BIT(12) #define XPCS_DUPLEX_FULL BIT(8) #define XPCS_SPEED_MASK (BIT(13) | BIT(6) | BIT(5)) -@@ -83,9 +98,11 @@ +@@ -78,9 +94,11 @@ #define XPCS_SPEED_10 0 #define XPCS_MII_AN_CTRL 0x1f8001 -+#define XPCS_CHANNEL_MII_AN_CTRL(x) (0x1a8001 + 0x10000 * ((x) - 1)) ++#define XPCS_MII1_AN_CTRL(x) (0x1a8001 + 0x10000 * ((x) - 1)) #define XPCS_MII_AN_8BIT BIT(8) #define XPCS_MII_AN_INTR_STS 0x1f8002 -+#define XPCS_CHANNEL_MII_AN_INTR_STS(x) (0x1a8002 + 0x10000 * ((x) - 1)) ++#define XPCS_MII1_AN_INTR_STS(x) (0x1a8002 + 0x10000 * ((x) - 1)) #define XPCS_USXG_AN_LINK_STS BIT(14) #define XPCS_USXG_AN_SPEED_MASK GENMASK(12, 10) #define XPCS_USXG_AN_SPEED_10 0 -@@ -95,6 +112,10 @@ +@@ -90,6 +108,10 @@ #define XPCS_USXG_AN_SPEED_5000 5 #define XPCS_USXG_AN_SPEED_10000 3 +#define XPCS_XAUI_MODE_CTRL 0x1f8004 -+#define XPCS_CHANNEL_XAUI_MODE_CTRL(x) (0x1a8004 + 0x10000 * ((x) - 1)) ++#define XPCS_MII1_XAUI_MODE_CTRL(x) (0x1a8004 + 0x10000 * ((x) - 1)) +#define XPCS_TX_IPG_CHECK_DIS BIT(0) + /* Per PCS MII private data */ struct ipq_pcs_mii { struct ipq_pcs *qpcs; -@@ -217,12 +238,16 @@ static void ipq_unipcs_get_state_2500bas +@@ -182,13 +204,14 @@ static void ipq_pcs_get_state_2500basex( + state->pause |= MLO_PAUSE_TXRX_MASK; } - static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, -+ int index, +-static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, ++static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs, int index, struct phylink_link_state *state) { - unsigned int val; -- int ret; -+ int ret, reg; -+ -+ reg = (index == 0) ? XPCS_MII_AN_INTR_STS : -+ XPCS_CHANNEL_MII_AN_INTR_STS(index); +- unsigned int val; ++ unsigned int reg, val; + int ret; - ret = regmap_read(qpcs->regmap, XPCS_MII_AN_INTR_STS, &val); ++ reg = (index == 0) ? XPCS_MII_AN_INTR_STS : XPCS_MII1_AN_INTR_STS(index); + ret = regmap_read(qpcs->regmap, reg, &val); if (ret) { state->link = 0; return; -@@ -316,6 +341,14 @@ static int ipq_pcs_config_mode(struct ip - val = PCS_MODE_XPCS; +@@ -273,6 +296,7 @@ static int ipq_pcs_config_mode(struct ip rate = 312500000; break; + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10G_QXGMII: -+ val = PCS_MODE_XPCS; -+ rate = 312500000; + case PHY_INTERFACE_MODE_10GBASER: + val = PCS_MODE_XPCS; + rate = 312500000; +@@ -285,6 +309,13 @@ static int ipq_pcs_config_mode(struct ip + if (ret) + return ret; + ++ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { + ret = regmap_set_bits(qpcs->regmap, PCS_QP_USXG_OPTION, + PCS_QP_USXG_GMII_SRC_XPCS); + if (ret) + return ret; -+ break; - default: - dev_err(qpcs->dev, - "interface %s not supported\n", phy_modes(interface)); -@@ -407,30 +440,55 @@ static int ipq_unipcs_config_2500basex(s - return 0; ++ } ++ + /* PCS PLL reset */ + ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); + if (ret) +@@ -358,27 +389,51 @@ static int ipq_pcs_config_2500basex(stru + return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_2500BASEX); } -static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs) +static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs, -+ int index, -+ phy_interface_t interface) ++ int index, ++ phy_interface_t interface) { -- int ret; -+ int ret, reg; ++ unsigned int reg; + int ret; /* Configure the XPCS for USXGMII mode if required */ - if (qpcs->interface == PHY_INTERFACE_MODE_USXGMII) @@ -129,87 +136,66 @@ Signed-off-by: Alexandru Gagniuc + ret = ipq_pcs_config_mode(qpcs, interface); + if (ret) + return ret; -+ } - -- /* Deassert XPCS and configure XPCS USXGMII */ -+ /* Deassert XPCS and configure XPCS USXGMII or 10G_QXGMII */ - reset_control_deassert(qpcs->reset[XPCS_RESET]); - - ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); - if (ret) - return ret; -- ret = regmap_set_bits(qpcs->regmap, XPCS_MII_AN_CTRL, XPCS_MII_AN_8BIT); -+ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ regmap_update_bits(qpcs->regmap, XPCS_KR_CTRL, -+ XPCS_USXG_MODE_MASK, XPCS_10G_QXGMII_MODE); +- ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); +- if (ret) +- return ret; ++ if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { ++ ret = regmap_update_bits(qpcs->regmap, XPCS_KR_CTRL, ++ XPCS_USXG_MODE_MASK, XPCS_10G_QXGMII_MODE); ++ if (ret) ++ return ret; + -+ /* Set Alignment Marker Interval */ -+ regmap_update_bits(qpcs->regmap, XPCS_DIG_STS, -+ XPCS_DIG_STS_AM_COUNT, 0x6018); ++ /* Set Alignment Marker Interval value as 0x6018 */ ++ ret = regmap_update_bits(qpcs->regmap, XPCS_DIG_STS, ++ XPCS_DIG_STS_AM_COUNT, 0x6018); ++ if (ret) ++ return ret; + -+ regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_SOFT_RESET); ++ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_SOFT_RESET); ++ if (ret) ++ return ret; + } + -+ qpcs->interface = interface; -+ + /* Disable Tx IPG check for 10G_QXGMII */ + if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { -+ reg = (index == 0) ? XPCS_XAUI_MODE_CTRL : -+ XPCS_CHANNEL_XAUI_MODE_CTRL(index); -+ -+ regmap_set_bits(qpcs->regmap, reg, XPCS_TX_IPG_CHECK_DIS); ++ reg = (index == 0) ? XPCS_XAUI_MODE_CTRL : XPCS_MII1_XAUI_MODE_CTRL(index); ++ ret = regmap_set_bits(qpcs->regmap, reg, XPCS_TX_IPG_CHECK_DIS); ++ if (ret) ++ return ret; + } -+ -+ /* Enable autoneg */ -+ reg = (index == 0) ? XPCS_MII_AN_CTRL : XPCS_CHANNEL_MII_AN_CTRL(index); + +- ret = regmap_set_bits(qpcs->regmap, XPCS_MII_AN_CTRL, XPCS_MII_AN_8BIT); ++ reg = (index == 0) ? XPCS_MII_AN_CTRL : XPCS_MII1_AN_CTRL(index); + ret = regmap_set_bits(qpcs->regmap, reg, XPCS_MII_AN_8BIT); if (ret) return ret; - return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN); -+ reg = (index == 0) ? XPCS_MII_CTRL : XPCS_CHANNEL_MII_CTRL(index); ++ reg = (index == 0) ? XPCS_MII_CTRL : XPCS_MII1_CTRL(index); + return regmap_set_bits(qpcs->regmap, reg, XPCS_MII_AN_EN); } - static int ipq_unipcs_config_10gbaser(struct ipq_pcs *qpcs, -@@ -538,6 +596,7 @@ ipq_unipcs_link_up_clock_rate_set(struct - break; - case PHY_INTERFACE_MODE_USXGMII: - case PHY_INTERFACE_MODE_10GBASER: -+ case PHY_INTERFACE_MODE_10G_QXGMII: - rate = ipq_unipcs_clock_rate_get_xgmii(speed); - break; - default: -@@ -603,7 +662,6 @@ static int ipq_unipcs_link_up_config_250 - int index, - int speed) - { -- unsigned int val; - int ret; - - /* 2500BASEX do not support autoneg and do not need to -@@ -618,10 +676,12 @@ static int ipq_unipcs_link_up_config_250 - PCS_MII_CTRL(index), PCS_MII_ADPT_RESET); + static int ipq_pcs_config_10gbaser(struct ipq_pcs *qpcs) +@@ -448,9 +503,10 @@ static int ipq_pcs_link_up_config_2500ba + PCS_MII_CTRL(0), PCS_MII_ADPT_RESET); } -static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed) +static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, -+ int channel, -+ int speed) ++ int index, int speed) { - unsigned int val; -- int ret; -+ int ret, reg; +- unsigned int val; ++ unsigned int reg, val; + int ret; switch (speed) { - case SPEED_10000: -@@ -648,14 +708,19 @@ static int ipq_pcs_link_up_config_usxgmi +@@ -478,14 +534,17 @@ static int ipq_pcs_link_up_config_usxgmi } /* Configure XPCS speed */ - ret = regmap_update_bits(qpcs->regmap, XPCS_MII_CTRL, -+ reg = (channel == 0) ? XPCS_MII_CTRL : XPCS_CHANNEL_MII_CTRL(channel); ++ reg = (index == 0) ? XPCS_MII_CTRL : XPCS_MII1_CTRL(index); + ret = regmap_update_bits(qpcs->regmap, reg, XPCS_SPEED_MASK, val | XPCS_DUPLEX_FULL); if (ret) @@ -217,25 +203,32 @@ Signed-off-by: Alexandru Gagniuc /* XPCS adapter reset */ - return regmap_set_bits(qpcs->regmap, -+ if (channel == 0) -+ return regmap_set_bits(qpcs->regmap, - XPCS_DIG_CTRL, XPCS_USXG_ADPT_RESET); -+ else -+ return regmap_set_bits(qpcs->regmap, XPCS_CHANNEL_DIG_CTRL(channel), -+ XPCS_CHANNEL_USXG_ADPT_RESET); +- XPCS_DIG_CTRL, XPCS_USXG_ADPT_RESET); ++ reg = (index == 0) ? XPCS_DIG_CTRL : XPCS_MII1_DIG_CTRL(index); ++ val = (index == 0) ? XPCS_USXG_ADPT_RESET : XPCS_MII1_USXG_ADPT_RESET; ++ return regmap_set_bits(qpcs->regmap, reg, val); ++ } static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, -@@ -671,6 +736,7 @@ static int ipq_pcs_validate(struct phyli - /* In-band autoneg is not supported for 2500BASEX */ +@@ -502,6 +561,7 @@ static int ipq_pcs_validate(struct phyli phylink_clear(supported, Autoneg); return 0; -+ case PHY_INTERFACE_MODE_10G_QXGMII: case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10G_QXGMII: /* USXGMII only supports full duplex mode */ phylink_clear(supported, 100baseT_Half); -@@ -750,7 +816,8 @@ static void ipq_pcs_get_state(struct phy - ipq_unipcs_get_state_2500basex(qpcs, index, state); + phylink_clear(supported, 10baseT_Half); +@@ -519,6 +579,7 @@ static unsigned int ipq_pcs_inband_caps( + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10G_QXGMII: + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_10GBASER: +@@ -582,7 +643,8 @@ static void ipq_pcs_get_state(struct phy + ipq_pcs_get_state_2500basex(qpcs, state); break; case PHY_INTERFACE_MODE_USXGMII: - ipq_pcs_get_state_usxgmii(qpcs, state); @@ -243,20 +236,19 @@ Signed-off-by: Alexandru Gagniuc + ipq_pcs_get_state_usxgmii(qpcs, index, state); break; case PHY_INTERFACE_MODE_10GBASER: - ipq_unipcs_get_state_10gbaser(qpcs, state); -@@ -786,7 +853,9 @@ static int ipq_pcs_config(struct phylink + ipq_pcs_get_state_10gbaser(qpcs, state); +@@ -617,7 +679,8 @@ static int ipq_pcs_config(struct phylink case PHY_INTERFACE_MODE_2500BASEX: - return ipq_unipcs_config_2500basex(qpcs, interface); + return ipq_pcs_config_2500basex(qpcs); case PHY_INTERFACE_MODE_USXGMII: - return ipq_pcs_config_usxgmii(qpcs); + case PHY_INTERFACE_MODE_10G_QXGMII: -+ return ipq_pcs_config_usxgmii(qpcs, index, -+ interface); ++ return ipq_pcs_config_usxgmii(qpcs, index, interface); case PHY_INTERFACE_MODE_10GBASER: - return ipq_unipcs_config_10gbaser(qpcs, interface); + return ipq_pcs_config_10gbaser(qpcs); default: -@@ -822,7 +891,8 @@ static void ipq_pcs_link_up(struct phyli - ret = ipq_unipcs_link_up_config_2500basex(qpcs, index, speed); +@@ -646,7 +709,8 @@ static void ipq_pcs_link_up(struct phyli + ret = ipq_pcs_link_up_config_2500basex(qpcs, speed); break; case PHY_INTERFACE_MODE_USXGMII: - ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed); @@ -265,3 +257,11 @@ Signed-off-by: Alexandru Gagniuc break; case PHY_INTERFACE_MODE_10GBASER: /* Nothing to do here */ +@@ -731,6 +795,7 @@ static unsigned long ipq_pcs_clk_rate_ge + switch (qpcs->interface) { + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10G_QXGMII: + case PHY_INTERFACE_MODE_10GBASER: + return 312500000; + default: diff --git a/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch b/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch index b34dd837ab..6ec8f2634e 100644 --- a/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch +++ b/target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch @@ -1,8 +1,7 @@ -From 930203b9bb94dc4ea9342f1ce176851918758ed7 Mon Sep 17 00:00:00 2001 +From 87da3bbd25eb0a17e2c698120528e76c26b326d0 Mon Sep 17 00:00:00 2001 From: Mantas Pucka Date: Mon, 2 Jun 2025 17:18:13 +0300 -Subject: [PATCH] net: pcs: ipq-uniphy: control MISC2 register for 2.5G - support +Subject: [PATCH] net: pcs: ipq-uniphy: control MISC2 register for 2.5G support When 2500base-x mode is enabled MISC2 regsister needs to have different value than for other 1G modes. @@ -14,7 +13,7 @@ Signed-off-by: Mantas Pucka --- a/drivers/net/pcs/pcs-qcom-ipq9574.c +++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -24,6 +24,11 @@ +@@ -22,6 +22,11 @@ #define PCS_CALIBRATION 0x1e0 #define PCS_CALIBRATION_DONE BIT(7) @@ -26,16 +25,16 @@ Signed-off-by: Mantas Pucka #define PCS_MODE_CTRL 0x46c #define PCS_MODE_SEL_MASK GENMASK(12, 8) #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) -@@ -311,7 +316,7 @@ static int ipq_pcs_config_mode(struct ip +@@ -275,7 +280,7 @@ static int ipq_pcs_config_mode(struct ip phy_interface_t interface) { unsigned long rate = 125000000; -- unsigned int val, mask = PCS_MODE_SEL_MASK; -+ unsigned int val, misc2 = 0, mask = PCS_MODE_SEL_MASK; +- unsigned int val, mask; ++ unsigned int val, mask, misc2 = 0; int ret; - /* Assert XPCS reset */ -@@ -321,6 +326,7 @@ static int ipq_pcs_config_mode(struct ip + /* Configure PCS interface mode */ +@@ -283,6 +288,7 @@ static int ipq_pcs_config_mode(struct ip switch (interface) { case PHY_INTERFACE_MODE_SGMII: val = PCS_MODE_SGMII; @@ -43,30 +42,29 @@ Signed-off-by: Mantas Pucka break; case PHY_INTERFACE_MODE_QSGMII: val = PCS_MODE_QSGMII; -@@ -328,10 +334,12 @@ static int ipq_pcs_config_mode(struct ip +@@ -290,9 +296,11 @@ static int ipq_pcs_config_mode(struct ip case PHY_INTERFACE_MODE_1000BASEX: - mask |= PCS_MODE_SGMII_CTRL_MASK; - val = PCS_MODE_SGMII | PCS_MODE_SGMII_CTRL_1000BASEX; + mask |= PCS_MODE_SGMII_MODE_MASK; + val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_1000BASEX; + misc2 = PCS_MISC2_MODE_SGMII; break; case PHY_INTERFACE_MODE_2500BASEX: - val = PCS_MODE_SGMII_PLUS; - rate = 312500000; + val = PCS_MODE_2500BASEX; + misc2 = PCS_MISC2_MODE_SGMII_PLUS; + rate = 312500000; break; - case PHY_INTERFACE_MODE_PSGMII: - val = PCS_MODE_PSGMII; -@@ -360,6 +368,13 @@ static int ipq_pcs_config_mode(struct ip - if (ret) - return ret; - + case PHY_INTERFACE_MODE_USXGMII: +@@ -315,6 +323,13 @@ static int ipq_pcs_config_mode(struct ip + if (ret) + return ret; + } ++ + if (misc2) { + ret = regmap_update_bits(qpcs->regmap, PCS_MISC2, + PCS_MISC2_MODE_MASK, misc2); + if (ret) + return ret; + } -+ + /* PCS PLL reset */ ret = regmap_clear_bits(qpcs->regmap, PCS_PLL_RESET, PCS_ANA_SW_RESET); - if (ret) diff --git a/target/linux/qualcommbe/patches-6.12/0366-net-pcs-ipq-uniphy-keep-autoneg-enabled-in-SGMII-mod.patch b/target/linux/qualcommbe/patches-6.12/0366-net-pcs-ipq-uniphy-keep-autoneg-enabled-in-SGMII-mod.patch deleted file mode 100644 index 58e2be35f4..0000000000 --- a/target/linux/qualcommbe/patches-6.12/0366-net-pcs-ipq-uniphy-keep-autoneg-enabled-in-SGMII-mod.patch +++ /dev/null @@ -1,25 +0,0 @@ -From ccdfd293f9e948f0f62ac4e9924d72539a4e81ee Mon Sep 17 00:00:00 2001 -From: Mantas Pucka -Date: Mon, 2 Jun 2025 17:19:45 +0300 -Subject: [PATCH] net: pcs: ipq-uniphy: keep autoneg enabled in SGMII mode - -For PHYs that don't use in-band-status (e.g. 2.5G PHY swiching between -SGMII and 2500base-x), SGMII autoneg still must be enabled. Only mode -that should use forced speed is 1000base-x - -Signed-off-by: Mantas Pucka ---- - drivers/net/pcs/pcs-qcom-ipq9574.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/net/pcs/pcs-qcom-ipq9574.c -+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -431,7 +431,7 @@ static int ipq_pcs_config_sgmii(struct i - /* Nothing to do here as in-band autoneg mode is enabled - * by default for each PCS MII port. - */ -- if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) -+ if (interface != PHY_INTERFACE_MODE_1000BASEX) - return 0; - - /* Set force speed mode */ diff --git a/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch b/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch index 980b8d0379..b02782e7b3 100644 --- a/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch +++ b/target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch @@ -1,4 +1,4 @@ -From 0cff1d9bb695bdc0ad7bad234b92eddf849ce88f Mon Sep 17 00:00:00 2001 +From bedf56b46ae53c4abb21eebb3e1d5a7483926dda Mon Sep 17 00:00:00 2001 From: Mantas Pucka Date: Mon, 2 Jun 2025 17:20:58 +0300 Subject: [PATCH] net: pcs: ipq-uniphy: fix USXGMII link-up failure @@ -13,7 +13,7 @@ Signed-off-by: Mantas Pucka --- a/drivers/net/pcs/pcs-qcom-ipq9574.c +++ b/drivers/net/pcs/pcs-qcom-ipq9574.c -@@ -380,7 +380,7 @@ static int ipq_pcs_config_mode(struct ip +@@ -336,7 +336,7 @@ static int ipq_pcs_config_mode(struct ip if (ret) return ret; diff --git a/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch b/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch new file mode 100644 index 0000000000..63a523ae1c --- /dev/null +++ b/target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch @@ -0,0 +1,282 @@ +From b4e07a8a3ec3dc5f676238987556e2aff0b14028 Mon Sep 17 00:00:00 2001 +From: Lei Wei +Date: Mon, 29 Jan 2024 11:39:36 +0800 +Subject: [PATCH] net: pcs: qcom-ipq9574: Update IPQ9574 PCS driver + +Keep the PCS driver synced with the latest version posted to the kernel +community and add the XPCS reset support. + +Signed-off-by: Luo Jie +Signed-off-by: Alexandru Gagniuc +--- + .../bindings/net/pcs/qcom,ipq9574-pcs.yaml | 7 ++ + drivers/net/pcs/pcs-qcom-ipq9574.c | 68 +++++++++++++++---- + 2 files changed, 63 insertions(+), 12 deletions(-) + +--- a/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml ++++ b/Documentation/devicetree/bindings/net/pcs/qcom,ipq9574-pcs.yaml +@@ -98,6 +98,10 @@ properties: + - const: sys + - const: ahb + ++ resets: ++ maxItems: 1 ++ description: XPCS reset ++ + '#clock-cells': + const: 1 + description: See include/dt-bindings/net/qcom,ipq9574-pcs.h for constants +@@ -137,6 +141,7 @@ required: + - '#size-cells' + - clocks + - clock-names ++ - resets + - '#clock-cells' + + additionalProperties: false +@@ -144,6 +149,7 @@ additionalProperties: false + examples: + - | + #include ++ #include + + ethernet-pcs@7a00000 { + compatible = "qcom,ipq9574-pcs"; +@@ -154,6 +160,7 @@ examples: + <&gcc GCC_UNIPHY0_AHB_CLK>; + clock-names = "sys", + "ahb"; ++ resets = <&gcc GCC_UNIPHY0_XPCS_RESET>; + #clock-cells = <1>; + + pcs-mii@0 { +--- a/drivers/net/pcs/pcs-qcom-ipq9574.c ++++ b/drivers/net/pcs/pcs-qcom-ipq9574.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #include + +@@ -31,9 +32,12 @@ + #define PCS_MODE_SEL_MASK GENMASK(12, 8) + #define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4) + #define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1) ++#define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2) + #define PCS_MODE_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8) + #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10) + #define PCS_MODE_SGMII_MODE_MASK GENMASK(6, 4) ++#define PCS_MODE_SGMII_MODE_MAC FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ ++ 0x2) + #define PCS_MODE_SGMII_MODE_1000BASEX FIELD_PREP(PCS_MODE_SGMII_MODE_MASK, \ + 0x0) + +@@ -52,6 +56,8 @@ + #define PCS_MII_STS_SPEED_10 0 + #define PCS_MII_STS_SPEED_100 1 + #define PCS_MII_STS_SPEED_1000 2 ++#define PCS_MII_STS_PAUSE_TX_EN BIT(1) ++#define PCS_MII_STS_PAUSE_RX_EN BIT(0) + + #define PCS_QP_USXG_OPTION 0x584 + #define PCS_QP_USXG_GMII_SRC_XPCS BIT(0) +@@ -142,6 +148,7 @@ struct ipq_pcs { + struct clk_hw tx_hw; + + struct ipq_pcs_mii *qpcs_mii[PCS_MAX_MII_NRS]; ++ struct reset_control *xpcs_rstc; + }; + + #define phylink_pcs_to_qpcs_mii(_pcs) \ +@@ -184,6 +191,11 @@ static void ipq_pcs_get_state_sgmii(stru + state->duplex = DUPLEX_FULL; + else + state->duplex = DUPLEX_HALF; ++ ++ if (val & PCS_MII_STS_PAUSE_TX_EN) ++ state->pause |= MLO_PAUSE_TX; ++ if (val & PCS_MII_STS_PAUSE_RX_EN) ++ state->pause |= MLO_PAUSE_RX; + } + + static void ipq_pcs_get_state_2500basex(struct ipq_pcs *qpcs, +@@ -198,7 +210,6 @@ static void ipq_pcs_get_state_2500basex( + return; + } + +- + state->link = !!(val & PCS_MII_LINK_STS); + + if (!state->link) +@@ -281,17 +292,27 @@ static int ipq_pcs_config_mode(struct ip + { + unsigned long rate = 125000000; + unsigned int val, mask, misc2 = 0; ++ bool xpcs_mode = false; + int ret; + ++ /* Assert XPCS reset */ ++ reset_control_assert(qpcs->xpcs_rstc); ++ + /* Configure PCS interface mode */ + mask = PCS_MODE_SEL_MASK; + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: +- val = PCS_MODE_SGMII; ++ mask |= PCS_MODE_SGMII_MODE_MASK; ++ val = PCS_MODE_SGMII | PCS_MODE_SGMII_MODE_MAC; + misc2 = PCS_MISC2_MODE_SGMII; + break; + case PHY_INTERFACE_MODE_QSGMII: +- val = PCS_MODE_QSGMII; ++ mask |= PCS_MODE_SGMII_MODE_MASK; ++ val = PCS_MODE_QSGMII | PCS_MODE_SGMII_MODE_MAC; ++ break; ++ case PHY_INTERFACE_MODE_PSGMII: ++ mask |= PCS_MODE_SGMII_MODE_MASK; ++ val = PCS_MODE_PSGMII | PCS_MODE_SGMII_MODE_MAC; + break; + case PHY_INTERFACE_MODE_1000BASEX: + mask |= PCS_MODE_SGMII_MODE_MASK; +@@ -308,6 +329,7 @@ static int ipq_pcs_config_mode(struct ip + case PHY_INTERFACE_MODE_10GBASER: + val = PCS_MODE_XPCS; + rate = 312500000; ++ xpcs_mode = true; + break; + default: + return -EOPNOTSUPP; +@@ -367,6 +389,10 @@ static int ipq_pcs_config_mode(struct ip + return ret; + } + ++ /* Deassert XPCS */ ++ if (xpcs_mode) ++ reset_control_deassert(qpcs->xpcs_rstc); ++ + return 0; + } + +@@ -384,15 +410,13 @@ static int ipq_pcs_config_sgmii(struct i + return ret; + } + +- /* Nothing to do here as in-band autoneg mode is enabled +- * by default for each PCS MII port. +- */ ++ /* Set AN mode or force mode */ + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) +- return 0; +- +- /* Set force speed mode */ +- return regmap_set_bits(qpcs->regmap, +- PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); ++ return regmap_clear_bits(qpcs->regmap, ++ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); ++ else ++ return regmap_set_bits(qpcs->regmap, ++ PCS_MII_CTRL(index), PCS_MII_FORCE_MODE); + } + + static int ipq_pcs_config_2500basex(struct ipq_pcs *qpcs) +@@ -417,6 +441,10 @@ static int ipq_pcs_config_usxgmii(struct + if (ret) + return ret; + ++ ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_USXG_EN); ++ if (ret) ++ return ret; ++ + if (interface == PHY_INTERFACE_MODE_10G_QXGMII) { + ret = regmap_update_bits(qpcs->regmap, XPCS_KR_CTRL, + XPCS_USXG_MODE_MASK, XPCS_10G_QXGMII_MODE); +@@ -432,6 +460,7 @@ static int ipq_pcs_config_usxgmii(struct + ret = regmap_set_bits(qpcs->regmap, XPCS_DIG_CTRL, XPCS_SOFT_RESET); + if (ret) + return ret; ++ } + } + + /* Disable Tx IPG check for 10G_QXGMII */ +@@ -559,7 +588,6 @@ static int ipq_pcs_link_up_config_usxgmi + reg = (index == 0) ? XPCS_DIG_CTRL : XPCS_MII1_DIG_CTRL(index); + val = (index == 0) ? XPCS_USXG_ADPT_RESET : XPCS_MII1_USXG_ADPT_RESET; + return regmap_set_bits(qpcs->regmap, reg, val); +- + } + + static int ipq_pcs_validate(struct phylink_pcs *pcs, unsigned long *supported, +@@ -568,6 +596,7 @@ static int ipq_pcs_validate(struct phyli + switch (state->interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_10GBASER: + return 0; +@@ -592,6 +621,7 @@ static unsigned int ipq_pcs_inband_caps( + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_USXGMII: + case PHY_INTERFACE_MODE_10G_QXGMII: +@@ -648,6 +678,7 @@ static void ipq_pcs_get_state(struct phy + switch (state->interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: + /* SGMII and 1000BASEX in-band autoneg word format are decoded + * by PCS hardware and both placed to the same status register. +@@ -689,6 +720,7 @@ static int ipq_pcs_config(struct phylink + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: + return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface); + case PHY_INTERFACE_MODE_2500BASEX: +@@ -703,6 +735,11 @@ static int ipq_pcs_config(struct phylink + }; + } + ++static void ipq_pcs_an_restart(struct phylink_pcs *pcs) ++{ ++ /* Currently not used */ ++} ++ + static void ipq_pcs_link_up(struct phylink_pcs *pcs, + unsigned int neg_mode, + phy_interface_t interface, +@@ -716,6 +753,7 @@ static void ipq_pcs_link_up(struct phyli + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_1000BASEX: + ret = ipq_pcs_link_up_config_sgmii(qpcs, index, + neg_mode, speed); +@@ -746,6 +784,7 @@ static const struct phylink_pcs_ops ipq_ + .pcs_disable = ipq_pcs_disable, + .pcs_get_state = ipq_pcs_get_state, + .pcs_config = ipq_pcs_config, ++ .pcs_an_restart = ipq_pcs_an_restart, + .pcs_link_up = ipq_pcs_link_up, + }; + +@@ -990,6 +1029,11 @@ static int ipq9574_pcs_probe(struct plat + return dev_err_probe(dev, PTR_ERR(clk), + "Failed to enable AHB clock\n"); + ++ qpcs->xpcs_rstc = devm_reset_control_get_optional(dev, NULL); ++ if (IS_ERR_OR_NULL(qpcs->xpcs_rstc)) ++ return dev_err_probe(dev, PTR_ERR(qpcs->xpcs_rstc), ++ "Failed to get XPCS reset\n"); ++ + ret = ipq_pcs_clk_register(qpcs); + if (ret) + return ret; -- 2.30.2