qualcommbe: update ipq9574 PCS driver
authorAlexandru Gagniuc <[email protected]>
Fri, 7 Nov 2025 03:52:11 +0000 (21:52 -0600)
committerRobert Marko <[email protected]>
Sun, 30 Nov 2025 15:51:12 +0000 (16:51 +0100)
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 <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/20993
Signed-off-by: Robert Marko <[email protected]>
13 files changed:
target/linux/qualcommbe/patches-6.12/0316-net-pcs-qcom-ipq9574-Add-PCS-instantiation-and-phyli.patch
target/linux/qualcommbe/patches-6.12/0319-net-pcs-qcom-ipq9574-remove-neg_mode-argument-from-i.patch [deleted file]
target/linux/qualcommbe/patches-6.12/0320-net-pcs-qcom-ipq9574-delay-mii-clock-probing-until-i.patch [deleted file]
target/linux/qualcommbe/patches-6.12/0321-net-pcs-qcom-ipq9574-add-changes-not-submitted-upstr.patch [deleted file]
target/linux/qualcommbe/patches-6.12/0322-arm64-dts-qcom-ipq9574-add-PCS-uniphy-nodes.patch
target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch
target/linux/qualcommbe/patches-6.12/0362-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch
target/linux/qualcommbe/patches-6.12/0363-net-pcs-Add-1000BASEX-interface-mode-support-to-IPQ-.patch
target/linux/qualcommbe/patches-6.12/0364-net-pcs-Add-10G_QXGMII-interface-mode-support-to-IPQ.patch
target/linux/qualcommbe/patches-6.12/0365-net-pcs-ipq-uniphy-control-MISC2-register-for-2.5G-s.patch
target/linux/qualcommbe/patches-6.12/0366-net-pcs-ipq-uniphy-keep-autoneg-enabled-in-SGMII-mod.patch [deleted file]
target/linux/qualcommbe/patches-6.12/0367-net-pcs-ipq-uniphy-fix-USXGMII-link-up-failure.patch
target/linux/qualcommbe/patches-6.12/0368-net-pcs-qcom-ipq9574-Update-IPQ9574-PCS-driver.patch [new file with mode: 0644]

index 1e7453a35c9adeecac46400164ac22e68c2ced83..7d071c2e25b8e441819921c0f67f36a95b8286b0 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
+Alex G: remove phylink_pcs .neg_mode boolean
+Signed-off-by: Alexandru Gagniuc <[email protected]>
 ---
- 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 <[email protected]>
  /* 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 <[email protected]>
 +      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 <[email protected]>
 +              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 <[email protected]>
  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 <[email protected]>
        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 (file)
index 6fc9652..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From ffe2a80fb76ccdc1781f817f6bbc9a8aa919816e Mon Sep 17 00:00:00 2001
-From: Alexandru Gagniuc <[email protected]>
-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 <[email protected]>
----
- 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 (file)
index ac4c44a..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-From 5b2f02ccca7b9496f0a8da6ade063b82810c75e7 Mon Sep 17 00:00:00 2001
-From: Alexandru Gagniuc <[email protected]>
-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 <[email protected]>
----
- 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 (file)
index 64a5bf6..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-From 7de372abe7a4b5b380fdbeedd268445f234990c8 Mon Sep 17 00:00:00 2001
-From: Lei Wei <[email protected]>
-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 <[email protected]>
-Alex G: Rebase original patch on top of 20250207 uniphy submission
-        Remove mutex that is not required according to
-        https://lore.kernel.org/lkml/[email protected]/
-Signed-off-by: Alexandru Gagniuc <[email protected]>
----
- 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 <linux/of.h>
- #include <linux/of_platform.h>
- #include <linux/pcs/pcs-qcom-ipq9574.h>
-+#include <linux/pcs/pcs-qcom-ipq-uniphy.h>
- #include <linux/phy.h>
- #include <linux/phylink.h>
- #include <linux/platform_device.h>
- #include <linux/regmap.h>
-+#include <linux/reset.h>
- #include <dt-bindings/net/qcom,ipq9574-pcs.h>
-@@ -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 */
index 29c20a240aebd003cece3ab33f2fa662684326f7..8196ff601c434edef84b6a8977eabdd319d3f96c 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
 ---
- 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 <[email protected]>
                                 <&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 <[email protected]>
 +                               <&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 <[email protected]>
 +                               <&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 <[email protected]>
 +                               <&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 {
index 157f5b62c6b7302ba21e5dbd02d381933dcf5e3a..5bdf3e9299f16051c5198f7d6cbf114616077c52 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
 Alex G: Use regmap to read/write registers
+        Remove xpcs_reset deassert logic (to be implemented later)
 Signed-off-by: Alexandru Gagniuc <[email protected]>
 ---
- 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 <[email protected]>
  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 <[email protected]>
                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:
index dff74f022430ac244f34e8c006aa6e9a98cf6e07..fbdebec13acff775c06825e056f27c99991f7f7c 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
 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 <[email protected]>
 ---
- 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 <[email protected]>
  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 <[email protected]>
        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) {
index 9c6bfabc45592d29318ed1c55d398001cbd29daf..37aa60d8ff092d615cc9c6e66f425dd99a082d23 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
 Signed-off-by: Alexandru Gagniuc <[email protected]>
 ---
- 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 <[email protected]>
                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);
index 03fa4dffefa7ba8741b75ceda0b68727bcb4a0bb..2563ac8396024609c129b62a43cea0a0bea7eee7 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
 Signed-off-by: Alexandru Gagniuc <[email protected]>
 ---
- 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 <[email protected]>
  #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 <[email protected]>
 +#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 <[email protected]>
 +              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 <[email protected]>
  
        /* 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 <[email protected]>
 +              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 <[email protected]>
                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:
index b34dd837ab1ebae8ee57d0e8ce06d5c19a929193..6ec8f2634ef13d1ed182bb87e9fbe046ab51662b 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
 
 --- 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 <[email protected]>
  #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 <[email protected]>
                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 (file)
index 58e2be3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From ccdfd293f9e948f0f62ac4e9924d72539a4e81ee Mon Sep 17 00:00:00 2001
-From: Mantas Pucka <[email protected]>
-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 <[email protected]>
----
- 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 */
index 980b8d0379afb80156104c5e6adb38c43109cecf..b02782e7b399365540cae76ca7b117a99fdba9ff 100644 (file)
@@ -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 <[email protected]>
 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 <[email protected]>
 
 --- 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 (file)
index 0000000..63a523a
--- /dev/null
@@ -0,0 +1,282 @@
+From b4e07a8a3ec3dc5f676238987556e2aff0b14028 Mon Sep 17 00:00:00 2001
+From: Lei Wei <[email protected]>
+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 <[email protected]>
+Signed-off-by: Alexandru Gagniuc <[email protected]>
+---
+ .../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 <dt-bindings/clock/qcom,ipq9574-gcc.h>
++    #include <dt-bindings/reset/qcom,ipq9574-gcc.h>
+     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 <linux/phylink.h>
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
++#include <linux/reset.h>
+ #include <dt-bindings/net/qcom,ipq9574-pcs.h>
+@@ -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;