]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
airoha: add pending patch for USB support on AN7581
authorChristian Marangi <ansuelsmth@gmail.com>
Tue, 28 Oct 2025 12:14:56 +0000 (13:14 +0100)
committerChristian Marangi <ansuelsmth@gmail.com>
Mon, 10 Nov 2025 17:20:40 +0000 (18:20 +0100)
Add pending patch for USB support on AN7581 SoC. This is also required
to make operational the 3rd PCIe line that use the USB2 Serdes for PCIe
operations.

(cherry picked from commit 7afc2da3fcc01a3932829ed4fb3ced6876b71846)
[ fix conflict errors, add missing Kconfig flag ]
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
target/linux/airoha/an7581/config-6.6
target/linux/airoha/patches-6.6/220-04-dt-bindings-soc-Add-bindings-for-Airoha-SCU-Serdes-l.patch [new file with mode: 0644]
target/linux/airoha/patches-6.6/220-05-dt-bindings-phy-Add-documentation-for-Airoha-AN7581-.patch [new file with mode: 0644]
target/linux/airoha/patches-6.6/220-06-phy-move-Airoha-PCIe-PHY-driver-to-dedicated-directo.patch [new file with mode: 0644]
target/linux/airoha/patches-6.6/220-07-phy-airoha-Add-support-for-Airoha-AN7581-USB-PHY.patch [new file with mode: 0644]
target/linux/airoha/patches-6.6/220-08-usb-host-add-ARCH_AIROHA-in-XHCI-MTK-dependency.patch [new file with mode: 0644]
target/linux/airoha/patches-6.6/220-10-PCI-mediatek-gen3-set-PHY-mode-for-Airoha-EN7581.patch [new file with mode: 0644]

index 8d253214f7c9b2d3e18f4584d73b6d07f03e9a90..9d2251c5c84a0c8e4ac1c20f1ac692a33b7d70bf 100644 (file)
@@ -458,6 +458,7 @@ CONFIG_PHYLIB_LEDS=y
 CONFIG_PHYLINK=y
 CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_PHY_AIROHA_PCIE=y
+CONFIG_PHY_AIROHA_USB=y
 CONFIG_PID_NS=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_AIROHA=y
diff --git a/target/linux/airoha/patches-6.6/220-04-dt-bindings-soc-Add-bindings-for-Airoha-SCU-Serdes-l.patch b/target/linux/airoha/patches-6.6/220-04-dt-bindings-soc-Add-bindings-for-Airoha-SCU-Serdes-l.patch
new file mode 100644 (file)
index 0000000..3fa8d6d
--- /dev/null
@@ -0,0 +1,35 @@
+From 39537b6b334dfac001aba395229adb9318627463 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 28 Oct 2025 12:09:57 +0100
+Subject: [PATCH 04/10] dt-bindings: soc: Add bindings for Airoha SCU Serdes
+ lines
+
+The Airoha AN7581 SoC have can configure the SCU serdes lines for
+multiple purpose. For example the Serdes for the USB1 port can be both
+used for USB 3.0 operation or for Ethernet. Or the USB2 serdes can both
+used for USB 3.0 operation or for PCIe.
+
+Add bindings to permit correct reference of the different ports in DT,
+mostly to differenciate the different supported modes internally to the
+drivers.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ include/dt-bindings/soc/airoha,scu-ssr.h | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+ create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h
+
+--- /dev/null
++++ b/include/dt-bindings/soc/airoha,scu-ssr.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++
++#ifndef __DT_BINDINGS_AIROHA_SCU_SSR_H
++#define __DT_BINDINGS_AIROHA_SCU_SSR_H
++
++#define AIROHA_SCU_SERDES_WIFI1               0
++#define AIROHA_SCU_SERDES_WIFI2               1
++#define AIROHA_SCU_SERDES_USB1                2
++#define AIROHA_SCU_SERDES_USB2                3
++
++#endif /* __DT_BINDINGS_AIROHA_SCU_SSR_H */
diff --git a/target/linux/airoha/patches-6.6/220-05-dt-bindings-phy-Add-documentation-for-Airoha-AN7581-.patch b/target/linux/airoha/patches-6.6/220-05-dt-bindings-phy-Add-documentation-for-Airoha-AN7581-.patch
new file mode 100644 (file)
index 0000000..3fc0ba7
--- /dev/null
@@ -0,0 +1,141 @@
+From e0095e21dd9179250c304d6df2643e9a50d48edb Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 7 Feb 2025 13:25:28 +0100
+Subject: [PATCH 05/10] dt-bindings: phy: Add documentation for Airoha AN7581
+ USB PHY
+
+Add documentation for Airoha AN7581 USB PHY that describe the USB PHY
+for the USB controller.
+
+Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
+always supported. The USB 3.0 mode is optional and depends on the Serdes
+mode currently configured on the system for the USB port.
+
+If the airoha,serdes-port property is not declared, it's assumed USB 3.0
+mode is not supported, as the Serdes mode can't be validated.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ .../bindings/phy/airoha,an7581-usb-phy.yaml   | 83 +++++++++++++++++++
+ MAINTAINERS                                   |  7 ++
+ .../dt-bindings/phy/airoha,an7581-usb-phy.h   | 11 +++
+ 3 files changed, 101 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
+ create mode 100644 include/dt-bindings/phy/airoha,an7581-usb-phy.h
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
+@@ -0,0 +1,83 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Airoha AN7581 SoC USB PHY
++
++maintainers:
++  - Christian Marangi <ansuelsmth@gmail.com>
++
++description: >
++  The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller.
++
++  Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is
++  always supported. The USB 3.0 mode is optional and depends on the Serdes
++  mode currently configured on the system for the USB port.
++
++  If the airoha,serdes-port property is not declared, it's assumed USB 3.0
++  mode is not supported, as the Serdes mode can't be validated.
++
++properties:
++  compatible:
++    const: airoha,an7581-usb-phy
++
++  reg:
++    maxItems: 1
++
++
++  airoha,usb2-monitor-clk-sel:
++    description: Describe what oscillator across the available 4
++      should be selected for USB 2.0 Slew Rate calibration.
++    $ref: /schemas/types.yaml#/definitions/uint32
++    enum: [0, 1, 2, 3]
++
++  airoha,serdes-port:
++    description: Describe what Serdes Port is attached to the USB 3.0 port.
++    $ref: /schemas/types.yaml#/definitions/uint32
++    enum: [0, 1, 2, 3]
++
++  airoha,scu:
++    description: Phandle to the SCU node for USB 3.0 Serdes mode validation.
++    $ref: /schemas/types.yaml#/definitions/phandle
++
++  '#phy-cells':
++    const: 1
++
++required:
++  - compatible
++  - reg
++  - airoha,usb2-monitor-clk-sel
++  - '#phy-cells'
++
++dependentRequired:
++  airoha,serdes-port: [ 'airoha,scu' ]
++
++additionalProperties: false
++
++examples:
++  - |
++    #include <dt-bindings/phy/airoha,an7581-usb-phy.h>
++    #include <dt-bindings/soc/airoha,scu-ssr.h>
++
++    phy@1fac0000 {
++        compatible = "airoha,an7581-usb-phy";
++        reg = <0x1fac0000 0x10000>;
++
++        airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL1>;
++        airoha,scu = <&scu>;
++        airoha,serdes-port = <AIROHA_SCU_SERDES_USB1>;
++
++        #phy-cells = <1>;
++    };
++
++    phy@1fae0000 {
++        compatible = "airoha,an7581-usb-phy";
++        reg = <0x1fae0000 0x10000>;
++
++        airoha,usb2-monitor-clk-sel = <AIROHA_USB2_MONCLK_SEL2>;
++
++        #phy-cells = <1>;
++    };
++
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -737,6 +737,13 @@ S:        Maintained
+ F:    Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml
+ F:    drivers/spi/spi-airoha-snfi.c
++AIROHA USB PHY DRIVER
++M:    Christian Marangi <ansuelsmth@gmail.com>
++L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
++S:    Maintained
++F:    Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
++F:    include/dt-bindings/phy/airoha,an7581-usb-phy.h
++
+ AIRSPY MEDIA DRIVER
+ L:    linux-media@vger.kernel.org
+ S:    Orphan
+--- /dev/null
++++ b/include/dt-bindings/phy/airoha,an7581-usb-phy.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
++
++#ifndef _DT_BINDINGS_AIROHA_AN7581_USB_PHY_H_
++#define _DT_BINDINGS_AIROHA_AN7581_USB_PHY_H_
++
++#define AIROHA_USB2_MONCLK_SEL0                 0
++#define AIROHA_USB2_MONCLK_SEL1                 1
++#define AIROHA_USB2_MONCLK_SEL2                 2
++#define AIROHA_USB2_MONCLK_SEL3                 3
++
++#endif
diff --git a/target/linux/airoha/patches-6.6/220-06-phy-move-Airoha-PCIe-PHY-driver-to-dedicated-directo.patch b/target/linux/airoha/patches-6.6/220-06-phy-move-Airoha-PCIe-PHY-driver-to-dedicated-directo.patch
new file mode 100644 (file)
index 0000000..e61de04
--- /dev/null
@@ -0,0 +1,1885 @@
+From 1bfe1cc581ffba2462580496507497840aa018aa Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Wed, 19 Mar 2025 15:23:50 +0100
+Subject: [PATCH 06/10] phy: move Airoha PCIe PHY driver to dedicated directory
+
+To keep the generic PHY directory tidy, move the PCIe PHY driver to a
+dedicated directory.
+
+This is also in preparation for support of the Airoha USB PHY driver.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ MAINTAINERS                               |    4 +-
+ drivers/phy/Kconfig                       |   11 +-
+ drivers/phy/Makefile                      |    5 +-
+ drivers/phy/airoha/Kconfig                |   13 +
+ drivers/phy/airoha/Makefile               |    3 +
+ drivers/phy/airoha/phy-airoha-pcie-regs.h |  494 ++++++++
+ drivers/phy/airoha/phy-airoha-pcie.c      | 1290 +++++++++++++++++++++
+ 7 files changed, 1806 insertions(+), 14 deletions(-)
+ create mode 100644 drivers/phy/airoha/Kconfig
+ create mode 100644 drivers/phy/airoha/Makefile
+ create mode 100644 drivers/phy/airoha/phy-airoha-pcie-regs.h
+ create mode 100644 drivers/phy/airoha/phy-airoha-pcie.c
+
+# diff --git a/MAINTAINERS b/MAINTAINERS
+# index 2468f4fea5b7..3f930a613658 100644
+# --- a/MAINTAINERS
+# +++ b/MAINTAINERS
+# @@ -733,8 +733,8 @@ M:       Lorenzo Bianconi <lorenzo@kernel.org>
+#  L:  linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+#  S:  Maintained
+#  F:  Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
+# -F:  drivers/phy/phy-airoha-pcie-regs.h
+# -F:  drivers/phy/phy-airoha-pcie.c
+# +F:  drivers/phy/airoha/phy-airoha-pcie-regs.h
+# +F:  drivers/phy/airoha/phy-airoha-pcie.c
+#  AIROHA SPI SNFI DRIVER
+#  M:  Lorenzo Bianconi <lorenzo@kernel.org>
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -72,16 +72,7 @@ config PHY_CAN_TRANSCEIVER
+         functional modes using gpios and sets the attribute max link
+         rate, for CAN drivers.
+-config PHY_AIROHA_PCIE
+-      tristate "Airoha PCIe-PHY Driver"
+-      depends on ARCH_AIROHA || COMPILE_TEST
+-      depends on OF
+-      select GENERIC_PHY
+-      help
+-        Say Y here to add support for Airoha PCIe PHY driver.
+-        This driver create the basic PHY instance and provides initialize
+-        callback for PCIe GEN3 port.
+-
++source "drivers/phy/airoha/Kconfig"
+ source "drivers/phy/allwinner/Kconfig"
+ source "drivers/phy/amlogic/Kconfig"
+ source "drivers/phy/broadcom/Kconfig"
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -10,8 +10,8 @@ obj-$(CONFIG_PHY_LPC18XX_USB_OTG)    += phy
+ obj-$(CONFIG_PHY_XGENE)                       += phy-xgene.o
+ obj-$(CONFIG_PHY_PISTACHIO_USB)               += phy-pistachio-usb.o
+ obj-$(CONFIG_USB_LGM_PHY)             += phy-lgm-usb.o
+-obj-$(CONFIG_PHY_AIROHA_PCIE)         += phy-airoha-pcie.o
+-obj-y                                 += allwinner/   \
++obj-y                                 += airoha/      \
++                                         allwinner/   \
+                                          amlogic/     \
+                                          broadcom/    \
+                                          cadence/     \
+--- /dev/null
++++ b/drivers/phy/airoha/Kconfig
+@@ -0,0 +1,13 @@
++# SPDX-License-Identifier: GPL-2.0-only
++#
++# Phy drivers for Airoha devices
++#
++config PHY_AIROHA_PCIE
++      tristate "Airoha PCIe-PHY Driver"
++      depends on ARCH_AIROHA || COMPILE_TEST
++      depends on OF
++      select GENERIC_PHY
++      help
++        Say Y here to add support for Airoha PCIe PHY driver.
++        This driver create the basic PHY instance and provides initialize
++        callback for PCIe GEN3 port.
+--- /dev/null
++++ b/drivers/phy/airoha/Makefile
+@@ -0,0 +1,3 @@
++# SPDX-License-Identifier: GPL-2.0
++
++obj-$(CONFIG_PHY_AIROHA_PCIE)         += phy-airoha-pcie.o
+--- /dev/null
++++ b/drivers/phy/airoha/phy-airoha-pcie-regs.h
+@@ -0,0 +1,494 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (c) 2024 AIROHA Inc
++ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
++ */
++
++#ifndef _PHY_AIROHA_PCIE_H
++#define _PHY_AIROHA_PCIE_H
++
++/* CSR_2L */
++#define REG_CSR_2L_CMN                                0x0000
++#define CSR_2L_PXP_CMN_LANE_EN                        BIT(0)
++#define CSR_2L_PXP_CMN_TRIM_MASK              GENMASK(28, 24)
++
++#define REG_CSR_2L_JCPLL_IB_EXT                       0x0004
++#define REG_CSR_2L_JCPLL_LPF_SHCK_EN          BIT(8)
++#define CSR_2L_PXP_JCPLL_CHP_IBIAS            GENMASK(21, 16)
++#define CSR_2L_PXP_JCPLL_CHP_IOFST            GENMASK(29, 24)
++
++#define REG_CSR_2L_JCPLL_LPF_BR                       0x0008
++#define CSR_2L_PXP_JCPLL_LPF_BR                       GENMASK(4, 0)
++#define CSR_2L_PXP_JCPLL_LPF_BC                       GENMASK(12, 8)
++#define CSR_2L_PXP_JCPLL_LPF_BP                       GENMASK(20, 16)
++#define CSR_2L_PXP_JCPLL_LPF_BWR              GENMASK(28, 24)
++
++#define REG_CSR_2L_JCPLL_LPF_BWC              0x000c
++#define CSR_2L_PXP_JCPLL_LPF_BWC              GENMASK(4, 0)
++#define CSR_2L_PXP_JCPLL_KBAND_CODE           GENMASK(23, 16)
++#define CSR_2L_PXP_JCPLL_KBAND_DIV            GENMASK(26, 24)
++
++#define REG_CSR_2L_JCPLL_KBAND_KFC            0x0010
++#define CSR_2L_PXP_JCPLL_KBAND_KFC            GENMASK(1, 0)
++#define CSR_2L_PXP_JCPLL_KBAND_KF             GENMASK(9, 8)
++#define CSR_2L_PXP_JCPLL_KBAND_KS             GENMASK(17, 16)
++#define CSR_2L_PXP_JCPLL_POSTDIV_EN           BIT(24)
++
++#define REG_CSR_2L_JCPLL_MMD_PREDIV_MODE      0x0014
++#define CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE      GENMASK(1, 0)
++#define CSR_2L_PXP_JCPLL_POSTDIV_D2           BIT(16)
++#define CSR_2L_PXP_JCPLL_POSTDIV_D5           BIT(24)
++
++#define CSR_2L_PXP_JCPLL_MONCK                        0x0018
++#define CSR_2L_PXP_JCPLL_REFIN_DIV            GENMASK(25, 24)
++
++#define REG_CSR_2L_JCPLL_RST_DLY              0x001c
++#define CSR_2L_PXP_JCPLL_RST_DLY              GENMASK(2, 0)
++#define CSR_2L_PXP_JCPLL_RST                  BIT(8)
++#define CSR_2L_PXP_JCPLL_SDM_DI_EN            BIT(16)
++#define CSR_2L_PXP_JCPLL_SDM_DI_LS            GENMASK(25, 24)
++
++#define REG_CSR_2L_JCPLL_SDM_IFM              0x0020
++#define CSR_2L_PXP_JCPLL_SDM_IFM              BIT(0)
++
++#define REG_CSR_2L_JCPLL_SDM_HREN             0x0024
++#define CSR_2L_PXP_JCPLL_SDM_HREN             BIT(0)
++#define CSR_2L_PXP_JCPLL_TCL_AMP_EN           BIT(8)
++#define CSR_2L_PXP_JCPLL_TCL_AMP_GAIN         GENMASK(18, 16)
++#define CSR_2L_PXP_JCPLL_TCL_AMP_VREF         GENMASK(28, 24)
++
++#define REG_CSR_2L_JCPLL_TCL_CMP              0x0028
++#define CSR_2L_PXP_JCPLL_TCL_LPF_EN           BIT(16)
++#define CSR_2L_PXP_JCPLL_TCL_LPF_BW           GENMASK(26, 24)
++
++#define REG_CSR_2L_JCPLL_VCODIV                       0x002c
++#define CSR_2L_PXP_JCPLL_VCO_CFIX             GENMASK(9, 8)
++#define CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN               BIT(16)
++#define CSR_2L_PXP_JCPLL_VCO_SCAPWR           GENMASK(26, 24)
++
++#define REG_CSR_2L_JCPLL_VCO_TCLVAR           0x0030
++#define CSR_2L_PXP_JCPLL_VCO_TCLVAR           GENMASK(2, 0)
++
++#define REG_CSR_2L_JCPLL_SSC                          0x0038
++#define CSR_2L_PXP_JCPLL_SSC_EN                       BIT(0)
++#define CSR_2L_PXP_JCPLL_SSC_PHASE_INI                BIT(8)
++#define CSR_2L_PXP_JCPLL_SSC_TRI_EN           BIT(16)
++
++#define REG_CSR_2L_JCPLL_SSC_DELTA1           0x003c
++#define CSR_2L_PXP_JCPLL_SSC_DELTA1           GENMASK(15, 0)
++#define CSR_2L_PXP_JCPLL_SSC_DELTA            GENMASK(31, 16)
++
++#define REG_CSR_2L_JCPLL_SSC_PERIOD           0x0040
++#define CSR_2L_PXP_JCPLL_SSC_PERIOD           GENMASK(15, 0)
++
++#define REG_CSR_2L_JCPLL_TCL_VTP_EN           0x004c
++#define CSR_2L_PXP_JCPLL_SPARE_LOW            GENMASK(31, 24)
++
++#define REG_CSR_2L_JCPLL_TCL_KBAND_VREF               0x0050
++#define CSR_2L_PXP_JCPLL_TCL_KBAND_VREF               GENMASK(4, 0)
++#define CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN    BIT(24)
++
++#define REG_CSR_2L_750M_SYS_CK                        0x0054
++#define CSR_2L_PXP_TXPLL_LPF_SHCK_EN          BIT(16)
++#define CSR_2L_PXP_TXPLL_CHP_IBIAS            GENMASK(29, 24)
++
++#define REG_CSR_2L_TXPLL_CHP_IOFST            0x0058
++#define CSR_2L_PXP_TXPLL_CHP_IOFST            GENMASK(5, 0)
++#define CSR_2L_PXP_TXPLL_LPF_BR                       GENMASK(12, 8)
++#define CSR_2L_PXP_TXPLL_LPF_BC                       GENMASK(20, 16)
++#define CSR_2L_PXP_TXPLL_LPF_BP                       GENMASK(28, 24)
++
++#define REG_CSR_2L_TXPLL_LPF_BWR              0x005c
++#define CSR_2L_PXP_TXPLL_LPF_BWR              GENMASK(4, 0)
++#define CSR_2L_PXP_TXPLL_LPF_BWC              GENMASK(12, 8)
++#define CSR_2L_PXP_TXPLL_KBAND_CODE           GENMASK(31, 24)
++
++#define REG_CSR_2L_TXPLL_KBAND_DIV            0x0060
++#define CSR_2L_PXP_TXPLL_KBAND_DIV            GENMASK(2, 0)
++#define CSR_2L_PXP_TXPLL_KBAND_KFC            GENMASK(9, 8)
++#define CSR_2L_PXP_TXPLL_KBAND_KF             GENMASK(17, 16)
++#define CSR_2L_PXP_txpll_KBAND_KS             GENMASK(25, 24)
++
++#define REG_CSR_2L_TXPLL_POSTDIV              0x0064
++#define CSR_2L_PXP_TXPLL_POSTDIV_EN           BIT(0)
++#define CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE      GENMASK(9, 8)
++#define CSR_2L_PXP_TXPLL_PHY_CK1_EN           BIT(24)
++
++#define REG_CSR_2L_TXPLL_PHY_CK2              0x0068
++#define CSR_2L_PXP_TXPLL_REFIN_INTERNAL               BIT(24)
++
++#define REG_CSR_2L_TXPLL_REFIN_DIV            0x006c
++#define CSR_2L_PXP_TXPLL_REFIN_DIV            GENMASK(1, 0)
++#define CSR_2L_PXP_TXPLL_RST_DLY              GENMASK(10, 8)
++#define CSR_2L_PXP_TXPLL_PLL_RSTB             BIT(16)
++
++#define REG_CSR_2L_TXPLL_SDM_DI_LS            0x0070
++#define CSR_2L_PXP_TXPLL_SDM_DI_LS            GENMASK(1, 0)
++#define CSR_2L_PXP_TXPLL_SDM_IFM              BIT(8)
++#define CSR_2L_PXP_TXPLL_SDM_ORD              GENMASK(25, 24)
++
++#define REG_CSR_2L_TXPLL_SDM_OUT              0x0074
++#define CSR_2L_PXP_TXPLL_TCL_AMP_EN           BIT(16)
++#define CSR_2L_PXP_TXPLL_TCL_AMP_GAIN         GENMASK(26, 24)
++
++#define REG_CSR_2L_TXPLL_TCL_AMP_VREF         0x0078
++#define CSR_2L_PXP_TXPLL_TCL_AMP_VREF         GENMASK(4, 0)
++#define CSR_2L_PXP_TXPLL_TCL_LPF_EN           BIT(24)
++
++#define REG_CSR_2L_TXPLL_TCL_LPF_BW           0x007c
++#define CSR_2L_PXP_TXPLL_TCL_LPF_BW           GENMASK(2, 0)
++#define CSR_2L_PXP_TXPLL_VCO_CFIX             GENMASK(17, 16)
++#define CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN               BIT(24)
++
++#define REG_CSR_2L_TXPLL_VCO_SCAPWR           0x0080
++#define CSR_2L_PXP_TXPLL_VCO_SCAPWR           GENMASK(2, 0)
++
++#define REG_CSR_2L_TXPLL_SSC                  0x0084
++#define CSR_2L_PXP_TXPLL_SSC_EN                       BIT(0)
++#define CSR_2L_PXP_TXPLL_SSC_PHASE_INI                BIT(8)
++
++#define REG_CSR_2L_TXPLL_SSC_DELTA1           0x0088
++#define CSR_2L_PXP_TXPLL_SSC_DELTA1           GENMASK(15, 0)
++#define CSR_2L_PXP_TXPLL_SSC_DELTA            GENMASK(31, 16)
++
++#define REG_CSR_2L_TXPLL_SSC_PERIOD           0x008c
++#define CSR_2L_PXP_txpll_SSC_PERIOD           GENMASK(15, 0)
++
++#define REG_CSR_2L_TXPLL_VTP                  0x0090
++#define CSR_2L_PXP_TXPLL_VTP_EN                       BIT(0)
++
++#define REG_CSR_2L_TXPLL_TCL_VTP              0x0098
++#define CSR_2L_PXP_TXPLL_SPARE_L              GENMASK(31, 24)
++
++#define REG_CSR_2L_TXPLL_TCL_KBAND_VREF               0x009c
++#define CSR_2L_PXP_TXPLL_TCL_KBAND_VREF               GENMASK(4, 0)
++#define CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN    BIT(24)
++
++#define REG_CSR_2L_TXPLL_POSTDIV_D256         0x00a0
++#define CSR_2L_PXP_CLKTX0_AMP                 GENMASK(10, 8)
++#define CSR_2L_PXP_CLKTX0_OFFSET              GENMASK(17, 16)
++#define CSR_2L_PXP_CLKTX0_SR                  GENMASK(25, 24)
++
++#define REG_CSR_2L_CLKTX0_FORCE_OUT1          0x00a4
++#define CSR_2L_PXP_CLKTX0_HZ                  BIT(8)
++#define CSR_2L_PXP_CLKTX0_IMP_SEL             GENMASK(20, 16)
++#define CSR_2L_PXP_CLKTX1_AMP                 GENMASK(26, 24)
++
++#define REG_CSR_2L_CLKTX1_OFFSET              0x00a8
++#define CSR_2L_PXP_CLKTX1_OFFSET              GENMASK(1, 0)
++#define CSR_2L_PXP_CLKTX1_SR                  GENMASK(9, 8)
++#define CSR_2L_PXP_CLKTX1_HZ                  BIT(24)
++
++#define REG_CSR_2L_CLKTX1_IMP_SEL             0x00ac
++#define CSR_2L_PXP_CLKTX1_IMP_SEL             GENMASK(4, 0)
++
++#define REG_CSR_2L_PLL_CMN_RESERVE0           0x00b0
++#define CSR_2L_PXP_PLL_RESERVE_MASK           GENMASK(15, 0)
++
++#define REG_CSR_2L_TX0_CKLDO                  0x00cc
++#define CSR_2L_PXP_TX0_CKLDO_EN                       BIT(0)
++#define CSR_2L_PXP_TX0_DMEDGEGEN_EN           BIT(24)
++
++#define REG_CSR_2L_TX1_CKLDO                  0x00e8
++#define CSR_2L_PXP_TX1_CKLDO_EN                       BIT(0)
++#define CSR_2L_PXP_TX1_DMEDGEGEN_EN           BIT(24)
++
++#define REG_CSR_2L_TX1_MULTLANE                       0x00ec
++#define CSR_2L_PXP_TX1_MULTLANE_EN            BIT(0)
++
++#define REG_CSR_2L_RX0_REV0                   0x00fc
++#define CSR_2L_PXP_VOS_PNINV                  GENMASK(19, 18)
++#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE                GENMASK(22, 20)
++#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE         GENMASK(26, 24)
++
++#define REG_CSR_2L_RX0_PHYCK_DIV              0x0100
++#define CSR_2L_PXP_RX0_PHYCK_SEL              GENMASK(9, 8)
++#define CSR_2L_PXP_RX0_PHYCK_RSTB             BIT(16)
++#define CSR_2L_PXP_RX0_TDC_CK_SEL             BIT(24)
++
++#define REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV     0x0104
++#define CSR_2L_PXP_CDR0_PD_EDGE_DISABLE               BIT(8)
++
++#define REG_CSR_2L_CDR0_LPF_RATIO             0x0110
++#define CSR_2L_PXP_CDR0_LPF_TOP_LIM           GENMASK(26, 8)
++
++#define REG_CSR_2L_CDR0_PR_INJ_MODE           0x011c
++#define CSR_2L_PXP_CDR0_INJ_FORCE_OFF         BIT(24)
++
++#define REG_CSR_2L_CDR0_PR_BETA_DAC           0x0120
++#define CSR_2L_PXP_CDR0_PR_BETA_SEL           GENMASK(19, 16)
++#define CSR_2L_PXP_CDR0_PR_KBAND_DIV          GENMASK(26, 24)
++
++#define REG_CSR_2L_CDR0_PR_VREG_IBAND         0x0124
++#define CSR_2L_PXP_CDR0_PR_VREG_IBAND         GENMASK(2, 0)
++#define CSR_2L_PXP_CDR0_PR_VREG_CKBUF         GENMASK(10, 8)
++
++#define REG_CSR_2L_CDR0_PR_CKREF_DIV          0x0128
++#define CSR_2L_PXP_CDR0_PR_CKREF_DIV          GENMASK(1, 0)
++
++#define REG_CSR_2L_CDR0_PR_MONCK              0x012c
++#define CSR_2L_PXP_CDR0_PR_MONCK_ENABLE               BIT(0)
++#define CSR_2L_PXP_CDR0_PR_RESERVE0           GENMASK(19, 16)
++
++#define REG_CSR_2L_CDR0_PR_COR_HBW            0x0130
++#define CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON               BIT(8)
++#define CSR_2L_PXP_CDR0_PR_CKREF_DIV1         GENMASK(17, 16)
++
++#define REG_CSR_2L_CDR0_PR_MONPI              0x0134
++#define CSR_2L_PXP_CDR0_PR_XFICK_EN           BIT(8)
++
++#define REG_CSR_2L_RX0_SIGDET_DCTEST          0x0140
++#define CSR_2L_PXP_RX0_SIGDET_LPF_CTRL                GENMASK(9, 8)
++#define CSR_2L_PXP_RX0_SIGDET_PEAK            GENMASK(25, 24)
++
++#define REG_CSR_2L_RX0_SIGDET_VTH_SEL         0x0144
++#define CSR_2L_PXP_RX0_SIGDET_VTH_SEL         GENMASK(4, 0)
++#define CSR_2L_PXP_RX0_FE_VB_EQ1_EN           BIT(24)
++
++#define REG_CSR_2L_PXP_RX0_FE_VB_EQ2          0x0148
++#define CSR_2L_PXP_RX0_FE_VB_EQ2_EN           BIT(0)
++#define CSR_2L_PXP_RX0_FE_VB_EQ3_EN           BIT(8)
++#define CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB                BIT(16)
++
++#define REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS     0x0158
++#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS               GENMASK(29, 24)
++
++#define REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS               0x015c
++#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS               GENMASK(5, 0)
++#define CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS               GENMASK(13, 8)
++
++#define REG_CSR_2L_RX1_REV0                   0x01b4
++
++#define REG_CSR_2L_RX1_PHYCK_DIV              0x01b8
++#define CSR_2L_PXP_RX1_PHYCK_SEL              GENMASK(9, 8)
++#define CSR_2L_PXP_RX1_PHYCK_RSTB             BIT(16)
++#define CSR_2L_PXP_RX1_TDC_CK_SEL             BIT(24)
++
++#define REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV     0x01bc
++#define CSR_2L_PXP_CDR1_PD_EDGE_DISABLE               BIT(8)
++
++#define REG_CSR_2L_CDR1_PR_BETA_DAC           0x01d8
++#define CSR_2L_PXP_CDR1_PR_BETA_SEL           GENMASK(19, 16)
++#define CSR_2L_PXP_CDR1_PR_KBAND_DIV          GENMASK(26, 24)
++
++#define REG_CSR_2L_CDR1_PR_MONCK              0x01e4
++#define CSR_2L_PXP_CDR1_PR_MONCK_ENABLE               BIT(0)
++#define CSR_2L_PXP_CDR1_PR_RESERVE0           GENMASK(19, 16)
++
++#define REG_CSR_2L_CDR1_LPF_RATIO             0x01c8
++#define CSR_2L_PXP_CDR1_LPF_TOP_LIM           GENMASK(26, 8)
++
++#define REG_CSR_2L_CDR1_PR_INJ_MODE           0x01d4
++#define CSR_2L_PXP_CDR1_INJ_FORCE_OFF         BIT(24)
++
++#define REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL     0x01dc
++#define CSR_2L_PXP_CDR1_PR_VREG_IBAND         GENMASK(2, 0)
++#define CSR_2L_PXP_CDR1_PR_VREG_CKBUF         GENMASK(10, 8)
++
++#define REG_CSR_2L_CDR1_PR_CKREF_DIV          0x01e0
++#define CSR_2L_PXP_CDR1_PR_CKREF_DIV          GENMASK(1, 0)
++
++#define REG_CSR_2L_CDR1_PR_COR_HBW            0x01e8
++#define CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON               BIT(8)
++#define CSR_2L_PXP_CDR1_PR_CKREF_DIV1         GENMASK(17, 16)
++
++#define REG_CSR_2L_CDR1_PR_MONPI              0x01ec
++#define CSR_2L_PXP_CDR1_PR_XFICK_EN           BIT(8)
++
++#define REG_CSR_2L_RX1_DAC_RANGE_EYE          0x01f4
++#define CSR_2L_PXP_RX1_SIGDET_LPF_CTRL                GENMASK(25, 24)
++
++#define REG_CSR_2L_RX1_SIGDET_NOVTH           0x01f8
++#define CSR_2L_PXP_RX1_SIGDET_PEAK            GENMASK(9, 8)
++#define CSR_2L_PXP_RX1_SIGDET_VTH_SEL         GENMASK(20, 16)
++
++#define REG_CSR_2L_RX1_FE_VB_EQ1              0x0200
++#define CSR_2L_PXP_RX1_FE_VB_EQ1_EN           BIT(0)
++#define CSR_2L_PXP_RX1_FE_VB_EQ2_EN           BIT(8)
++#define CSR_2L_PXP_RX1_FE_VB_EQ3_EN           BIT(16)
++#define CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB                BIT(24)
++
++#define REG_CSR_2L_RX1_OSCAL_VGA1IOS          0x0214
++#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS               GENMASK(5, 0)
++#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS               GENMASK(13, 8)
++#define CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS               GENMASK(21, 16)
++
++/* PMA */
++#define REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1 0x0004
++#define PCIE_LCPLL_MAN_PWDB                   BIT(0)
++
++#define REG_PCIE_PMA_SEQUENCE_DISB_CTRL1      0x010c
++#define PCIE_DISB_RX_SDCAL_EN                 BIT(0)
++
++#define REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1        0x0114
++#define PCIE_FORCE_RX_SDCAL_EN                        BIT(0)
++
++#define REG_PCIE_PMA_SS_RX_FREQ_DET1          0x014c
++#define PCIE_PLL_FT_LOCK_CYCLECNT             GENMASK(15, 0)
++#define PCIE_PLL_FT_UNLOCK_CYCLECNT           GENMASK(31, 16)
++
++#define REG_PCIE_PMA_SS_RX_FREQ_DET2          0x0150
++#define PCIE_LOCK_TARGET_BEG                  GENMASK(15, 0)
++#define PCIE_LOCK_TARGET_END                  GENMASK(31, 16)
++
++#define REG_PCIE_PMA_SS_RX_FREQ_DET3          0x0154
++#define PCIE_UNLOCK_TARGET_BEG                        GENMASK(15, 0)
++#define PCIE_UNLOCK_TARGET_END                        GENMASK(31, 16)
++
++#define REG_PCIE_PMA_SS_RX_FREQ_DET4          0x0158
++#define PCIE_FREQLOCK_DET_EN                  GENMASK(2, 0)
++#define PCIE_LOCK_LOCKTH                      GENMASK(11, 8)
++#define PCIE_UNLOCK_LOCKTH                    GENMASK(15, 12)
++
++#define REG_PCIE_PMA_SS_RX_CAL1                       0x0160
++#define REG_PCIE_PMA_SS_RX_CAL2                       0x0164
++#define PCIE_CAL_OUT_OS                               GENMASK(11, 8)
++
++#define REG_PCIE_PMA_SS_RX_SIGDET0            0x0168
++#define PCIE_SIGDET_WIN_NONVLD_TIMES          GENMASK(28, 24)
++
++#define REG_PCIE_PMA_TX_RESET                 0x0260
++#define PCIE_TX_TOP_RST                               BIT(0)
++#define PCIE_TX_CAL_RST                               BIT(8)
++
++#define REG_PCIE_PMA_RX_FORCE_MODE0           0x0294
++#define PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL    GENMASK(1, 0)
++
++#define REG_PCIE_PMA_SS_DA_XPON_PWDB0         0x034c
++#define PCIE_DA_XPON_CDR_PR_PWDB              BIT(8)
++
++#define REG_PCIE_PMA_SW_RESET                 0x0460
++#define PCIE_SW_RX_FIFO_RST                   BIT(0)
++#define PCIE_SW_RX_RST                                BIT(1)
++#define PCIE_SW_TX_RST                                BIT(2)
++#define PCIE_SW_PMA_RST                               BIT(3)
++#define PCIE_SW_ALLPCS_RST                    BIT(4)
++#define PCIE_SW_REF_RST                               BIT(5)
++#define PCIE_SW_TX_FIFO_RST                   BIT(6)
++#define PCIE_SW_XFI_TXPCS_RST                 BIT(7)
++#define PCIE_SW_XFI_RXPCS_RST                 BIT(8)
++#define PCIE_SW_XFI_RXPCS_BIST_RST            BIT(9)
++#define PCIE_SW_HSG_TXPCS_RST                 BIT(10)
++#define PCIE_SW_HSG_RXPCS_RST                 BIT(11)
++#define PCIE_PMA_SW_RST                               (PCIE_SW_RX_FIFO_RST | \
++                                               PCIE_SW_RX_RST | \
++                                               PCIE_SW_TX_RST | \
++                                               PCIE_SW_PMA_RST | \
++                                               PCIE_SW_ALLPCS_RST | \
++                                               PCIE_SW_REF_RST | \
++                                               PCIE_SW_TX_FIFO_RST | \
++                                               PCIE_SW_XFI_TXPCS_RST | \
++                                               PCIE_SW_XFI_RXPCS_RST | \
++                                               PCIE_SW_XFI_RXPCS_BIST_RST | \
++                                               PCIE_SW_HSG_TXPCS_RST | \
++                                               PCIE_SW_HSG_RXPCS_RST)
++
++#define REG_PCIE_PMA_RO_RX_FREQDET            0x0530
++#define PCIE_RO_FBCK_LOCK                     BIT(0)
++#define PCIE_RO_FL_OUT                                GENMASK(31, 16)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC 0x0794
++#define PCIE_FORCE_DA_PXP_CDR_PR_IDAC         GENMASK(10, 0)
++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC     BIT(16)
++#define PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW   BIT(24)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW       0x0798
++#define PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW               GENMASK(30, 0)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS   0x079c
++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW   BIT(16)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW       0x0800
++#define PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW               GENMASK(30, 0)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB 0x081c
++#define PCIE_FORCE_DA_PXP_CDR_PD_PWDB         BIT(0)
++#define PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB     BIT(8)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C        0x0820
++#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN     BIT(0)
++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN BIT(8)
++#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN     BIT(16)
++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN BIT(24)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB   0x0824
++#define PCIE_FORCE_DA_PXP_CDR_PR_PWDB                 BIT(16)
++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB             BIT(24)
++
++#define REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT    0x0828
++#define PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN      BIT(0)
++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN  BIT(8)
++#define PCIE_FORCE_DA_PXP_JCPLL_EN            BIT(16)
++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_EN                BIT(24)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST 0x0084c
++#define PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB      BIT(16)
++#define PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB  BIT(24)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT 0x0854
++#define PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN      BIT(0)
++#define PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN  BIT(8)
++#define PCIE_FORCE_DA_PXP_TXPLL_EN            BIT(16)
++#define PCIE_FORCE_SEL_DA_PXP_TXPLL_EN                BIT(24)
++
++#define REG_PCIE_PMA_SCAN_MODE                                0x0884
++#define PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN         BIT(0)
++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN     BIT(8)
++
++#define REG_PCIE_PMA_DIG_RESERVE_13           0x08bc
++#define PCIE_FLL_IDAC_PCIEG1                  GENMASK(10, 0)
++#define PCIE_FLL_IDAC_PCIEG2                  GENMASK(26, 16)
++
++#define REG_PCIE_PMA_DIG_RESERVE_14           0x08c0
++#define PCIE_FLL_IDAC_PCIEG3                  GENMASK(10, 0)
++#define PCIE_FLL_LOAD_EN                      BIT(16)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL     0x088c
++#define PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL             GENMASK(1, 0)
++#define PCIE_FORCE_SEL_DA_PXP_RX_FE_GAIN_CTRL         BIT(8)
++
++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB  0x0894
++#define PCIE_FORCE_DA_PXP_RX_FE_PWDB          BIT(0)
++#define PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB      BIT(8)
++
++#define REG_PCIE_PMA_DIG_RESERVE_12           0x08b8
++#define PCIE_FORCE_PMA_RX_SPEED                       GENMASK(7, 4)
++#define PCIE_FORCE_SEL_PMA_RX_SPEED           BIT(7)
++
++#define REG_PCIE_PMA_DIG_RESERVE_17           0x08e0
++
++#define REG_PCIE_PMA_DIG_RESERVE_18           0x08e4
++#define PCIE_PXP_RX_VTH_SEL_PCIE_G1           GENMASK(4, 0)
++#define PCIE_PXP_RX_VTH_SEL_PCIE_G2           GENMASK(12, 8)
++#define PCIE_PXP_RX_VTH_SEL_PCIE_G3           GENMASK(20, 16)
++
++#define REG_PCIE_PMA_DIG_RESERVE_19           0x08e8
++#define PCIE_PCP_RX_REV0_PCIE_GEN1            GENMASK(31, 16)
++
++#define REG_PCIE_PMA_DIG_RESERVE_20           0x08ec
++#define PCIE_PCP_RX_REV0_PCIE_GEN2            GENMASK(15, 0)
++#define PCIE_PCP_RX_REV0_PCIE_GEN3            GENMASK(31, 16)
++
++#define REG_PCIE_PMA_DIG_RESERVE_21           0x08f0
++#define REG_PCIE_PMA_DIG_RESERVE_22           0x08f4
++#define REG_PCIE_PMA_DIG_RESERVE_27           0x0908
++#define REG_PCIE_PMA_DIG_RESERVE_30           0x0914
++
++/* DTIME */
++#define REG_PCIE_PEXTP_DIG_GLB44              0x00
++#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL      GENMASK(7, 0)
++#define PCIE_XTP_RXDET_EN_STB_T_SEL           GENMASK(15, 8)
++#define PCIE_XTP_RXDET_FINISH_STB_T_SEL               GENMASK(23, 16)
++#define PCIE_XTP_TXPD_TX_DATA_EN_DLY          GENMASK(27, 24)
++#define PCIE_XTP_TXPD_RXDET_DONE_CDT          BIT(28)
++#define PCIE_XTP_RXDET_LATCH_STB_T_SEL                GENMASK(31, 29)
++
++/* RX AEQ */
++#define REG_PCIE_PEXTP_DIG_LN_RX30_P0         0x0000
++#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT   GENMASK(7, 0)
++#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN     BIT(8)
++#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT    GENMASK(31, 16)
++
++#define REG_PCIE_PEXTP_DIG_LN_RX30_P1         0x0100
++
++#endif /* _PHY_AIROHA_PCIE_H */
+--- /dev/null
++++ b/drivers/phy/airoha/phy-airoha-pcie.c
+@@ -0,0 +1,1290 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (c) 2024 AIROHA Inc
++ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
++ */
++
++#include <linux/bitfield.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/phy/phy.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include "phy-airoha-pcie-regs.h"
++
++#define LEQ_LEN_CTRL_MAX_VAL  7
++#define FREQ_LOCK_MAX_ATTEMPT 10
++
++/* PCIe-PHY initialization time in ms needed by the hw to complete */
++#define PHY_HW_INIT_TIME_MS   30
++
++enum airoha_pcie_port_gen {
++      PCIE_PORT_GEN1 = 1,
++      PCIE_PORT_GEN2,
++      PCIE_PORT_GEN3,
++};
++
++/**
++ * struct airoha_pcie_phy - PCIe phy driver main structure
++ * @dev: pointer to device
++ * @phy: pointer to generic phy
++ * @csr_2l: Analogic lane IO mapped register base address
++ * @pma0: IO mapped register base address of PMA0-PCIe
++ * @pma1: IO mapped register base address of PMA1-PCIe
++ * @p0_xr_dtime: IO mapped register base address of port0 Tx-Rx detection time
++ * @p1_xr_dtime: IO mapped register base address of port1 Tx-Rx detection time
++ * @rx_aeq: IO mapped register base address of Rx AEQ training
++ */
++struct airoha_pcie_phy {
++      struct device *dev;
++      struct phy *phy;
++      void __iomem *csr_2l;
++      void __iomem *pma0;
++      void __iomem *pma1;
++      void __iomem *p0_xr_dtime;
++      void __iomem *p1_xr_dtime;
++      void __iomem *rx_aeq;
++};
++
++static void airoha_phy_clear_bits(void __iomem *reg, u32 mask)
++{
++      u32 val = readl(reg) & ~mask;
++
++      writel(val, reg);
++}
++
++static void airoha_phy_set_bits(void __iomem *reg, u32 mask)
++{
++      u32 val = readl(reg) | mask;
++
++      writel(val, reg);
++}
++
++static void airoha_phy_update_bits(void __iomem *reg, u32 mask, u32 val)
++{
++      u32 tmp = readl(reg);
++
++      tmp &= ~mask;
++      tmp |= val & mask;
++      writel(tmp, reg);
++}
++
++#define airoha_phy_update_field(reg, mask, val)                                       \
++      do {                                                                    \
++              BUILD_BUG_ON_MSG(!__builtin_constant_p((mask)),                 \
++                               "mask is not constant");                       \
++              airoha_phy_update_bits((reg), (mask),                           \
++                                     FIELD_PREP((mask), (val)));              \
++      } while (0)
++
++#define airoha_phy_csr_2l_clear_bits(pcie_phy, reg, mask)                     \
++      airoha_phy_clear_bits((pcie_phy)->csr_2l + (reg), (mask))
++#define airoha_phy_csr_2l_set_bits(pcie_phy, reg, mask)                               \
++      airoha_phy_set_bits((pcie_phy)->csr_2l + (reg), (mask))
++#define airoha_phy_csr_2l_update_field(pcie_phy, reg, mask, val)              \
++      airoha_phy_update_field((pcie_phy)->csr_2l + (reg), (mask), (val))
++#define airoha_phy_pma0_clear_bits(pcie_phy, reg, mask)                               \
++      airoha_phy_clear_bits((pcie_phy)->pma0 + (reg), (mask))
++#define airoha_phy_pma1_clear_bits(pcie_phy, reg, mask)                               \
++      airoha_phy_clear_bits((pcie_phy)->pma1 + (reg), (mask))
++#define airoha_phy_pma0_set_bits(pcie_phy, reg, mask)                         \
++      airoha_phy_set_bits((pcie_phy)->pma0 + (reg), (mask))
++#define airoha_phy_pma1_set_bits(pcie_phy, reg, mask)                         \
++      airoha_phy_set_bits((pcie_phy)->pma1 + (reg), (mask))
++#define airoha_phy_pma0_update_field(pcie_phy, reg, mask, val)                        \
++      airoha_phy_update_field((pcie_phy)->pma0 + (reg), (mask), (val))
++#define airoha_phy_pma1_update_field(pcie_phy, reg, mask, val)                        \
++      airoha_phy_update_field((pcie_phy)->pma1 + (reg), (mask), (val))
++
++static void
++airoha_phy_init_lane0_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy,
++                                    enum airoha_pcie_port_gen gen)
++{
++      u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941;
++      u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767;
++      u32 pr_idac, val, cdr_pr_idac_tmp = 0;
++      int i;
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1,
++                               PCIE_LCPLL_MAN_PWDB);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
++                                   PCIE_LOCK_TARGET_BEG,
++                                   fl_out_target - 100);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
++                                   PCIE_LOCK_TARGET_END,
++                                   fl_out_target + 100);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
++                                   PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                   PCIE_LOCK_LOCKTH, 0x3);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
++                                   PCIE_UNLOCK_TARGET_BEG,
++                                   fl_out_target - 100);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
++                                   PCIE_UNLOCK_TARGET_END,
++                                   fl_out_target + 100);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
++                                   PCIE_PLL_FT_UNLOCK_CYCLECNT,
++                                   lock_cyclecnt);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                   PCIE_UNLOCK_LOCKTH, 0x3);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE,
++                                 CSR_2L_PXP_CDR0_INJ_FORCE_OFF);
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                               PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                                 PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                                 PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                               PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
++
++      for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) {
++              airoha_phy_pma0_update_field(pcie_phy,
++                              REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                              PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8);
++              airoha_phy_pma0_clear_bits(pcie_phy,
++                                         REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                         PCIE_FREQLOCK_DET_EN);
++              airoha_phy_pma0_update_field(pcie_phy,
++                                           REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                           PCIE_FREQLOCK_DET_EN, 0x3);
++
++              usleep_range(10000, 15000);
++
++              val = FIELD_GET(PCIE_RO_FL_OUT,
++                              readl(pcie_phy->pma0 +
++                                    REG_PCIE_PMA_RO_RX_FREQDET));
++              if (val > fl_out_target)
++                      cdr_pr_idac_tmp = i << 8;
++      }
++
++      for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) {
++              pr_idac = cdr_pr_idac_tmp | (0x1 << i);
++              airoha_phy_pma0_update_field(pcie_phy,
++                              REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                              PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac);
++              airoha_phy_pma0_clear_bits(pcie_phy,
++                                         REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                         PCIE_FREQLOCK_DET_EN);
++              airoha_phy_pma0_update_field(pcie_phy,
++                                           REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                           PCIE_FREQLOCK_DET_EN, 0x3);
++
++              usleep_range(10000, 15000);
++
++              val = FIELD_GET(PCIE_RO_FL_OUT,
++                              readl(pcie_phy->pma0 +
++                                    REG_PCIE_PMA_RO_RX_FREQDET));
++              if (val < fl_out_target)
++                      pr_idac &= ~(0x1 << i);
++
++              cdr_pr_idac_tmp = pr_idac;
++      }
++
++      airoha_phy_pma0_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                                   PCIE_FORCE_DA_PXP_CDR_PR_IDAC,
++                                   cdr_pr_idac_tmp);
++
++      for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) {
++              u32 val;
++
++              airoha_phy_pma0_clear_bits(pcie_phy,
++                                         REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                         PCIE_FREQLOCK_DET_EN);
++              airoha_phy_pma0_update_field(pcie_phy,
++                                           REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                           PCIE_FREQLOCK_DET_EN, 0x3);
++
++              usleep_range(10000, 15000);
++
++              val = readl(pcie_phy->pma0 + REG_PCIE_PMA_RO_RX_FREQDET);
++              if (val & PCIE_RO_FBCK_LOCK)
++                      break;
++      }
++
++      /* turn off force mode and update band values */
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE,
++                                   CSR_2L_PXP_CDR0_INJ_FORCE_OFF);
++
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
++      if (gen == PCIE_PORT_GEN3) {
++              airoha_phy_pma0_update_field(pcie_phy,
++                                           REG_PCIE_PMA_DIG_RESERVE_14,
++                                           PCIE_FLL_IDAC_PCIEG3,
++                                           cdr_pr_idac_tmp);
++      } else {
++              airoha_phy_pma0_update_field(pcie_phy,
++                                           REG_PCIE_PMA_DIG_RESERVE_13,
++                                           PCIE_FLL_IDAC_PCIEG1,
++                                           cdr_pr_idac_tmp);
++              airoha_phy_pma0_update_field(pcie_phy,
++                                           REG_PCIE_PMA_DIG_RESERVE_13,
++                                           PCIE_FLL_IDAC_PCIEG2,
++                                           cdr_pr_idac_tmp);
++      }
++}
++
++static void
++airoha_phy_init_lane1_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy,
++                                    enum airoha_pcie_port_gen gen)
++{
++      u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941;
++      u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767;
++      u32 pr_idac, val, cdr_pr_idac_tmp = 0;
++      int i;
++
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1,
++                               PCIE_LCPLL_MAN_PWDB);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
++                                   PCIE_LOCK_TARGET_BEG,
++                                   fl_out_target - 100);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2,
++                                   PCIE_LOCK_TARGET_END,
++                                   fl_out_target + 100);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
++                                   PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                   PCIE_LOCK_LOCKTH, 0x3);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
++                                   PCIE_UNLOCK_TARGET_BEG,
++                                   fl_out_target - 100);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3,
++                                   PCIE_UNLOCK_TARGET_END,
++                                   fl_out_target + 100);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1,
++                                   PCIE_PLL_FT_UNLOCK_CYCLECNT,
++                                   lock_cyclecnt);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                   PCIE_UNLOCK_LOCKTH, 0x3);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE,
++                                 CSR_2L_PXP_CDR1_INJ_FORCE_OFF);
++
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                               PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                                 PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                                 PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                               PCIE_FORCE_DA_PXP_CDR_PR_PWDB);
++
++      for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) {
++              airoha_phy_pma1_update_field(pcie_phy,
++                              REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                              PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8);
++              airoha_phy_pma1_clear_bits(pcie_phy,
++                                         REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                         PCIE_FREQLOCK_DET_EN);
++              airoha_phy_pma1_update_field(pcie_phy,
++                                           REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                           PCIE_FREQLOCK_DET_EN, 0x3);
++
++              usleep_range(10000, 15000);
++
++              val = FIELD_GET(PCIE_RO_FL_OUT,
++                              readl(pcie_phy->pma1 +
++                                    REG_PCIE_PMA_RO_RX_FREQDET));
++              if (val > fl_out_target)
++                      cdr_pr_idac_tmp = i << 8;
++      }
++
++      for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) {
++              pr_idac = cdr_pr_idac_tmp | (0x1 << i);
++              airoha_phy_pma1_update_field(pcie_phy,
++                              REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                              PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac);
++              airoha_phy_pma1_clear_bits(pcie_phy,
++                                         REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                         PCIE_FREQLOCK_DET_EN);
++              airoha_phy_pma1_update_field(pcie_phy,
++                                           REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                           PCIE_FREQLOCK_DET_EN, 0x3);
++
++              usleep_range(10000, 15000);
++
++              val = FIELD_GET(PCIE_RO_FL_OUT,
++                              readl(pcie_phy->pma1 +
++                                    REG_PCIE_PMA_RO_RX_FREQDET));
++              if (val < fl_out_target)
++                      pr_idac &= ~(0x1 << i);
++
++              cdr_pr_idac_tmp = pr_idac;
++      }
++
++      airoha_phy_pma1_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                                   PCIE_FORCE_DA_PXP_CDR_PR_IDAC,
++                                   cdr_pr_idac_tmp);
++
++      for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) {
++              u32 val;
++
++              airoha_phy_pma1_clear_bits(pcie_phy,
++                                         REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                         PCIE_FREQLOCK_DET_EN);
++              airoha_phy_pma1_update_field(pcie_phy,
++                                           REG_PCIE_PMA_SS_RX_FREQ_DET4,
++                                           PCIE_FREQLOCK_DET_EN, 0x3);
++
++              usleep_range(10000, 15000);
++
++              val = readl(pcie_phy->pma1 + REG_PCIE_PMA_RO_RX_FREQDET);
++              if (val & PCIE_RO_FBCK_LOCK)
++                      break;
++      }
++
++      /* turn off force mode and update band values */
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE,
++                                   CSR_2L_PXP_CDR1_INJ_FORCE_OFF);
++
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                                 PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC);
++      if (gen == PCIE_PORT_GEN3) {
++              airoha_phy_pma1_update_field(pcie_phy,
++                                           REG_PCIE_PMA_DIG_RESERVE_14,
++                                           PCIE_FLL_IDAC_PCIEG3,
++                                           cdr_pr_idac_tmp);
++      } else {
++              airoha_phy_pma1_update_field(pcie_phy,
++                                           REG_PCIE_PMA_DIG_RESERVE_13,
++                                           PCIE_FLL_IDAC_PCIEG1,
++                                           cdr_pr_idac_tmp);
++              airoha_phy_pma1_update_field(pcie_phy,
++                                           REG_PCIE_PMA_DIG_RESERVE_13,
++                                           PCIE_FLL_IDAC_PCIEG2,
++                                           cdr_pr_idac_tmp);
++      }
++}
++
++static void airoha_pcie_phy_init_default(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CMN,
++                                     CSR_2L_PXP_CMN_TRIM_MASK, 0x10);
++      writel(0xcccbcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_21);
++      writel(0xcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_22);
++      writel(0xcccbcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_21);
++      writel(0xcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_22);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CMN,
++                                 CSR_2L_PXP_CMN_LANE_EN);
++}
++
++static void airoha_pcie_phy_init_clk_out(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_TXPLL_POSTDIV_D256,
++                                     CSR_2L_PXP_CLKTX0_AMP, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_CLKTX0_FORCE_OUT1,
++                                     CSR_2L_PXP_CLKTX1_AMP, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_TXPLL_POSTDIV_D256,
++                                     CSR_2L_PXP_CLKTX0_OFFSET, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
++                                     CSR_2L_PXP_CLKTX1_OFFSET, 0x2);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX0_FORCE_OUT1,
++                                   CSR_2L_PXP_CLKTX0_HZ);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
++                                   CSR_2L_PXP_CLKTX1_HZ);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_CLKTX0_FORCE_OUT1,
++                                     CSR_2L_PXP_CLKTX0_IMP_SEL, 0x12);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_IMP_SEL,
++                                     CSR_2L_PXP_CLKTX1_IMP_SEL, 0x12);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV_D256,
++                                   CSR_2L_PXP_CLKTX0_SR);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
++                                   CSR_2L_PXP_CLKTX1_SR);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
++                                     CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
++}
++
++static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
++                               PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
++                               PCIE_SW_RX_RST);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
++                               PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
++                               PCIE_SW_RX_RST);
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
++                               PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
++                               PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
++}
++
++static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
++{
++      writel(0x2a00090b, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_17);
++      writel(0x2a00090b, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_17);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONPI,
++                                 CSR_2L_PXP_CDR0_PR_XFICK_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONPI,
++                                 CSR_2L_PXP_CDR1_PR_XFICK_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy,
++                                   REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV,
++                                   CSR_2L_PXP_CDR0_PD_EDGE_DISABLE);
++      airoha_phy_csr_2l_clear_bits(pcie_phy,
++                                   REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV,
++                                   CSR_2L_PXP_CDR1_PD_EDGE_DISABLE);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV,
++                                     CSR_2L_PXP_RX0_PHYCK_SEL, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV,
++                                     CSR_2L_PXP_RX1_PHYCK_SEL, 0x1);
++}
++
++static void airoha_pcie_phy_init_jcpll(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                                 PCIE_FORCE_DA_PXP_JCPLL_EN);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                                 PCIE_FORCE_DA_PXP_JCPLL_EN);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_VTP_EN,
++                                     CSR_2L_PXP_JCPLL_SPARE_LOW, 0x20);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
++                                 CSR_2L_PXP_JCPLL_RST);
++      writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_JCPLL_SSC_DELTA1);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD,
++                                   CSR_2L_PXP_JCPLL_SSC_PERIOD);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
++                                   CSR_2L_PXP_JCPLL_SSC_PHASE_INI);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
++                                   CSR_2L_PXP_JCPLL_SSC_TRI_EN);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
++                                     CSR_2L_PXP_JCPLL_LPF_BR, 0xa);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
++                                     CSR_2L_PXP_JCPLL_LPF_BP, 0xc);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
++                                     CSR_2L_PXP_JCPLL_LPF_BC, 0x1f);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
++                                     CSR_2L_PXP_JCPLL_LPF_BWC, 0x1e);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR,
++                                     CSR_2L_PXP_JCPLL_LPF_BWR, 0xa);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
++                                     CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE,
++                                     0x1);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, CSR_2L_PXP_JCPLL_MONCK,
++                                   CSR_2L_PXP_JCPLL_REFIN_DIV);
++
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW);
++      airoha_phy_pma0_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW,
++                                   PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW,
++                                   0x50000000);
++      airoha_phy_pma1_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW,
++                                   PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW,
++                                   0x50000000);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy,
++                                 REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
++                                 CSR_2L_PXP_JCPLL_POSTDIV_D5);
++      airoha_phy_csr_2l_set_bits(pcie_phy,
++                                 REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
++                                 CSR_2L_PXP_JCPLL_POSTDIV_D2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
++                                     CSR_2L_PXP_JCPLL_RST_DLY, 0x4);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
++                                   CSR_2L_PXP_JCPLL_SDM_DI_LS);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_KBAND_VREF,
++                                   CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
++                                   CSR_2L_PXP_JCPLL_CHP_IOFST);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
++                                     CSR_2L_PXP_JCPLL_CHP_IBIAS, 0xc);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_JCPLL_MMD_PREDIV_MODE,
++                                     CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE,
++                                     0x1);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
++                                 CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
++                                     CSR_2L_PXP_JCPLL_VCO_CFIX, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV,
++                                     CSR_2L_PXP_JCPLL_VCO_SCAPWR, 0x4);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT,
++                                   REG_CSR_2L_JCPLL_LPF_SHCK_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
++                                 CSR_2L_PXP_JCPLL_POSTDIV_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
++                                   CSR_2L_PXP_JCPLL_KBAND_KFC);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
++                                     CSR_2L_PXP_JCPLL_KBAND_KF, 0x3);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC,
++                                   CSR_2L_PXP_JCPLL_KBAND_KS);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
++                                     CSR_2L_PXP_JCPLL_KBAND_DIV, 0x1);
++
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN);
++      airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE,
++                                 PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN);
++
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC,
++                                     CSR_2L_PXP_JCPLL_KBAND_CODE, 0xe4);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
++                                 CSR_2L_PXP_JCPLL_TCL_AMP_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP,
++                                 CSR_2L_PXP_JCPLL_TCL_LPF_EN);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_JCPLL_TCL_KBAND_VREF,
++                                     CSR_2L_PXP_JCPLL_TCL_KBAND_VREF, 0xf);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
++                                     CSR_2L_PXP_JCPLL_TCL_AMP_GAIN, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
++                                     CSR_2L_PXP_JCPLL_TCL_AMP_VREF, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP,
++                                     CSR_2L_PXP_JCPLL_TCL_LPF_BW, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCO_TCLVAR,
++                                     CSR_2L_PXP_JCPLL_VCO_TCLVAR, 0x3);
++
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN);
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN);
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_JCPLL_EN);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_JCPLL_EN);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_JCPLL_EN);
++}
++
++static void airoha_pcie_phy_txpll(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                                 PCIE_FORCE_DA_PXP_TXPLL_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                                 PCIE_FORCE_DA_PXP_TXPLL_EN);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
++                                 CSR_2L_PXP_TXPLL_PLL_RSTB);
++      writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC_PERIOD,
++                                   CSR_2L_PXP_txpll_SSC_PERIOD);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
++                                     CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK,
++                                     CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
++                                   CSR_2L_PXP_TXPLL_REFIN_DIV);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
++                                     CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3);
++
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
++      airoha_phy_pma0_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW,
++                                   PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW,
++                                   0xc800000);
++      airoha_phy_pma1_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW,
++                                   PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW,
++                                   0xc800000);
++
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
++                                   CSR_2L_PXP_TXPLL_SDM_IFM);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
++                                   CSR_2L_PXP_TXPLL_SSC_PHASE_INI);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
++                                     CSR_2L_PXP_TXPLL_RST_DLY, 0x4);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
++                                   CSR_2L_PXP_TXPLL_SDM_DI_LS);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS,
++                                     CSR_2L_PXP_TXPLL_SDM_ORD, 0x3);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
++                                   CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN);
++      writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
++                                     CSR_2L_PXP_TXPLL_LPF_BP, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
++                                     CSR_2L_PXP_TXPLL_LPF_BC, 0x18);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
++                                     CSR_2L_PXP_TXPLL_LPF_BR, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST,
++                                     CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK,
++                                     CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_VTP,
++                                     CSR_2L_PXP_TXPLL_SPARE_L, 0x1);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
++                                   CSR_2L_PXP_TXPLL_LPF_BWC);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
++                                   CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV,
++                                   CSR_2L_PXP_TXPLL_REFIN_DIV);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
++                                 CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_VCO_SCAPWR,
++                                     CSR_2L_PXP_TXPLL_VCO_SCAPWR, 0x7);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
++                                     CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3);
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW);
++
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
++                                   CSR_2L_PXP_TXPLL_SSC_PHASE_INI);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
++                                   CSR_2L_PXP_TXPLL_LPF_BWR);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2,
++                                 CSR_2L_PXP_TXPLL_REFIN_INTERNAL);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
++                                   CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_VTP,
++                                   CSR_2L_PXP_TXPLL_VTP_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
++                                   CSR_2L_PXP_TXPLL_PHY_CK1_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2,
++                                 CSR_2L_PXP_TXPLL_REFIN_INTERNAL);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC,
++                                   CSR_2L_PXP_TXPLL_SSC_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_750M_SYS_CK,
++                                   CSR_2L_PXP_TXPLL_LPF_SHCK_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV,
++                                   CSR_2L_PXP_TXPLL_POSTDIV_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
++                                   CSR_2L_PXP_TXPLL_KBAND_KFC);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
++                                     CSR_2L_PXP_TXPLL_KBAND_KF, 0x3);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
++                                     CSR_2L_PXP_txpll_KBAND_KS, 0x1);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV,
++                                     CSR_2L_PXP_TXPLL_KBAND_DIV, 0x4);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR,
++                                     CSR_2L_PXP_TXPLL_KBAND_CODE, 0xe4);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT,
++                                 CSR_2L_PXP_TXPLL_TCL_AMP_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_AMP_VREF,
++                                 CSR_2L_PXP_TXPLL_TCL_LPF_EN);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_TXPLL_TCL_KBAND_VREF,
++                                     CSR_2L_PXP_TXPLL_TCL_KBAND_VREF, 0xf);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT,
++                                     CSR_2L_PXP_TXPLL_TCL_AMP_GAIN, 0x3);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_TXPLL_TCL_AMP_VREF,
++                                     CSR_2L_PXP_TXPLL_TCL_AMP_VREF, 0xb);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW,
++                                     CSR_2L_PXP_TXPLL_TCL_LPF_BW, 0x3);
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_TXPLL_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_SEL_DA_PXP_TXPLL_EN);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT,
++                               PCIE_FORCE_DA_PXP_TXPLL_EN);
++}
++
++static void airoha_pcie_phy_init_ssc_jcpll(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1,
++                                     CSR_2L_PXP_JCPLL_SSC_DELTA1, 0x106);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1,
++                                     CSR_2L_PXP_JCPLL_SSC_DELTA, 0x106);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD,
++                                     CSR_2L_PXP_JCPLL_SSC_PERIOD, 0x31b);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
++                                 CSR_2L_PXP_JCPLL_SSC_PHASE_INI);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
++                                 CSR_2L_PXP_JCPLL_SSC_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
++                                 CSR_2L_PXP_JCPLL_SDM_IFM);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
++                                 CSR_2L_PXP_JCPLL_SDM_HREN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
++                                   CSR_2L_PXP_JCPLL_SDM_DI_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
++                                 CSR_2L_PXP_JCPLL_SSC_TRI_EN);
++}
++
++static void
++airoha_pcie_phy_set_rxlan0_signal_detect(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW,
++                                 CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON);
++
++      usleep_range(100, 200);
++
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19,
++                                   PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
++                                   PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
++                                   PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030);
++
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST,
++                                     CSR_2L_PXP_RX0_SIGDET_PEAK, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL,
++                                     CSR_2L_PXP_RX0_SIGDET_VTH_SEL, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
++                                     CSR_2L_PXP_VOS_PNINV, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST,
++                                     CSR_2L_PXP_RX0_SIGDET_LPF_CTRL, 0x1);
++
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2,
++                                   PCIE_CAL_OUT_OS, 0x0);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2,
++                                 CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB);
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
++                               PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
++      airoha_phy_pma0_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
++                                   PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0,
++                                   PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0,
++                                   PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3);
++      airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1,
++                                 PCIE_DISB_RX_SDCAL_EN);
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
++                               PCIE_FORCE_RX_SDCAL_EN);
++      usleep_range(150, 200);
++      airoha_phy_pma0_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
++                                 PCIE_FORCE_RX_SDCAL_EN);
++}
++
++static void
++airoha_pcie_phy_set_rxlan1_signal_detect(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW,
++                                 CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON);
++
++      usleep_range(100, 200);
++
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19,
++                                   PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
++                                   PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20,
++                                   PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030);
++
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH,
++                                     CSR_2L_PXP_RX1_SIGDET_PEAK, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH,
++                                     CSR_2L_PXP_RX1_SIGDET_VTH_SEL, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
++                                     CSR_2L_PXP_VOS_PNINV, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_DAC_RANGE_EYE,
++                                     CSR_2L_PXP_RX1_SIGDET_LPF_CTRL, 0x1);
++
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2,
++                                   PCIE_CAL_OUT_OS, 0x0);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1,
++                                 CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB);
++
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
++                               PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
++      airoha_phy_pma1_update_field(pcie_phy,
++                                   REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL,
++                                   PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0,
++                                   PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0,
++                                   PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3);
++      airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1,
++                                 PCIE_DISB_RX_SDCAL_EN);
++
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
++                               PCIE_FORCE_RX_SDCAL_EN);
++      usleep_range(150, 200);
++      airoha_phy_pma1_clear_bits(pcie_phy,
++                                 REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1,
++                                 PCIE_FORCE_RX_SDCAL_EN);
++}
++
++static void airoha_pcie_phy_set_rxflow(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST,
++                               PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB |
++                               PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST,
++                               PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB |
++                               PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB);
++
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB,
++                               PCIE_FORCE_DA_PXP_CDR_PD_PWDB |
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB);
++      airoha_phy_pma0_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB,
++                               PCIE_FORCE_DA_PXP_RX_FE_PWDB |
++                               PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB,
++                               PCIE_FORCE_DA_PXP_CDR_PD_PWDB |
++                               PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB);
++      airoha_phy_pma1_set_bits(pcie_phy,
++                               REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB,
++                               PCIE_FORCE_DA_PXP_RX_FE_PWDB |
++                               PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV,
++                                 CSR_2L_PXP_RX0_PHYCK_RSTB |
++                                 CSR_2L_PXP_RX0_TDC_CK_SEL);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV,
++                                 CSR_2L_PXP_RX1_PHYCK_RSTB |
++                                 CSR_2L_PXP_RX1_TDC_CK_SEL);
++
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
++                               PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST |
++                               PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST |
++                               PCIE_SW_TX_FIFO_RST);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
++                               PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST |
++                               PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST |
++                               PCIE_SW_TX_FIFO_RST);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2,
++                                 CSR_2L_PXP_RX0_FE_VB_EQ2_EN |
++                                 CSR_2L_PXP_RX0_FE_VB_EQ3_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL,
++                                 CSR_2L_PXP_RX0_FE_VB_EQ1_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1,
++                                 CSR_2L_PXP_RX1_FE_VB_EQ1_EN |
++                                 CSR_2L_PXP_RX1_FE_VB_EQ2_EN |
++                                 CSR_2L_PXP_RX1_FE_VB_EQ3_EN);
++
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
++                                     CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0,
++                                     CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
++                                     CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0,
++                                     CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4);
++}
++
++static void airoha_pcie_phy_set_pr(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND,
++                                     CSR_2L_PXP_CDR0_PR_VREG_IBAND, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND,
++                                     CSR_2L_PXP_CDR0_PR_VREG_CKBUF, 0x5);
++
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_CKREF_DIV,
++                                   CSR_2L_PXP_CDR0_PR_CKREF_DIV);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW,
++                                   CSR_2L_PXP_CDR0_PR_CKREF_DIV1);
++
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL,
++                                     CSR_2L_PXP_CDR1_PR_VREG_IBAND, 0x5);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL,
++                                     CSR_2L_PXP_CDR1_PR_VREG_CKBUF, 0x5);
++
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_CKREF_DIV,
++                                   CSR_2L_PXP_CDR1_PR_CKREF_DIV);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW,
++                                   CSR_2L_PXP_CDR1_PR_CKREF_DIV1);
++
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_LPF_RATIO,
++                                     CSR_2L_PXP_CDR0_LPF_TOP_LIM, 0x20000);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_LPF_RATIO,
++                                     CSR_2L_PXP_CDR1_LPF_TOP_LIM, 0x20000);
++
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC,
++                                     CSR_2L_PXP_CDR0_PR_BETA_SEL, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC,
++                                     CSR_2L_PXP_CDR1_PR_BETA_SEL, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC,
++                                     CSR_2L_PXP_CDR0_PR_KBAND_DIV, 0x4);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC,
++                                     CSR_2L_PXP_CDR1_PR_KBAND_DIV, 0x4);
++}
++
++static void airoha_pcie_phy_set_txflow(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO,
++                                 CSR_2L_PXP_TX0_CKLDO_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO,
++                                 CSR_2L_PXP_TX1_CKLDO_EN);
++
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO,
++                                 CSR_2L_PXP_TX0_DMEDGEGEN_EN);
++      airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO,
++                                 CSR_2L_PXP_TX1_DMEDGEGEN_EN);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TX1_MULTLANE,
++                                   CSR_2L_PXP_TX1_MULTLANE_EN);
++}
++
++static void airoha_pcie_phy_set_rx_mode(struct airoha_pcie_phy *pcie_phy)
++{
++      writel(0x804000, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_27);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
++                                   PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
++                                   PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5);
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
++                                   PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5);
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30,
++                               0x77700);
++
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK,
++                                   CSR_2L_PXP_CDR0_PR_MONCK_ENABLE);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK,
++                                     CSR_2L_PXP_CDR0_PR_RESERVE0, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS,
++                                     CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS, 0x19);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS,
++                                     CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS, 0x19);
++      airoha_phy_csr_2l_update_field(pcie_phy,
++                                     REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS,
++                                     CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS, 0x14);
++
++      writel(0x804000, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_27);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
++                                   PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
++                                   PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18,
++                                   PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5);
++
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30,
++                               0x77700);
++
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK,
++                                   CSR_2L_PXP_CDR1_PR_MONCK_ENABLE);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK,
++                                     CSR_2L_PXP_CDR1_PR_RESERVE0, 0x2);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
++                                     CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS, 0x19);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
++                                     CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS, 0x19);
++      airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS,
++                                     CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS, 0x14);
++}
++
++static void airoha_pcie_phy_load_kflow(struct airoha_pcie_phy *pcie_phy)
++{
++      airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
++                                   PCIE_FORCE_PMA_RX_SPEED, 0xa);
++      airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
++                                   PCIE_FORCE_PMA_RX_SPEED, 0xa);
++      airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3);
++      airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3);
++
++      airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
++                                 PCIE_FORCE_PMA_RX_SPEED);
++      airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12,
++                                 PCIE_FORCE_PMA_RX_SPEED);
++      usleep_range(100, 200);
++
++      airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2);
++      airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2);
++}
++
++/**
++ * airoha_pcie_phy_init() - Initialize the phy
++ * @phy: the phy to be initialized
++ *
++ * Initialize the phy registers.
++ * The hardware settings will be reset during suspend, it should be
++ * reinitialized when the consumer calls phy_init() again on resume.
++ */
++static int airoha_pcie_phy_init(struct phy *phy)
++{
++      struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
++      u32 val;
++
++      /* Setup Tx-Rx detection time */
++      val = FIELD_PREP(PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL, 0x33) |
++            FIELD_PREP(PCIE_XTP_RXDET_EN_STB_T_SEL, 0x1) |
++            FIELD_PREP(PCIE_XTP_RXDET_FINISH_STB_T_SEL, 0x2) |
++            FIELD_PREP(PCIE_XTP_TXPD_TX_DATA_EN_DLY, 0x3) |
++            FIELD_PREP(PCIE_XTP_RXDET_LATCH_STB_T_SEL, 0x1);
++      writel(val, pcie_phy->p0_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
++      writel(val, pcie_phy->p1_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
++      /* Setup Rx AEQ training time */
++      val = FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT, 0x32) |
++            FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT, 0x5050);
++      writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P0);
++      writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P1);
++
++      /* enable load FLL-K flow */
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
++                               PCIE_FLL_LOAD_EN);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
++                               PCIE_FLL_LOAD_EN);
++
++      airoha_pcie_phy_init_default(pcie_phy);
++      airoha_pcie_phy_init_clk_out(pcie_phy);
++      airoha_pcie_phy_init_csr_2l(pcie_phy);
++
++      usleep_range(100, 200);
++
++      airoha_pcie_phy_init_rx(pcie_phy);
++      /* phase 1, no ssc for K TXPLL */
++      airoha_pcie_phy_init_jcpll(pcie_phy);
++
++      usleep_range(500, 600);
++
++      /* TX PLL settings */
++      airoha_pcie_phy_txpll(pcie_phy);
++
++      usleep_range(200, 300);
++
++      /* SSC JCPLL setting */
++      airoha_pcie_phy_init_ssc_jcpll(pcie_phy);
++
++      usleep_range(100, 200);
++
++      /* Rx lan0 signal detect */
++      airoha_pcie_phy_set_rxlan0_signal_detect(pcie_phy);
++      /* Rx lan1 signal detect */
++      airoha_pcie_phy_set_rxlan1_signal_detect(pcie_phy);
++      /* RX FLOW */
++      airoha_pcie_phy_set_rxflow(pcie_phy);
++
++      usleep_range(100, 200);
++
++      airoha_pcie_phy_set_pr(pcie_phy);
++      /* TX FLOW */
++      airoha_pcie_phy_set_txflow(pcie_phy);
++
++      usleep_range(100, 200);
++      /* RX mode setting */
++      airoha_pcie_phy_set_rx_mode(pcie_phy);
++      /* Load K-Flow */
++      airoha_pcie_phy_load_kflow(pcie_phy);
++      airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
++                                 PCIE_DA_XPON_CDR_PR_PWDB);
++      airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
++                                 PCIE_DA_XPON_CDR_PR_PWDB);
++
++      usleep_range(100, 200);
++
++      airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
++                               PCIE_DA_XPON_CDR_PR_PWDB);
++      airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
++                               PCIE_DA_XPON_CDR_PR_PWDB);
++
++      /* Wait for the PCIe PHY to complete initialization before returning */
++      msleep(PHY_HW_INIT_TIME_MS);
++
++      return 0;
++}
++
++static int airoha_pcie_phy_exit(struct phy *phy)
++{
++      struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
++
++      airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
++                                 PCIE_PMA_SW_RST);
++      airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET,
++                                 PCIE_PMA_SW_RST);
++      airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
++                                   CSR_2L_PXP_JCPLL_SSC_PHASE_INI |
++                                   CSR_2L_PXP_JCPLL_SSC_TRI_EN |
++                                   CSR_2L_PXP_JCPLL_SSC_EN);
++
++      return 0;
++}
++
++static const struct phy_ops airoha_pcie_phy_ops = {
++      .init = airoha_pcie_phy_init,
++      .exit = airoha_pcie_phy_exit,
++      .owner = THIS_MODULE,
++};
++
++static int airoha_pcie_phy_probe(struct platform_device *pdev)
++{
++      struct airoha_pcie_phy *pcie_phy;
++      struct device *dev = &pdev->dev;
++      struct phy_provider *provider;
++
++      pcie_phy = devm_kzalloc(dev, sizeof(*pcie_phy), GFP_KERNEL);
++      if (!pcie_phy)
++              return -ENOMEM;
++
++      pcie_phy->csr_2l = devm_platform_ioremap_resource_byname(pdev, "csr-2l");
++      if (IS_ERR(pcie_phy->csr_2l))
++              return dev_err_probe(dev, PTR_ERR(pcie_phy->csr_2l),
++                                   "Failed to map phy-csr-2l base\n");
++
++      pcie_phy->pma0 = devm_platform_ioremap_resource_byname(pdev, "pma0");
++      if (IS_ERR(pcie_phy->pma0))
++              return dev_err_probe(dev, PTR_ERR(pcie_phy->pma0),
++                                   "Failed to map phy-pma0 base\n");
++
++      pcie_phy->pma1 = devm_platform_ioremap_resource_byname(pdev, "pma1");
++      if (IS_ERR(pcie_phy->pma1))
++              return dev_err_probe(dev, PTR_ERR(pcie_phy->pma1),
++                                   "Failed to map phy-pma1 base\n");
++
++      pcie_phy->phy = devm_phy_create(dev, dev->of_node, &airoha_pcie_phy_ops);
++      if (IS_ERR(pcie_phy->phy))
++              return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),
++                                   "Failed to create PCIe phy\n");
++
++      pcie_phy->p0_xr_dtime =
++              devm_platform_ioremap_resource_byname(pdev, "p0-xr-dtime");
++      if (IS_ERR(pcie_phy->p0_xr_dtime))
++              return dev_err_probe(dev, PTR_ERR(pcie_phy->p0_xr_dtime),
++                                   "Failed to map P0 Tx-Rx dtime base\n");
++
++      pcie_phy->p1_xr_dtime =
++              devm_platform_ioremap_resource_byname(pdev, "p1-xr-dtime");
++      if (IS_ERR(pcie_phy->p1_xr_dtime))
++              return dev_err_probe(dev, PTR_ERR(pcie_phy->p1_xr_dtime),
++                                   "Failed to map P1 Tx-Rx dtime base\n");
++
++      pcie_phy->rx_aeq = devm_platform_ioremap_resource_byname(pdev, "rx-aeq");
++      if (IS_ERR(pcie_phy->rx_aeq))
++              return dev_err_probe(dev, PTR_ERR(pcie_phy->rx_aeq),
++                                   "Failed to map Rx AEQ base\n");
++
++      pcie_phy->dev = dev;
++      phy_set_drvdata(pcie_phy->phy, pcie_phy);
++
++      provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
++      if (IS_ERR(provider))
++              return dev_err_probe(dev, PTR_ERR(provider),
++                                   "PCIe phy probe failed\n");
++
++      return 0;
++}
++
++static const struct of_device_id airoha_pcie_phy_of_match[] = {
++      { .compatible = "airoha,en7581-pcie-phy" },
++      { /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, airoha_pcie_phy_of_match);
++
++static struct platform_driver airoha_pcie_phy_driver = {
++      .probe  = airoha_pcie_phy_probe,
++      .driver = {
++              .name = "airoha-pcie-phy",
++              .of_match_table = airoha_pcie_phy_of_match,
++      },
++};
++module_platform_driver(airoha_pcie_phy_driver);
++
++MODULE_DESCRIPTION("Airoha PCIe PHY driver");
++MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/airoha/patches-6.6/220-07-phy-airoha-Add-support-for-Airoha-AN7581-USB-PHY.patch b/target/linux/airoha/patches-6.6/220-07-phy-airoha-Add-support-for-Airoha-AN7581-USB-PHY.patch
new file mode 100644 (file)
index 0000000..609df08
--- /dev/null
@@ -0,0 +1,667 @@
+From fadd22890b239e5a251dbe47367cfbeb1ea105f7 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 7 Feb 2025 13:28:40 +0100
+Subject: [PATCH 07/10] phy: airoha: Add support for Airoha AN7581 USB PHY
+
+Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2
+USB port with USB 2.0 mode always supported and USB 3.0 mode available
+only if the Serdes port is correctly configured for USB 3.0.
+
+The second USB port on the SoC can be both used for USB 3.0 operation or
+PCIe. (toggled by the SCU SSR register and configured by the USB PHY
+driver)
+
+If the USB 3.0 mode is not configured, the modes needs to be also
+disabled in the xHCI node or the driver will report unsable clock and
+fail probe.
+
+Also USB 3.0 PHY instance are provided only if the airoha,serdes-port
+and airoha,scu property is defined in DT, if it's not then USB 3.0 PHY
+is assumed not supported.
+
+For USB 2.0 Slew Rate calibration, airoha,usb2-monitor-clk-sel is
+mandatory and is used to select the monitor clock for calibration.
+
+Normally it's 1 for USB port 1 and 2 for USB port 2.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ MAINTAINERS                         |   1 +
+ drivers/phy/airoha/Kconfig          |  10 +
+ drivers/phy/airoha/Makefile         |   1 +
+ drivers/phy/airoha/phy-airoha-usb.c | 597 ++++++++++++++++++++++++++++
+ 4 files changed, 609 insertions(+)
+ create mode 100644 drivers/phy/airoha/phy-airoha-usb.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -742,6 +742,7 @@ M: Christian Marangi <ansuelsmth@gmail.c
+ L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+ S:    Maintained
+ F:    Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml
++F:    drivers/phy/airoha/phy-airoha-usb.c
+ F:    include/dt-bindings/phy/airoha,an7581-usb-phy.h
+ AIRSPY MEDIA DRIVER
+--- a/drivers/phy/airoha/Kconfig
++++ b/drivers/phy/airoha/Kconfig
+@@ -11,3 +11,13 @@ config PHY_AIROHA_PCIE
+         Say Y here to add support for Airoha PCIe PHY driver.
+         This driver create the basic PHY instance and provides initialize
+         callback for PCIe GEN3 port.
++
++config PHY_AIROHA_USB
++      tristate "Airoha USB PHY Driver"
++      depends on ARCH_AIROHA || COMPILE_TEST
++      depends on OF
++      select GENERIC_PHY
++      help
++        Say 'Y' here to add support for Airoha USB PHY driver.
++        This driver create the basic PHY instance and provides initialize
++        callback for USB port.
+--- a/drivers/phy/airoha/Makefile
++++ b/drivers/phy/airoha/Makefile
+@@ -1,3 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-$(CONFIG_PHY_AIROHA_PCIE)         += phy-airoha-pcie.o
++obj-$(CONFIG_PHY_AIROHA_USB)          += phy-airoha-usb.o
+--- /dev/null
++++ b/drivers/phy/airoha/phy-airoha-usb.c
+@@ -0,0 +1,596 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Author: Christian Marangi <ansuelsmth@gmail.com>
++ */
++
++#include <dt-bindings/phy/phy.h>
++#include <dt-bindings/soc/airoha,scu-ssr.h>
++#include <linux/bitfield.h>
++#include <linux/math.h>
++#include <linux/module.h>
++#include <linux/mfd/syscon.h>
++#include <linux/phy/phy.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++
++/* SCU */
++#define AIROHA_SCU_SSTR                               0x9c
++#define   AIROHA_SCU_SSTR_USB_PCIE_SEL                BIT(3)
++#define   AIROHA_SCU_SSTR_USB_PCIE_SEL_PCIE   FIELD_PREP_CONST(AIROHA_SCU_SSTR_USB_PCIE_SEL, 0x0)
++#define   AIROHA_SCU_SSTR_USB_PCIE_SEL_USB    FIELD_PREP_CONST(AIROHA_SCU_SSTR_USB_PCIE_SEL, 0x1)
++
++/* U2PHY */
++#define AIROHA_USB_PHY_FMCR0                  0x100
++#define   AIROHA_USB_PHY_MONCLK_SEL           GENMASK(27, 26)
++#define   AIROHA_USB_PHY_MONCLK_SEL0          FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x0)
++#define   AIROHA_USB_PHY_MONCLK_SEL1          FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x1)
++#define   AIROHA_USB_PHY_MONCLK_SEL2          FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x2)
++#define   AIROHA_USB_PHY_MONCLK_SEL3          FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x3)
++#define   AIROHA_USB_PHY_FREQDET_EN           BIT(24)
++#define   AIROHA_USB_PHY_CYCLECNT             GENMASK(23, 0)
++#define AIROHA_USB_PHY_FMMONR0                        0x10c
++#define   AIROHA_USB_PHY_USB_FM_OUT           GENMASK(31, 0)
++#define AIROHA_USB_PHY_FMMONR1                        0x110
++#define   AIROHA_USB_PHY_FRCK_EN              BIT(8)
++
++#define AIROHA_USB_PHY_USBPHYACR4             0x310
++#define   AIROHA_USB_PHY_USB20_FS_CR          GENMASK(10, 8)
++#define   AIROHA_USB_PHY_USB20_FS_CR_MAX      FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x0)
++#define   AIROHA_USB_PHY_USB20_FS_CR_NORMAL   FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x2)
++#define   AIROHA_USB_PHY_USB20_FS_CR_SMALLER  FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x4)
++#define   AIROHA_USB_PHY_USB20_FS_CR_MIN      FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x6)
++#define   AIROHA_USB_PHY_USB20_FS_SR          GENMASK(2, 0)
++#define   AIROHA_USB_PHY_USB20_FS_SR_MAX      FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x0)
++#define   AIROHA_USB_PHY_USB20_FS_SR_NORMAL   FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x2)
++#define   AIROHA_USB_PHY_USB20_FS_SR_SMALLER  FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x4)
++#define   AIROHA_USB_PHY_USB20_FS_SR_MIN      FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x6)
++#define AIROHA_USB_PHY_USBPHYACR5             0x314
++#define   AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN  BIT(15)
++#define   AIROHA_USB_PHY_USB20_HSTX_SRCTRL    GENMASK(14, 12)
++#define AIROHA_USB_PHY_USBPHYACR6             0x318
++#define   AIROHA_USB_PHY_USB20_BC11_SW_EN     BIT(23)
++#define   AIROHA_USB_PHY_USB20_DISCTH         GENMASK(7, 4)
++#define   AIROHA_USB_PHY_USB20_DISCTH_400     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x0)
++#define   AIROHA_USB_PHY_USB20_DISCTH_420     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x1)
++#define   AIROHA_USB_PHY_USB20_DISCTH_440     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x2)
++#define   AIROHA_USB_PHY_USB20_DISCTH_460     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x3)
++#define   AIROHA_USB_PHY_USB20_DISCTH_480     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x4)
++#define   AIROHA_USB_PHY_USB20_DISCTH_500     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x5)
++#define   AIROHA_USB_PHY_USB20_DISCTH_520     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x6)
++#define   AIROHA_USB_PHY_USB20_DISCTH_540     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x7)
++#define   AIROHA_USB_PHY_USB20_DISCTH_560     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x8)
++#define   AIROHA_USB_PHY_USB20_DISCTH_580     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x9)
++#define   AIROHA_USB_PHY_USB20_DISCTH_600     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xa)
++#define   AIROHA_USB_PHY_USB20_DISCTH_620     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xb)
++#define   AIROHA_USB_PHY_USB20_DISCTH_640     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xc)
++#define   AIROHA_USB_PHY_USB20_DISCTH_660     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xd)
++#define   AIROHA_USB_PHY_USB20_DISCTH_680     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xe)
++#define   AIROHA_USB_PHY_USB20_DISCTH_700     FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xf)
++#define   AIROHA_USB_PHY_USB20_SQTH           GENMASK(3, 0)
++#define   AIROHA_USB_PHY_USB20_SQTH_85                FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x0)
++#define   AIROHA_USB_PHY_USB20_SQTH_90                FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x1)
++#define   AIROHA_USB_PHY_USB20_SQTH_95                FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x2)
++#define   AIROHA_USB_PHY_USB20_SQTH_100               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x3)
++#define   AIROHA_USB_PHY_USB20_SQTH_105               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x4)
++#define   AIROHA_USB_PHY_USB20_SQTH_110               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x5)
++#define   AIROHA_USB_PHY_USB20_SQTH_115               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x6)
++#define   AIROHA_USB_PHY_USB20_SQTH_120               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x7)
++#define   AIROHA_USB_PHY_USB20_SQTH_125               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x8)
++#define   AIROHA_USB_PHY_USB20_SQTH_130               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x9)
++#define   AIROHA_USB_PHY_USB20_SQTH_135               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xa)
++#define   AIROHA_USB_PHY_USB20_SQTH_140               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xb)
++#define   AIROHA_USB_PHY_USB20_SQTH_145               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xc)
++#define   AIROHA_USB_PHY_USB20_SQTH_150               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xd)
++#define   AIROHA_USB_PHY_USB20_SQTH_155               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xe)
++#define   AIROHA_USB_PHY_USB20_SQTH_160               FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xf)
++
++#define AIROHA_USB_PHY_U2PHYDTM1              0x36c
++#define   AIROHA_USB_PHY_FORCE_IDDIG          BIT(9)
++#define   AIROHA_USB_PHY_IDDIG                        BIT(1)
++
++#define AIROHA_USB_PHY_GPIO_CTLD              0x80c
++#define   AIROHA_USB_PHY_C60802_GPIO_CTLD     GENMASK(31, 0)
++#define     AIROHA_USB_PHY_SSUSB_IP_SW_RST    BIT(31)
++#define     AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN BIT(30)
++#define     AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST BIT(29)
++#define     AIROHA_USB_PHY_SSUSB_SW_RST               BIT(28)
++
++#define AIROHA_USB_PHY_U3_PHYA_REG0           0xb00
++#define   AIROHA_USB_PHY_SSUSB_BG_DIV         GENMASK(29, 28)
++#define   AIROHA_USB_PHY_SSUSB_BG_DIV_2               FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x0)
++#define   AIROHA_USB_PHY_SSUSB_BG_DIV_4               FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x1)
++#define   AIROHA_USB_PHY_SSUSB_BG_DIV_8               FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x2)
++#define   AIROHA_USB_PHY_SSUSB_BG_DIV_16      FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x3)
++#define AIROHA_USB_PHY_U3_PHYA_REG1           0xb04
++#define   AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE       GENMASK(25, 10)
++#define AIROHA_USB_PHY_U3_PHYA_REG6           0xb18
++#define   AIROHA_USB_PHY_SSUSB_CDR_RESERVE    GENMASK(31, 24)
++#define AIROHA_USB_PHY_U3_PHYA_REG8           0xb20
++#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY    GENMASK(7, 6)
++#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x0)
++#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_64 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x1)
++#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_128        FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x2)
++#define   AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_216        FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x3)
++
++#define AIROHA_USB_PHY_U3_PHYA_DA_REG19               0xc38
++#define   AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3 GENMASK(15, 0)
++
++#define AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT    1024
++#define AIROHA_USB_PHY_REF_CK                 20
++#define AIROHA_USB_PHY_U2_SR_COEF             28
++#define AIROHA_USB_PHY_U2_SR_COEF_DIVISOR     1000
++
++#define AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION 0x5
++#define AIROHA_USB_PHY_FREQDET_SLEEP          1000 /* 1ms */
++#define AIROHA_USB_PHY_FREQDET_TIMEOUT                (AIROHA_USB_PHY_FREQDET_SLEEP * 10)
++
++struct airoha_usb_phy_instance {
++      struct phy *phy;
++      u32 type;
++};
++
++enum airoha_usb_phy_instance_type {
++      AIROHA_PHY_USB2,
++      AIROHA_PHY_USB3,
++
++      AIROHA_PHY_USB_MAX,
++};
++
++struct airoha_usb_phy_priv {
++      struct device *dev;
++      struct regmap *regmap;
++      struct regmap *scu;
++
++      unsigned int monclk_sel;
++      unsigned int serdes_port;
++
++      struct airoha_usb_phy_instance *phys[AIROHA_PHY_USB_MAX];
++};
++
++static void airoha_usb_phy_u2_slew_rate_calibration(struct airoha_usb_phy_priv *priv)
++{
++      u32 fm_out;
++      u32 srctrl;
++
++      /* Enable HS TX SR calibration */
++      regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
++                      AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
++
++      usleep_range(1000, 1500);
++
++      /* Enable Free run clock */
++      regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
++                      AIROHA_USB_PHY_FRCK_EN);
++
++      /* Select Monitor Clock */
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
++                         AIROHA_USB_PHY_MONCLK_SEL,
++                         FIELD_PREP(AIROHA_USB_PHY_MONCLK_SEL,
++                                    priv->monclk_sel));
++
++      /* Set cyclecnt */
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
++                         AIROHA_USB_PHY_CYCLECNT,
++                         FIELD_PREP(AIROHA_USB_PHY_CYCLECNT,
++                                    AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT));
++
++      /* Enable Frequency meter */
++      regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
++                      AIROHA_USB_PHY_FREQDET_EN);
++
++      /* Timeout can happen and we will apply workaround at the end */
++      regmap_read_poll_timeout(priv->regmap, AIROHA_USB_PHY_FMMONR0, fm_out,
++                               fm_out, AIROHA_USB_PHY_FREQDET_SLEEP,
++                               AIROHA_USB_PHY_FREQDET_TIMEOUT);
++
++      /* Disable Frequency meter */
++      regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMCR0,
++                        AIROHA_USB_PHY_FREQDET_EN);
++
++      /* Disable Free run clock */
++      regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1,
++                        AIROHA_USB_PHY_FRCK_EN);
++
++      /* Disable HS TX SR calibration */
++      regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
++                        AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
++
++      usleep_range(1000, 1500);
++
++      /* Frequency was not detected, use default SR calibration value */
++      if (!fm_out) {
++              srctrl = AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION;
++              dev_err(priv->dev, "Frequency not detected, using default SR calibration.\n");
++      } else {
++              /* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */
++              srctrl = AIROHA_USB_PHY_REF_CK * AIROHA_USB_PHY_U2_SR_COEF;
++              srctrl = (srctrl * AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT) / fm_out;
++              srctrl = DIV_ROUND_CLOSEST(srctrl, AIROHA_USB_PHY_U2_SR_COEF_DIVISOR);
++              dev_dbg(priv->dev, "SR calibration applied: %x\n", srctrl);
++      }
++
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5,
++                         AIROHA_USB_PHY_USB20_HSTX_SRCTRL,
++                         FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl));
++}
++
++static void airoha_usb_phy_u2_init(struct airoha_usb_phy_priv *priv)
++{
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
++                         AIROHA_USB_PHY_USB20_FS_CR,
++                         AIROHA_USB_PHY_USB20_FS_CR_MIN);
++
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4,
++                         AIROHA_USB_PHY_USB20_FS_SR,
++                         AIROHA_USB_PHY_USB20_FS_SR_NORMAL);
++
++      /* FIXME: evaluate if needed */
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
++                         AIROHA_USB_PHY_USB20_SQTH,
++                         AIROHA_USB_PHY_USB20_SQTH_130);
++
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
++                         AIROHA_USB_PHY_USB20_DISCTH,
++                         AIROHA_USB_PHY_USB20_DISCTH_600);
++
++      /* Enable the USB port and then disable after calibration */
++      regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
++                        AIROHA_USB_PHY_USB20_BC11_SW_EN);
++
++      airoha_usb_phy_u2_slew_rate_calibration(priv);
++
++      regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
++                      AIROHA_USB_PHY_USB20_BC11_SW_EN);
++
++      usleep_range(1000, 1500);
++}
++
++/*
++ * USB 3.0 mode can only work if USB serdes is correctly set.
++ * This is validated in xLate function.
++ */
++static void airoha_usb_phy_u3_init(struct airoha_usb_phy_priv *priv)
++{
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG8,
++                         AIROHA_USB_PHY_SSUSB_CDR_RST_DLY,
++                         AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32);
++
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG6,
++                         AIROHA_USB_PHY_SSUSB_CDR_RESERVE,
++                         FIELD_PREP(AIROHA_USB_PHY_SSUSB_CDR_RESERVE, 0xe));
++
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG0,
++                         AIROHA_USB_PHY_SSUSB_BG_DIV,
++                         AIROHA_USB_PHY_SSUSB_BG_DIV_4);
++
++      regmap_set_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG1,
++                      FIELD_PREP(AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE, 0x600));
++
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_DA_REG19,
++                         AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3,
++                         FIELD_PREP(AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, 0x43));
++}
++
++static int airoha_usb_phy_init(struct phy *phy)
++{
++      struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
++      struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
++
++      switch (instance->type) {
++      case PHY_TYPE_USB2:
++              airoha_usb_phy_u2_init(priv);
++              break;
++      case PHY_TYPE_USB3:
++              if (phy_get_mode(phy) == PHY_MODE_PCIE)
++                      return 0;
++
++              airoha_usb_phy_u3_init(priv);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int airoha_usb_phy_u2_power_on(struct airoha_usb_phy_priv *priv)
++{
++      regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
++                        AIROHA_USB_PHY_USB20_BC11_SW_EN);
++
++      usleep_range(1000, 1500);
++
++      return 0;
++}
++
++static int airoha_usb_phy_u3_power_on(struct airoha_usb_phy_priv *priv)
++{
++      regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
++                        AIROHA_USB_PHY_SSUSB_IP_SW_RST |
++                        AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN |
++                        AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST |
++                        AIROHA_USB_PHY_SSUSB_SW_RST);
++
++      usleep_range(1000, 1500);
++
++      return 0;
++}
++
++static int airoha_usb_phy_power_on(struct phy *phy)
++{
++      struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
++      struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
++
++      switch (instance->type) {
++      case PHY_TYPE_USB2:
++              airoha_usb_phy_u2_power_on(priv);
++              break;
++      case PHY_TYPE_USB3:
++              if (phy_get_mode(phy) == PHY_MODE_PCIE)
++                      return 0;
++
++              airoha_usb_phy_u3_power_on(priv);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int airoha_usb_phy_u2_power_off(struct airoha_usb_phy_priv *priv)
++{
++      regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6,
++                      AIROHA_USB_PHY_USB20_BC11_SW_EN);
++
++      usleep_range(1000, 1500);
++
++      return 0;
++}
++
++static int airoha_usb_phy_u3_power_off(struct airoha_usb_phy_priv *priv)
++{
++      regmap_set_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD,
++                      AIROHA_USB_PHY_SSUSB_IP_SW_RST |
++                      AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST);
++
++      usleep_range(1000, 1500);
++
++      return 0;
++}
++
++static int airoha_usb_phy_power_off(struct phy *phy)
++{
++      struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
++      struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
++
++      switch (instance->type) {
++      case PHY_TYPE_USB2:
++              airoha_usb_phy_u2_power_off(priv);
++              break;
++      case PHY_TYPE_USB3:
++              if (phy_get_mode(phy) == PHY_MODE_PCIE)
++                      return 0;
++
++              airoha_usb_phy_u3_power_off(priv);
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static int airoha_usb_phy_u2_set_mode(struct airoha_usb_phy_priv *priv,
++                                    enum phy_mode mode)
++{
++      u32 val;
++
++      /*
++       * For Device and Host mode, enable force IDDIG.
++       * For Device set IDDIG, for Host clear IDDIG.
++       * For OTG disable force and clear IDDIG bit while at it.
++       */
++      switch (mode) {
++      case PHY_MODE_USB_DEVICE:
++              val = AIROHA_USB_PHY_IDDIG;
++              break;
++      case PHY_MODE_USB_HOST:
++              val = AIROHA_USB_PHY_FORCE_IDDIG |
++                    AIROHA_USB_PHY_FORCE_IDDIG;
++              break;
++      case PHY_MODE_USB_OTG:
++              val = 0;
++              break;
++      default:
++              return 0;
++      }
++
++      regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U2PHYDTM1,
++                         AIROHA_USB_PHY_FORCE_IDDIG |
++                         AIROHA_USB_PHY_IDDIG, val);
++
++      return 0;
++}
++
++static int airoha_usb_phy_u3_set_mode(struct airoha_usb_phy_priv *priv,
++                                    enum phy_mode mode)
++{
++      u32 sel;
++
++      /* Only USB2 supports PCIe mode */
++      if (mode == PHY_MODE_PCIE &&
++          priv->serdes_port != AIROHA_SCU_SERDES_USB2)
++              return -EINVAL;
++
++      if (mode == PHY_MODE_PCIE)
++              sel = AIROHA_SCU_SSTR_USB_PCIE_SEL_PCIE;
++      else
++              sel = AIROHA_SCU_SSTR_USB_PCIE_SEL_USB;
++
++      regmap_update_bits(priv->scu, AIROHA_SCU_SSTR,
++                         AIROHA_SCU_SSTR_USB_PCIE_SEL, sel);
++
++      return 0;
++}
++
++static int airoha_usb_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
++{
++      struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy);
++      struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
++
++      switch (instance->type) {
++      case PHY_TYPE_USB2:
++              return airoha_usb_phy_u2_set_mode(priv, mode);
++      case PHY_TYPE_USB3:
++              return airoha_usb_phy_u3_set_mode(priv, mode);
++      default:
++              return 0;
++      }
++}
++
++static struct phy *airoha_usb_phy_xlate(struct device *dev,
++                                      struct of_phandle_args *args)
++{
++      struct airoha_usb_phy_priv *priv = dev_get_drvdata(dev);
++      struct airoha_usb_phy_instance *instance = NULL;
++      unsigned int index, phy_type;
++
++      if (args->args_count != 1) {
++              dev_err(dev, "invalid number of cells in 'phy' property\n");
++              return ERR_PTR(-EINVAL);
++      }
++
++      phy_type = args->args[0];
++      if (!(phy_type == PHY_TYPE_USB2 || phy_type == PHY_TYPE_USB3)) {
++              dev_err(dev, "unsupported device type: %d\n", phy_type);
++              return ERR_PTR(-EINVAL);
++      }
++
++      for (index = 0; index < AIROHA_PHY_USB_MAX; index++)
++              if (priv->phys[index] &&
++                  phy_type == priv->phys[index]->type) {
++                      instance = priv->phys[index];
++                      break;
++              }
++
++      if (!instance) {
++              dev_err(dev, "failed to find appropriate phy\n");
++              return ERR_PTR(-EINVAL);
++      }
++
++      return instance->phy;
++}
++
++static const struct phy_ops airoha_phy = {
++      .init           = airoha_usb_phy_init,
++      .power_on       = airoha_usb_phy_power_on,
++      .power_off      = airoha_usb_phy_power_off,
++      .set_mode       = airoha_usb_phy_set_mode,
++      .owner          = THIS_MODULE,
++};
++
++static const struct regmap_config airoha_usb_phy_regmap_config = {
++      .reg_bits = 32,
++      .val_bits = 32,
++      .reg_stride = 4,
++};
++
++static int airoha_usb_phy_probe(struct platform_device *pdev)
++{
++      struct phy_provider *phy_provider;
++      struct airoha_usb_phy_priv *priv;
++      struct device *dev = &pdev->dev;
++      unsigned int index;
++      void *base;
++      int ret;
++
++      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      priv->dev = dev;
++
++      ret = of_property_read_u32(dev->of_node, "airoha,usb2-monitor-clk-sel",
++                                 &priv->monclk_sel);
++      if (ret)
++              return dev_err_probe(dev, ret, "Monitor clock selection is mandatory for USB PHY calibration.\n");
++
++      if (priv->monclk_sel > 3)
++              return dev_err_probe(dev, -EINVAL, "only 4 Monitor clock are selectable on the SoC.\n");
++
++      base = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(base))
++              return PTR_ERR(base);
++
++      priv->regmap = devm_regmap_init_mmio(dev, base, &airoha_usb_phy_regmap_config);
++      if (IS_ERR(priv->regmap))
++              return PTR_ERR(priv->regmap);
++
++      platform_set_drvdata(pdev, priv);
++
++      for (index = 0; index < AIROHA_PHY_USB_MAX; index++) {
++              enum airoha_usb_phy_instance_type phy_type;
++              struct airoha_usb_phy_instance *instance;
++
++              switch (index) {
++              case AIROHA_PHY_USB2:
++                      phy_type = PHY_TYPE_USB2;
++                      break;
++              case AIROHA_PHY_USB3:
++                      phy_type = PHY_TYPE_USB3;
++                      break;
++              }
++
++              /* Skip registering USB3 instance if not supported */
++              if (phy_type == PHY_TYPE_USB3) {
++                      ret = of_property_read_u32(dev->of_node, "airoha,serdes-port",
++                                                 &priv->serdes_port);
++                      if (ret)
++                              continue;
++
++                      /* With Serdes Port property, SCU is required */
++                      priv->scu = syscon_regmap_lookup_by_phandle(dev->of_node,
++                                                                  "airoha,scu");
++                      if (IS_ERR(priv->scu))
++                              return dev_err_probe(dev, PTR_ERR(priv->scu), "failed to get SCU syscon.\n");
++              }
++
++              instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
++              if (!instance)
++                      return -ENOMEM;
++
++              instance->type = phy_type;
++              priv->phys[index] = instance;
++
++              instance->phy = devm_phy_create(dev, NULL, &airoha_phy);
++              if (IS_ERR(instance->phy))
++                      return dev_err_probe(dev, PTR_ERR(instance->phy), "failed to create phy\n");
++
++              phy_set_drvdata(instance->phy, instance);
++      }
++
++      phy_provider = devm_of_phy_provider_register(&pdev->dev, airoha_usb_phy_xlate);
++
++      return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct of_device_id airoha_phy_id_table[] = {
++      { .compatible = "airoha,an7581-usb-phy" },
++      { },
++};
++MODULE_DEVICE_TABLE(of, airoha_phy_id_table);
++
++static struct platform_driver airoha_usb_driver = {
++      .probe          = airoha_usb_phy_probe,
++      .driver         = {
++              .name   = "airoha-usb-phy",
++              .of_match_table = airoha_phy_id_table,
++      },
++};
++
++module_platform_driver(airoha_usb_driver);
++
++MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Airoha USB PHY driver");
diff --git a/target/linux/airoha/patches-6.6/220-08-usb-host-add-ARCH_AIROHA-in-XHCI-MTK-dependency.patch b/target/linux/airoha/patches-6.6/220-08-usb-host-add-ARCH_AIROHA-in-XHCI-MTK-dependency.patch
new file mode 100644 (file)
index 0000000..3756f76
--- /dev/null
@@ -0,0 +1,25 @@
+From 3d3a406dea89b789dfb550bd05d0eba5ae926755 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 7 Feb 2025 14:17:06 +0100
+Subject: [PATCH 08/10] usb: host: add ARCH_AIROHA in XHCI MTK dependency
+
+Airoha SoC use the same register map a logic of the Mediatek xHCI
+driver, hence add it to the dependency list to permit compilation also
+on this ARCH.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/usb/host/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -71,7 +71,7 @@ config USB_XHCI_HISTB
+ config USB_XHCI_MTK
+       tristate "xHCI support for MediaTek SoCs"
+       select MFD_SYSCON
+-      depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST
++      depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || ARCH_AIROHA || COMPILE_TEST
+       help
+         Say 'Y' to enable the support for the xHCI host controller
+         found in MediaTek SoCs.
diff --git a/target/linux/airoha/patches-6.6/220-10-PCI-mediatek-gen3-set-PHY-mode-for-Airoha-EN7581.patch b/target/linux/airoha/patches-6.6/220-10-PCI-mediatek-gen3-set-PHY-mode-for-Airoha-EN7581.patch
new file mode 100644 (file)
index 0000000..19d168d
--- /dev/null
@@ -0,0 +1,34 @@
+From 112c6ea7ac356dab16e11084f2183e653a289e91 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 28 Oct 2025 12:35:41 +0100
+Subject: [PATCH 10/10] PCI: mediatek-gen3: set PHY mode for Airoha EN7581
+
+For the Airoha EN7581 SoC, the 3rd PCIe line is attached to a special
+PHY that can be both used for USB 3.0 operation or PCIe.
+
+Configure the PHY for PCIe operation before init it to correctly
+configure the SCU Serdes register.
+
+This permits correct functionality and enumeration of PCIe devices on
+the 3rd PCIe line present on the SoC.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/pci/controller/pcie-mediatek-gen3.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/pci/controller/pcie-mediatek-gen3.c
++++ b/drivers/pci/controller/pcie-mediatek-gen3.c
+@@ -925,6 +925,12 @@ static int mtk_pcie_en7581_power_up(stru
+       size = lower_32_bits(resource_size(entry->res));
+       regmap_write(pbus_regmap, args[1], GENMASK(31, __fls(size)));
++      err = phy_set_mode(pcie->phy, PHY_MODE_PCIE);
++      if (err) {
++              dev_err(dev, "failed to set PHY mode\n");
++              return err;
++      }
++
+       /*
+        * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
+        * requires PHY initialization and power-on before PHY reset deassert.