Devicetree
 help / color / mirror / Atom feed
* [PATCH v3 0/3] phy: Add support for Airoha AN7583 USB PHY
@ 2026-08-27 13:15 Christian Marangi
  2026-08-27 13:15 ` [PATCH v3 1/3] dt-bindings: phy: airoha: Document support for " Christian Marangi
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Christian Marangi @ 2026-08-27 13:15 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Christian Marangi, linux-phy, devicetree,
	linux-kernel

This small series add support for Airoha USB PHY and Gen2 PCIe
PHY.

Changes v3:
- Fix broken patch for YAML patch
- Split the YAML for USB and PCIe
- Rework driver to direct node for PCIe PHY

Changes v2:
- Add Documentation
- Out of RFC
- Rework to Serdes PHY instead of SCU (following
  for consistency AN7581 implementation)
  Link: https://lore.kernel.org/all/20260811124724.702467-1-ansuelsmth@gmail.com/

Christian Marangi (3):
  dt-bindings: phy: airoha: Document support for AN7583 USB PHY
  dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY
  phy: airoha: Add support for Airoha AN7583 USB PHY

 .../phy/airoha,an7583-pcie-gen2-phy.yaml      |   63 +
 .../bindings/phy/airoha,an7583-usb-phy.yaml   |  133 ++
 drivers/phy/Kconfig                           |    1 +
 drivers/phy/Makefile                          |    3 +-
 drivers/phy/airoha/Kconfig                    |   11 +
 drivers/phy/airoha/Makefile                   |    3 +
 drivers/phy/airoha/phy-an7583-usb.c           | 2016 +++++++++++++++++
 7 files changed, 2229 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml
 create mode 100644 drivers/phy/airoha/Kconfig
 create mode 100644 drivers/phy/airoha/Makefile
 create mode 100644 drivers/phy/airoha/phy-an7583-usb.c

-- 
2.53.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/3] dt-bindings: phy: airoha: Document support for AN7583 USB PHY
  2026-08-27 13:15 [PATCH v3 0/3] phy: Add support for Airoha AN7583 USB PHY Christian Marangi
@ 2026-08-27 13:15 ` Christian Marangi
  2026-08-27 13:25   ` sashiko-bot
  2026-08-27 13:15 ` [PATCH v3 2/3] dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY Christian Marangi
  2026-08-27 13:15 ` [PATCH v3 3/3] phy: airoha: Add support for Airoha AN7583 USB PHY Christian Marangi
  2 siblings, 1 reply; 7+ messages in thread
From: Christian Marangi @ 2026-08-27 13:15 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Christian Marangi, linux-phy, devicetree,
	linux-kernel

Add documentation for Airoha AN7583 USB PHY that describe the USB PHY
for the USB controller.

Airoha AN7583 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 relevant USB port.

To correctly calibrate, the USB 2.0 port require correct value in
"airoha,usb2-monitor-clk-sel" property. Both the 2 USB 2.0 port permit
selecting one of the 4 monitor clock for calibration (internal clock not
exposed to the system) but each port have only one of the 4 actually
connected in HW hence the correct value needs to be specified in DT
based on board and the physical port. Normally it's monitor clock 1 for
USB1 and monitor clock 2 for USB2.

To correctly setup the Serdes mode attached to the USB 3.0 mode, a phys
property is required with the phandle pointing to the correct Serdes port
provided by the SCU node. Providing the phys property is optional if USB
3.0 is not used.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
 .../bindings/phy/airoha,an7583-usb-phy.yaml   | 133 ++++++++++++++++++
 1 file changed, 133 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml
new file mode 100644
index 000000000000..7ec655253a8e
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml
@@ -0,0 +1,133 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/airoha,an7583-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 AN7583 SoC USB PHY describes the USB PHY for the USB controller..
+
+  Airoha AN7583 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 relevant USB port.
+
+  On Airoha AN7583 there is an unified PHY implementation where a single
+  PHY provide support for both the 2 USB 2.0 port and
+  optionally one 3.0 USB.
+
+properties:
+  compatible:
+    const: airoha,an7583-usb-phy
+
+  reg:
+    items:
+      - description: phy register
+      - description: ana register
+      - description: pma register
+      - description: dig register
+
+  reg-names:
+    items:
+      - const: phy
+      - const: ana
+      - const: pma
+      - const: dig
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  usb3-phy:
+    type: object
+
+    properties:
+      phys:
+        items:
+          - description: phandle to Serdes PHY
+
+      '#phy-cells':
+        description: The cell contains the mode, PHY_TYPE_USB2 or PHY_TYPE_USB3,
+          as defined in dt-bindings/phy/phy.h.
+        const: 1
+
+    required:
+      - phys
+      - '#phy-cells'
+
+    additionalProperties: false
+
+patternProperties:
+  '^usb2-phy@[0-9-a-f]+$':
+    type: object
+
+    properties:
+      reg:
+        enum: [0x0, 0x1000]
+
+      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]
+
+      '#phy-cells':
+        description: The cell contains the mode, PHY_TYPE_USB2 or PHY_TYPE_USB3,
+          as defined in dt-bindings/phy/phy.h.
+        const: 1
+
+    required:
+      - reg
+      - airoha,usb2-monitor-clk-sel
+      - '#phy-cells'
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - '#address-cells'
+  - '#size-cells'
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    phy@1fac0000 {
+        compatible = "airoha,an7583-usb-phy";
+        reg = <0x1fac0000 0x11ff>,
+              <0x1fa6f000 0xff>,
+              <0x1fa6e000 0x3ff>,
+              <0x1fa6a000 0x8ff>;
+        reg-names = "phy", "ana", "pma", "dig";
+
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        usb2-phy@0 {
+            reg = <0x0>;
+            airoha,usb2-monitor-clk-sel = <0>;
+
+            #phy-cells = <1>;
+        };
+
+        usb2-phy@1000 {
+            reg = <0x1000>;
+            airoha,usb2-monitor-clk-sel = <1>;
+
+            #phy-cells = <1>;
+        };
+
+        usb3-phy {
+            phys = <&serdes_phy>;
+
+            #phy-cells = <1>;
+        };
+    };
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/3] dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY
  2026-08-27 13:15 [PATCH v3 0/3] phy: Add support for Airoha AN7583 USB PHY Christian Marangi
  2026-08-27 13:15 ` [PATCH v3 1/3] dt-bindings: phy: airoha: Document support for " Christian Marangi
@ 2026-08-27 13:15 ` Christian Marangi
  2026-08-27 13:23   ` sashiko-bot
  2026-08-27 13:15 ` [PATCH v3 3/3] phy: airoha: Add support for Airoha AN7583 USB PHY Christian Marangi
  2 siblings, 1 reply; 7+ messages in thread
From: Christian Marangi @ 2026-08-27 13:15 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Christian Marangi, linux-phy, devicetree,
	linux-kernel

Document support for AN7583 Gen2 PCIe PHY used to make the Gen2 PCIe port
work. Add the required register to configure the PCIe PHY and provide an
example for it.

Similar to the USB 3.0 PHY, a dedicated phys property is required to
configure the serdes for PCIe or Ethernet usage.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
 .../phy/airoha,an7583-pcie-gen2-phy.yaml      | 63 +++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml

diff --git a/Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml
new file mode 100644
index 000000000000..f31d838871fc
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/airoha,an7583-pcie-gen2-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha AN7581 SoC PCIe Gen2 PHY
+
+maintainers:
+  - Christian Marangi <ansuelsmth@gmail.com>
+
+description: >
+  The Airoha AN7583 SoC PCIe Gen2 PHY describes the PCIe PHY for the
+  Gen2 PCIe controller.
+
+  This PCIe PHY makes use of a dedicated USB PHY for PCIe usage and
+  can also be used for Ethernet usage for SGMII or HSGMII mode.
+
+properties:
+  compatible:
+    const: airoha,an7583-pcie-phy
+
+  reg:
+    items:
+      - description: ana register
+      - description: pma register
+      - description: dig register
+
+  reg-names:
+    items:
+      - const: ana
+      - const: pma
+      - const: dig
+
+  phys:
+    items:
+      - description: phandle to Serdes PHY
+
+  '#phy-cells':
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - phys
+  - '#phy-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    phy@1fa5f000 {
+        compatible = "airoha,an7583-pcie-phy";
+        reg = <0x1fa5f000 0xff>,
+              <0x1fa5e000 0x3ff>,
+              <0x1fa5a000 0x8ff>;
+        reg-names = "ana", "pma", "dig";
+
+        phys = <&serdes_phy>;
+
+        #phy-cells = <0>;
+    };
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 3/3] phy: airoha: Add support for Airoha AN7583 USB PHY
  2026-08-27 13:15 [PATCH v3 0/3] phy: Add support for Airoha AN7583 USB PHY Christian Marangi
  2026-08-27 13:15 ` [PATCH v3 1/3] dt-bindings: phy: airoha: Document support for " Christian Marangi
  2026-08-27 13:15 ` [PATCH v3 2/3] dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY Christian Marangi
@ 2026-08-27 13:15 ` Christian Marangi
  2026-08-27 13:26   ` sashiko-bot
  2 siblings, 1 reply; 7+ messages in thread
From: Christian Marangi @ 2026-08-27 13:15 UTC (permalink / raw)
  To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Christian Marangi, linux-phy, devicetree,
	linux-kernel

Add support for USB PHY for Airoha AN7583 SoC, this share some U2 init
from AN7581 but use a totally different init phase for PLL and
calibration for U3. Also on AN7583 there is a single USB PHY that init 2
U2 port and one U3 port. (the USB controller expose 2 hub, one with 2
usb 2.0 port and one with one 3.0 port)

A second USB PHY is used for PCIe Gen2 controller and follow the same
calibration and setup logic of USB.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
 drivers/phy/Kconfig                 |    1 +
 drivers/phy/Makefile                |    3 +-
 drivers/phy/airoha/Kconfig          |   11 +
 drivers/phy/airoha/Makefile         |    3 +
 drivers/phy/airoha/phy-an7583-usb.c | 2016 +++++++++++++++++++++++++++
 5 files changed, 2033 insertions(+), 1 deletion(-)
 create mode 100644 drivers/phy/airoha/Kconfig
 create mode 100644 drivers/phy/airoha/Makefile
 create mode 100644 drivers/phy/airoha/phy-an7583-usb.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 19f3b7d12b7d..80b7c50fd768 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -168,6 +168,7 @@ config PHY_XGENE
 	help
 	  This option enables support for APM X-Gene SoC multi-purpose PHY.
 
+source "drivers/phy/airoha/Kconfig"
 source "drivers/phy/allwinner/Kconfig"
 source "drivers/phy/amlogic/Kconfig"
 source "drivers/phy/apple/Kconfig"
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index d7aa516bcc49..0baf0b7fd077 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -20,7 +20,8 @@ obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy-pistachio-usb.o
 obj-$(CONFIG_PHY_SNPS_EUSB2)		+= phy-snps-eusb2.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
 
-obj-$(CONFIG_GENERIC_PHY)		+= allwinner/	\
+obj-$(CONFIG_GENERIC_PHY)		+= airoha/	\
+					   allwinner/	\
 					   amlogic/	\
 					   apple/	\
 					   axiado/	\
diff --git a/drivers/phy/airoha/Kconfig b/drivers/phy/airoha/Kconfig
new file mode 100644
index 000000000000..13e49ff947e3
--- /dev/null
+++ b/drivers/phy/airoha/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config PHY_AIROHA_AN7583_USB
+	tristate "Airoha AN7583 USB PHY Driver"
+	depends on ARCH_AIROHA || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Say 'Y' here to add support for Airoha AN7583 USB PHY driver.
+ 	  This driver create the basic PHY instance and provides initialize
+ 	  callback for USB port.
diff --git a/drivers/phy/airoha/Makefile b/drivers/phy/airoha/Makefile
new file mode 100644
index 000000000000..e484a803505b
--- /dev/null
+++ b/drivers/phy/airoha/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_PHY_AIROHA_AN7583_USB)	+= phy-an7583-usb.o
diff --git a/drivers/phy/airoha/phy-an7583-usb.c b/drivers/phy/airoha/phy-an7583-usb.c
new file mode 100644
index 000000000000..33915c9f4a0d
--- /dev/null
+++ b/drivers/phy/airoha/phy-an7583-usb.c
@@ -0,0 +1,2016 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Christian Marangi <ansuelsmth@gmail.com>
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/bitfield.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* PHY */
+#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_USBPHYACR2		0x308
+#define   AIROHA_USB_PHY_SIFSLV_MAC_BANDGAP_EN	BIT(17)
+#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_DISC_FIT_EN	BIT(28)
+#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_HSRX_BIAS_EN_SEL	 GENMASK(10, 9)
+#define   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL_ENPLL \
+	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL, 0x0)
+#define   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL_IDLEB_RCV_EN \
+	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL, 0x1)
+#define   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL_NO_ENPLL_FS_BIAS_EN \
+	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL, 0x2)
+#define   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL_USB20_HSRX_TMODE_EN \
+	FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL, 0x3)
+#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_U2PHYACR3		0x31c
+#define   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE	GENMASK(25, 24)
+#define   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE_TOGGLE FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE, 0x0)
+#define   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE_HS_TERM FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE, 0x1)
+#define   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE_FORCE_DISABLE FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE, 0x2)
+#define   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE_FORCE_ENABLE FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE, 0x3)
+#define   AIROHA_USB_PHY_USB20_USB11_TMODE_EN	BIT(19)
+#define   AIROHA_USB_PHY_USB20_TMODE_FS_LS_TX_EN BIT(18)
+#define   AIROHA_USB_PHY_USB20_PUPD_BIST_EN	BIT(12)
+#define AIROHA_USB_PHY_U2PHYDTM0		0x368
+#define   AIROHA_USB_PHY_FORCE_XCVRSEL		BIT(19)
+#define   AIROHA_USB_PHY_FORCE_SUSPENDDM	BIT(18)
+#define   AIROHA_USB_PHY_FORCE_TERMSEL		BIT(17)
+#define   AIROHA_USB_PHY_XCVRSEL		GENMASK(5, 4)
+#define   AIROHA_USB_PHY_TERMSEL		BIT(2)
+#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)
+
+/* ANA */
+#define AIROHA_USB_ANA_RXAFE_RESERVE		0x4
+#define   AIROHA_USB_ANA_CDR_PD_10B_EN		BIT(11)
+#define   AIROHA_USB_ANA_CDR_PD_EDGE_DIS	BIT(10)
+#define AIROHA_USB_ANA_CDR_LPF_BOT_LIM		0x8
+#define   AIROHA_USB_ANA_CDR_LPF_KP_GAIN	GENMASK(26, 24)
+#define   AIROHA_USB_ANA_CDR_LPF_KI_GAIN	GENMASK(22, 20)
+#define AIROHA_USB_ANA_CDR_LPF_MJV_LIM		0xc
+#define   AIROHA_USB_ANA_CDR_LPF_RATIO		GENMASK(5, 4)
+#define AIROHA_USB_ANA_CDR_PR_CKREF_DIV1	0x18
+#define   AIROHA_USB_ANA_CDR_PR_KBAND_DIV	GENMASK(26, 24)
+#define   AIROHA_USB_ANA_CDR_PR_DAC_BAND	GENMASK(12, 8)
+#define AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE_REG 0x1c
+#define   AIROHA_USB_ANA_CDR_PR_XFICK_EN	BIT(30)
+#define   AIROHA_USB_ANA_CDR_PR_KBAND_PCIE_MODE	BIT(6)
+#define   AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE	GENMASK(5, 0)
+#define AIROHA_USB_ANA_CDR_FORCE_IBANDLPF_R_OFF	0x20
+#define   AIROHA_USB_ANA_CDR_PHYCK_RSTB		BIT(13)
+#define AIROHA_USB_ANA_QP_TX_MODE_16B_EN	0x28
+#define   AIROHA_USB_QP_TX_RESERVE		GENMASK(31, 16)
+#define     AIROHA_USB_ANA_TX_VLMON_EN		BIT(2)
+#define     AIROHA_USB_ANA_TX_RESERVE_8		BIT(8)
+#define AIROHA_USB_ANA_RXLBTX_EN		0x2c
+#define   AIROHA_USB_ANA_TX_DMEDGEGEN_EN	BIT(27)
+#define   AIROHA_USB_ANA_TX_RXDET_METHOD	BIT(25)
+#define AIROHA_USB_ANA_SSUSB_BGR_EN		0x30
+#define   AIROHA_USB_ANA_BIAS_V2V_CAL		GENMASK(26, 21)
+#define   AIROHA_USB_ANA_SSUSB_BG_DIV		GENMASK(3, 2)
+#define   AIROHA_USB_ANA_SSUSB_CHPEN		BIT(1)
+#define AIROHA_USB_ANA_CLKDRV_IMPSEL		0x34
+#define   AIROHA_USB_ANA_PCIE_CLKDRV_AMP	GENMASK(27, 25)
+#define   AIROHA_USB_ANA_PCIE_CLKDRV_FORCEIN	GENMASK(24, 23)
+#define   AIROHA_USB_ANA_PCIE_CLKDRV_HZ		BIT(14)
+#define   AIROHA_USB_ANA_PCIE_CLKDRV_RP		GENMASK(13, 9)
+#define   AIROHA_USB_ANA_PCIE_CLKDRV_IMPSEL	GENMASK(4, 0)
+#define AIROHA_USB_ANA_TDC_FT_CK_EN		0x38
+#define   AIROHA_USB_ANA_PLL_DEBUG_SEL		BIT(19)
+#define   AIROHA_USB_ANA_VUSB10_ON		BIT(8)
+#define AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL	0x3c
+#define   AIROHA_USB_ANA_PLL_PREDIV		GENMASK(26, 25)
+#define   AIROHA_USB_ANA_PLL_OSCAL_ENB		BIT(19)
+#define   AIROHA_USB_ANA_PLL_MON_LDO_SEL	GENMASK(18, 16)
+#define   AIROHA_USB_ANA_PLL_MONVC_EN		BIT(14)
+#define   AIROHA_USB_ANA_PLL_LDOLPF_VSEL	GENMASK(6, 5)
+#define AIROHA_USB_ANA_PLL_SDM_ORD		0x40
+#define   AIROHA_USB_ANA_PLL_SSC_TRI_EN		BIT(4)
+#define   AIROHA_USB_ANA_PLL_SSC_PHASE_INI	BIT(3)
+
+/* PMA */
+#define AIROHA_USB_PMA_TX_DA_CTRL_0		0x0
+#define   AIROHA_USB_PMA_RXDET_RD_WAIT_TIMER	GENMASK(15, 12)
+#define   AIROHA_USB_PMA_RXDET_EN_WINDOW	GENMASK(9, 4)
+#define AIROHA_USB_PMA_TX_DA_CTRL_1		0x4
+#define   AIROHA_USB_PMA_FORCE_TX_BIT_INVERSE	BIT(7)
+#define AIROHA_USB_PMA_TX_DA_CTRL_2		0x8
+#define   AIROHA_USB_PMA_FORCE_TX_DEM_SEL	BIT(27)
+#define AIROHA_USB_PMA_TX_DA_CTRL_3		0xc
+#define   AIROHA_USB_PMA_TX_DATA_RATE_SEL	GENMASK(30, 28)
+#define AIROHA_USB_PMA_PON_RXFEDIG_CTRL_0	0x100
+#define   AIROHA_USB_PMA_EQ_RX500M_CK_SEL	BIT(12)
+#define AIROHA_USB_PMA_PON_RXFEDIG_CTRL_8	0x120
+#define   AIROHA_USB_PMA_QP_EQ_EYE_MASK		GENMASK(9, 0)
+#define AIROHA_USB_PMA_PON_RXFEDIG_CTRL_10	0x128
+#define   AIROHA_USB_PMA_QP_EQ_PIEYE_INI	GENMASK(22, 16)
+#define AIROHA_USB_PMA_SS_LCPLL_PWCTL_SETTING_2	0x208
+#define   AIROHA_USB_PMA_NCPO_ANA_MSB		GENMASK(17, 16)
+#define AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_2	0x230
+#define   AIROHA_USB_PMA_LCPLL_NCPO_VALUE	GENMASK(30, 0)
+#define AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_5	0x23c
+#define   AIROHA_USB_PMA_LCPLL_NCPO_CHG		BIT(24)
+#define AIROHA_USB_PMA_SS_LCPLL_TDC_PCW_1	0x248
+#define   AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON GENMASK(30, 0)
+#define AIROHA_USB_PMA_INTF_CTRL_5		0x314
+#define   AIROHA_USB_PMA_RX_HZ_SEL		BIT(5)
+#define   AIROHA_USB_PMA_RX_HZ_FORCE		BIT(4)
+#define AIROHA_USB_PMA_INTF_CTRL_6		0x318
+#define   AIROHA_USB_PMA_TX_DATA_EN_SEL		BIT(13)
+#define   AIROHA_USB_PMA_TX_DATA_EN_FORCE	BIT(12)
+#define AIROHA_USB_PMA_INTF_CTRL_7		0x31c
+#define   AIROHA_USB_PMA_PLL_EN_SEL		BIT(5)
+#define   AIROHA_USB_PMA_PLL_EN_FORCE		BIT(4)
+#define AIROHA_USB_PMA_INTF_CTRL_8		0x320
+#define   AIROHA_USB_PMA_XTAL_EXT_EN_SEL	BIT(13)
+#define   AIROHA_USB_PMA_XTAL_EXT_EN_FORCE	GENMASK(12, 11)
+#define   AIROHA_USB_PMA_TX_TERM_SEL_SEL	BIT(7)
+#define   AIROHA_USB_PMA_TX_TERM_SEL_FORCE	GENMASK(6, 5)
+#define AIROHA_USB_PMA_INTF_STS_9		0x364
+#define   AIROHA_USB_PMA_RX_IMP_SEL_SEL		BIT(31)
+#define   AIROHA_USB_PMA_RX_IMP_SEL_FORCE	GENMASK(30, 26)
+#define   AIROHA_USB_PMA_ADDR_INTF_STS_PLL_VCOCAL GENMASK(23, 16)
+#define AIROHA_USB_PMA_PLL_CTRL_0		0x400
+#define   AIROHA_USB_PMA_AUTO_INIT		BIT(0)
+#define AIROHA_USB_PMA_PLL_CTRL_1		0x404
+#define   AIROHA_USB_PMA_PLL_SSC_EN		BIT(30)
+#define AIROHA_USB_PMA_PLL_CTRL_2		0x408
+#define   AIROHA_USB_PMA_PLL_SDM_IFM_INTF	BIT(30)
+#define   AIROHA_USB_PMA_PLL_RICO_SEL_INTF	BIT(29)
+#define   AIROHA_USB_PMA_PLL_PHY_CK_EN_INTF	BIT(27)
+#define   AIROHA_USB_PMA_PLL_PCK_SEL_INTF	BIT(22)
+#define   AIROHA_USB_PMA_PLL_KBAND_PREDIV_INTF	GENMASK(21, 20)
+#define   AIROHA_USB_PMA_PLL_IR_INTF		GENMASK(19, 16)
+#define   AIROHA_USB_PMA_PLL_ICOIQ_EN_INTF	BIT(14)
+#define   AIROHA_USB_PMA_PLL_FBKSEL_INTF	GENMASK(13, 12)
+#define   AIROHA_USB_PMA_PLL_BR_INTF		GENMASK(10, 8)
+#define   AIROHA_USB_PMA_PLL_BPB_INTF		GENMASK(7, 6)
+#define   AIROHA_USB_PMA_PLL_BPA_INTF		GENMASK(4, 2)
+#define   AIROHA_USB_PMA_PLL_BC_INTF		GENMASK(1, 0)
+#define AIROHA_USB_PMA_PLL_CTRL_3		0x40c
+#define   AIROHA_USB_PMA_PLL_SSC_PERIOD_INTF	GENMASK(31, 16)
+#define   AIROHA_USB_PMA_PLL_SSC_DELTA_INTF	GENMASK(15, 0)
+#define AIROHA_USB_PMA_PLL_CTRL_4		0x410
+#define   AIROHA_USB_PMA_PLL_SDM_HREN_INTF	GENMASK(4, 3)
+#define   AIROHA_USB_PMA_PLL_ICOLP_EN_INTF	BIT(2)
+#define AIROHA_USB_PMA_PLL_CK_CTRL_0		0x414
+#define   AIROHA_USB_PMA_PCIE_CLKTX_EN_INTF	BIT(5)
+#define   AIROHA_USB_PMA_PCIE_CLKRX_EN_INTF	BIT(4)
+#define AIROHA_USB_PMA_PLL_CK_CTRL_1		0x418
+#define   AIROHA_USB_PMA_PLL_FORCE_UNSTABLE	BIT(19)
+#define   AIROHA_USB_PMA_PLL_FORCE_STABLE	BIT(18)
+#define AIROHA_USB_PMA_PLL_CK_CTRL_2		0x41c
+#define   AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_OFF_EN BIT(2)
+#define   AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_ON_EN BIT(1)
+#define   AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_EN	BIT(0)
+#define AIROHA_USB_PMA_RX_SYS_CTRL_0		0x600
+#define   AIROHA_USB_PMA_ROC_CK_EN		BIT(1)
+#define AIROHA_USB_PMA_RX_DLY_0			0x614
+#define   AIROHA_USB_PMA_RX_PI_CAL_EN_H_DLY	GENMASK(7, 0)
+#define AIROHA_USB_PMA_RX_CTRL_2		0x630
+#define   AIROHA_USB_PMA_RX_EQ_EN_H_DLY		GENMASK(28, 16)
+#define AIROHA_USB_PMA_RX_CTRL_5		0x63c
+#define   AIROHA_USB_PMA_FREDET_CHK_CYCLE	GENMASK(29, 10)
+#define AIROHA_USB_PMA_RX_CTRL_6		0x640
+#define   AIROHA_USB_PMA_FREDET_GOLDEN_CYCLE	GENMASK(19, 0)
+#define AIROHA_USB_PMA_RX_CTRL_7		0x644
+#define   AIROHA_USB_PMA_FREDET_TOLERATE_CYCLE	GENMASK(19, 0)
+#define AIROHA_USB_PMA_RX_CTRL_10		0x650
+#define   AIROHA_USB_PMA_CRSDET_RSTB		BIT(1)
+#define AIROHA_USB_PMA_RX_CTRL_11		0x654
+#define   AIROHA_USB_PMA_FORCE_SIGDET_5G	BIT(19)
+#define AIROHA_USB_PMA_RX_CTRL_26		0x690
+#define   AIROHA_USB_PMA_QP_EQ_RETRAIN_ONLY_EN	BIT(26)
+#define   AIROHA_USB_PMA_LINK_ERRO_EN		BIT(23)
+#define AIROHA_USB_PMA_RX_CTRL_27		0x694
+#define   AIROHA_USB_PMA_QP_LINK_ERRO_CNT	GENMASK(31, 0)
+#define AIROHA_USB_PMA_RX_CTRL_36		0x6b8
+#define   AIROHA_USB_PMA_PCIE_USB_SYSTEM	BIT(26)
+#define   AIROHA_USB_PMA_LCK2DATA_DLY_TIME	GENMASK(23, 16)
+#define AIROHA_USB_PMA_RX_CTRL_38		0x6C0
+#define   AIROHA_USB_PMA_RESERVE_3		GENMASK(31, 24)
+#define AIROHA_USB_PMA_RX_CTRL_45		0x6dc
+#define   AIROHA_USB_PMA_EQ_EN_DLY		GENMASK(12, 0)
+#define AIROHA_USB_PMA_RX_CTRL_46		0x6e0
+#define   AIROHA_USB_PMA_PCIE_USB_BYPASS_EQ_P3_TO_P0_EN	BIT(29)
+#define   AIROHA_USB_PMA_PCIE_USB_BYPASS_EQ_P2_TO_P0_EN	BIT(28)
+#define   AIROHA_USB_PMA_PCIE_USB_BYPASS_EQ_P1_TO_P0_EN	BIT(27)
+#define   AIROHA_USB_PMA_REBACK_P0_LCK2REF_EN	BIT(26)
+#define AIROHA_USB_PMA_RX_CTRL_49		0x6ec
+#define   AIROHA_USB_PMA_LFPS_FINISH_TIME	GENMASK(31, 21)
+#define AIROHA_USB_PMA_RX_CTRL_50		0x6f0
+#define   AIROHA_USB_PMA_P3_TO_P0_DO_EQ_USB	BIT(28)
+#define   AIROHA_USB_PMA_P2_TO_P0_DO_EQ_USB	BIT(27)
+#define   AIROHA_USB_PMA_P1_TO_P0_DO_EQ_USB	BIT(26)
+#define   AIROHA_USB_PMA_EQ_EN_DLY_SHORT	GENMASK(25, 13)
+#define   AIROHA_USB_PMA_RX_EQ_EN_H_DLY_SHORT	GENMASK(12, 0)
+
+/* DIG */
+#define AIROHA_USB_DIG_CK_RST_CTRL_3		0x30c
+#define   AIROHA_USB_DIG_NS_CK_DIV_SEL		BIT(25)
+#define   AIROHA_USB_DIG_US_CK_DIV_SEL		BIT(24)
+#define AIROHA_USB_DIG_MODE_CTRL_0		0x324
+#define   AIROHA_USB_DIG_SGMII_AN_EN		BIT(0)
+#define AIROHA_USB_DIG_MODE_CTRL_1		0x330
+#define   AIROHA_USB_DIG_TPHY_SPEED		GENMASK(3, 2)
+#define AIROHA_USB_DIG_CK_RST_CTRL_7		0x340
+#define   AIROHA_USB_DIG_MULTI_USB2P5_EN	BIT(26)
+#define   AIROHA_USB_DIG_MULTI_USB5_EN		BIT(25)
+#define   AIROHA_USB_DIG_MULTI_PHY_USB_EN	BIT(24)
+
+#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_FREQDET_SLEEP		1000 /* 1ms */
+#define AIROHA_USB_PHY_FREQDET_TIMEOUT		(AIROHA_USB_PHY_FREQDET_SLEEP * 10)
+
+#define AIROHA_USB_PHY_U3_MAX_CALIB_TRY		50
+#define AIROHA_USB_PHY_MAX_INSTANCE		3
+#define AIROHA_PCIE_PHY_MAX_INSTANCE		1
+
+struct an7583_usb_phy_instance {
+	struct device_node *node;
+	u32 type;
+
+	u32 offset;
+	unsigned int monclk_sel;
+	struct phy *serdes_phy;
+};
+
+enum an7583_usb_phy_regs {
+	AIROHA_USB_PHY_PHY,
+	AIROHA_USB_PHY_ANA,
+	AIROHA_USB_PHY_PMA,
+	AIROHA_USB_PHY_DIG,
+
+	AIROHA_USB_PHY_REGS_MAX,
+};
+
+struct an7583_usb_phy_priv {
+	struct regmap *regs[AIROHA_USB_PHY_REGS_MAX];
+
+	struct phy *phys[AIROHA_USB_PHY_MAX_INSTANCE];
+};
+
+struct an7583_usb_phy_match_data {
+	int max_instance;
+	const char * const *regs_name;
+	int regs_num;
+	int (*parse_ports)(struct device *dev,
+			   struct an7583_usb_phy_priv *priv,
+			   int index, struct device_node *subnode);
+};
+
+static int an7583_usb_phy_u2_slew_rate_calibration(struct phy *phy)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+	u32 fm_out, srctrl;
+	u32 offset;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+	offset = instance->offset;
+
+	/* Enable HS TX SR calibration */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_USBPHYACR5 + offset,
+			AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+	usleep_range(1000, 1500);
+
+	/* Enable Free run clock */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_FMMONR1 + offset,
+			AIROHA_USB_PHY_FRCK_EN);
+
+	/* Select Monitor Clock */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_FMCR0 + offset,
+			   AIROHA_USB_PHY_MONCLK_SEL,
+			   FIELD_PREP(AIROHA_USB_PHY_MONCLK_SEL,
+				      instance->monclk_sel));
+
+	/* Set cyclecnt */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_FMCR0 + offset,
+			   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->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_FMCR0 + offset,
+			AIROHA_USB_PHY_FREQDET_EN);
+
+	/* Timeout can happen and we will apply workaround at the end */
+	regmap_read_poll_timeout(priv->regs[AIROHA_USB_PHY_PHY],
+				 AIROHA_USB_PHY_FMMONR0 + offset,
+				 fm_out, fm_out, AIROHA_USB_PHY_FREQDET_SLEEP,
+				 AIROHA_USB_PHY_FREQDET_TIMEOUT);
+
+	/* Disable Frequency meter */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_FMCR0 + offset,
+			  AIROHA_USB_PHY_FREQDET_EN);
+
+	/* Disable Free run clock */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_FMMONR1 + offset,
+			  AIROHA_USB_PHY_FRCK_EN);
+
+	/* Disable HS TX SR calibration */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_USBPHYACR5 + offset,
+			  AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
+
+	usleep_range(1000, 1500);
+
+	/* Frequency was not detected, use default SR calibration value */
+	if (!fm_out) {
+		srctrl = 0x5;
+		dev_err(dev, "Frequency not detected, using default SR calibration.\n");
+	/* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */
+	} else {
+		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(dev, "SR calibration applied: %x\n", srctrl);
+	}
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_USBPHYACR5 + offset,
+			   AIROHA_USB_PHY_USB20_HSTX_SRCTRL,
+			   FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl));
+
+	return 0;
+}
+
+static bool an7583_usb_phy_u3_kband_is_calibrated(struct an7583_usb_phy_priv *priv)
+{
+	u32 val, res;
+
+	/* Default ICO setting */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			  AIROHA_USB_PMA_PLL_CTRL_4,
+			  AIROHA_USB_PMA_PLL_ICOLP_EN_INTF);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_SSUSB_BGR_EN,
+			   AIROHA_USB_ANA_BIAS_V2V_CAL,
+			   FIELD_PREP(AIROHA_USB_ANA_BIAS_V2V_CAL, 0x15));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL,
+			   AIROHA_USB_ANA_PLL_OSCAL_ENB |
+			   AIROHA_USB_ANA_PLL_LDOLPF_VSEL,
+			   AIROHA_USB_ANA_PLL_OSCAL_ENB |
+			   FIELD_PREP(AIROHA_USB_ANA_PLL_LDOLPF_VSEL, 0x1));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_PLL_CTRL_2,
+			AIROHA_USB_PMA_PLL_RICO_SEL_INTF);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			  AIROHA_USB_PMA_INTF_CTRL_8,
+			  AIROHA_USB_PMA_XTAL_EXT_EN_SEL |
+			  AIROHA_USB_PMA_XTAL_EXT_EN_FORCE);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_PLL_CTRL_2,
+			AIROHA_USB_PMA_PLL_ICOIQ_EN_INTF);
+
+	/* Read KBand */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			  AIROHA_USB_ANA_TDC_FT_CK_EN,
+			  AIROHA_USB_ANA_PLL_DEBUG_SEL);
+
+	mdelay(5);
+
+	regmap_read(priv->regs[AIROHA_USB_PHY_PMA],
+		    AIROHA_USB_PMA_INTF_STS_9, &val);
+	res = FIELD_GET(AIROHA_USB_PMA_ADDR_INTF_STS_PLL_VCOCAL, val) << 4;
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			AIROHA_USB_ANA_TDC_FT_CK_EN,
+			AIROHA_USB_ANA_PLL_DEBUG_SEL);
+
+	mdelay(5);
+
+	regmap_read(priv->regs[AIROHA_USB_PHY_PMA],
+		    AIROHA_USB_PMA_INTF_STS_9, &val);
+	res |= FIELD_GET(AIROHA_USB_PMA_ADDR_INTF_STS_PLL_VCOCAL, val);
+
+	/*
+	 * KBand is calibrated if KBand Code is NOT 0xfff and
+	 * KBand Done is set.
+	 */
+	return res != 0xfff && res & 0x800;
+}
+
+static int an7583_usb_phy_u2_init(struct phy *phy)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+	u32 offset;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+	offset = instance->offset;
+
+	mdelay(1);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_USBPHYACR4 + offset,
+			   AIROHA_USB_PHY_USB20_FS_CR,
+			   AIROHA_USB_PHY_USB20_FS_CR_MIN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_USBPHYACR4 + offset,
+			   AIROHA_USB_PHY_USB20_FS_SR,
+			   AIROHA_USB_PHY_USB20_FS_SR_NORMAL);
+
+	/* FIXME: evaluate if needed */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_USBPHYACR6 + offset,
+			   AIROHA_USB_PHY_USB20_SQTH,
+			   AIROHA_USB_PHY_USB20_SQTH_125);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_USBPHYACR6 + offset,
+			   AIROHA_USB_PHY_USB20_DISCTH,
+			   AIROHA_USB_PHY_USB20_DISCTH_580);
+
+	/* Enable the USB port and then disable after calibration */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_USBPHYACR6 + offset,
+			  AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	an7583_usb_phy_u2_slew_rate_calibration(phy);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_USBPHYACR6 + offset,
+			AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	usleep_range(1000, 1500);
+
+	return 0;
+}
+
+static int an7583_usb_phy_eth_init_sgmii(struct an7583_usb_phy_priv *priv)
+{
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_27,
+			   AIROHA_USB_PMA_QP_LINK_ERRO_CNT,
+			   FIELD_PREP(AIROHA_USB_PMA_QP_LINK_ERRO_CNT, 0x100000));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_PCW_1,
+			   AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+				      0x48000000));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_DIG],
+			   AIROHA_USB_DIG_MODE_CTRL_1,
+			   AIROHA_USB_DIG_TPHY_SPEED,
+			   FIELD_PREP(AIROHA_USB_DIG_TPHY_SPEED, 0x0));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_2,
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   AIROHA_USB_PMA_PLL_IR_INTF,
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_IR_INTF, 0x4));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_2,
+			   AIROHA_USB_PMA_LCPLL_NCPO_VALUE,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_NCPO_VALUE, 0x48000000));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_LPF_MJV_LIM,
+			   AIROHA_USB_ANA_CDR_LPF_RATIO,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_RATIO, 0x2));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_CKREF_DIV1,
+			   AIROHA_USB_ANA_CDR_PR_DAC_BAND,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_DAC_BAND, 0xc));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_LPF_BOT_LIM,
+			   AIROHA_USB_ANA_CDR_LPF_KP_GAIN |
+			   AIROHA_USB_ANA_CDR_LPF_KI_GAIN,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_KP_GAIN, 0x6) |
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_KI_GAIN, 0x6));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_5,
+			   AIROHA_USB_PMA_FREDET_CHK_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_CHK_CYCLE, 0x28));
+
+	return 0;
+}
+
+static int an7583_usb_phy_eth_init_hsgmii(struct an7583_usb_phy_priv *priv)
+{
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_PCW_1,
+			   AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+				      0x7a000000));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_DIG],
+			   AIROHA_USB_DIG_MODE_CTRL_1,
+			   AIROHA_USB_DIG_TPHY_SPEED,
+			   FIELD_PREP(AIROHA_USB_DIG_TPHY_SPEED, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_2,
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   AIROHA_USB_PMA_PLL_IR_INTF,
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_IR_INTF, 0x6));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_2,
+			   AIROHA_USB_PMA_LCPLL_NCPO_VALUE,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_NCPO_VALUE, 0x7a000000));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_LPF_MJV_LIM,
+			   AIROHA_USB_ANA_CDR_LPF_RATIO,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_RATIO, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_CKREF_DIV1,
+			   AIROHA_USB_ANA_CDR_PR_DAC_BAND,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_DAC_BAND, 0xf));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_LPF_BOT_LIM,
+			   AIROHA_USB_ANA_CDR_LPF_KP_GAIN |
+			   AIROHA_USB_ANA_CDR_LPF_KI_GAIN,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_KP_GAIN, 0x5) |
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_KI_GAIN, 0x5));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_5,
+			   AIROHA_USB_PMA_FREDET_CHK_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_CHK_CYCLE, 0x10));
+
+	return 0;
+}
+
+static int an7583_usb_phy_set_mode_eth(struct phy *phy, int submode)
+{
+	struct an7583_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	/* TODO handle efuse */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_8,
+			   AIROHA_USB_PMA_TX_TERM_SEL_SEL |
+			   AIROHA_USB_PMA_TX_TERM_SEL_FORCE,
+			   AIROHA_USB_PMA_TX_TERM_SEL_SEL |
+			   FIELD_PREP(AIROHA_USB_PMA_TX_TERM_SEL_FORCE, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_STS_9,
+			   AIROHA_USB_PMA_RX_IMP_SEL_SEL |
+			   AIROHA_USB_PMA_RX_IMP_SEL_FORCE,
+			   AIROHA_USB_PMA_RX_IMP_SEL_SEL |
+			   FIELD_PREP(AIROHA_USB_PMA_RX_IMP_SEL_FORCE, 0x1));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_26,
+			AIROHA_USB_PMA_QP_EQ_RETRAIN_ONLY_EN |
+			AIROHA_USB_PMA_LINK_ERRO_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_SSUSB_BGR_EN,
+			   AIROHA_USB_ANA_SSUSB_BG_DIV,
+			   FIELD_PREP(AIROHA_USB_ANA_SSUSB_BG_DIV, 0x1));
+
+	/* Digital CLK trigger reverse */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PON_RXFEDIG_CTRL_0,
+			  AIROHA_USB_PMA_EQ_RX500M_CK_SEL);
+
+	/* Common Setting */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_CK_RST_CTRL_3,
+			AIROHA_USB_DIG_NS_CK_DIV_SEL |
+			AIROHA_USB_DIG_US_CK_DIV_SEL);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_TX_DA_CTRL_1,
+			  AIROHA_USB_PMA_FORCE_TX_BIT_INVERSE);
+
+	/* TODO check they report 0x8400000 */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_TX_DA_CTRL_2,
+			AIROHA_USB_PMA_FORCE_TX_DEM_SEL);
+
+	/* PLL */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_2,
+			   AIROHA_USB_PMA_PLL_BR_INTF |
+			   AIROHA_USB_PMA_PLL_BPB_INTF |
+			   AIROHA_USB_PMA_PLL_BPA_INTF |
+			   AIROHA_USB_PMA_PLL_BC_INTF,
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BR_INTF, 0x3) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BPB_INTF, 0x0) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BPA_INTF, 0x5) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BC_INTF, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL,
+			   AIROHA_USB_ANA_PLL_PREDIV,
+			   FIELD_PREP(AIROHA_USB_ANA_PLL_PREDIV, 0x1));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_4,
+			AIROHA_USB_PMA_PLL_ICOLP_EN_INTF);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_MODE_CTRL_0,
+			  AIROHA_USB_DIG_SGMII_AN_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_RXLBTX_EN,
+			AIROHA_USB_ANA_TX_DMEDGEGEN_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_QP_TX_MODE_16B_EN,
+			FIELD_PREP(AIROHA_USB_QP_TX_RESERVE,
+				   AIROHA_USB_ANA_TX_RESERVE_8 |
+				   AIROHA_USB_ANA_TX_VLMON_EN));
+
+	if (submode == PHY_INTERFACE_MODE_2500BASEX)
+		an7583_usb_phy_eth_init_hsgmii(priv);
+	else
+		an7583_usb_phy_eth_init_sgmii(priv);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_5,
+			  AIROHA_USB_PMA_LCPLL_NCPO_CHG);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_5,
+			AIROHA_USB_PMA_LCPLL_NCPO_CHG);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_PWCTL_SETTING_2,
+			   AIROHA_USB_PMA_NCPO_ANA_MSB,
+			   FIELD_PREP(AIROHA_USB_PMA_NCPO_ANA_MSB, 0x1));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			AIROHA_USB_ANA_RXAFE_RESERVE,
+			AIROHA_USB_ANA_CDR_PD_10B_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_PON_RXFEDIG_CTRL_10,
+			   AIROHA_USB_PMA_QP_EQ_PIEYE_INI,
+			   FIELD_PREP(AIROHA_USB_PMA_QP_EQ_PIEYE_INI, 0x0));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_PON_RXFEDIG_CTRL_8,
+			   AIROHA_USB_PMA_QP_EQ_EYE_MASK,
+			   FIELD_PREP(AIROHA_USB_PMA_QP_EQ_EYE_MASK, 0x2aa));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_6,
+			   AIROHA_USB_PMA_FREDET_GOLDEN_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_GOLDEN_CYCLE, 0x64));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_7,
+			   AIROHA_USB_PMA_FREDET_TOLERATE_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_TOLERATE_CYCLE, 0x2710));
+
+	/* PLL auto init */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_0,
+			  AIROHA_USB_PMA_AUTO_INIT);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_0,
+			AIROHA_USB_PMA_AUTO_INIT);
+
+	usleep_range(100, 200);
+
+	return 0;
+}
+
+static void an7583_usb_phy_tx_pll_enable(struct an7583_usb_phy_priv *priv)
+{
+	/* PLL Reset to default */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			  AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL,
+			  AIROHA_USB_ANA_PLL_MON_LDO_SEL |
+			  AIROHA_USB_ANA_PLL_MONVC_EN);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			  AIROHA_USB_PMA_INTF_CTRL_7,
+			  AIROHA_USB_PMA_PLL_EN_SEL |
+			  AIROHA_USB_PMA_PLL_EN_FORCE);
+
+	/* PLL Auto Mode (For PMA) */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_PLL_CK_CTRL_1,
+			AIROHA_USB_PMA_PLL_FORCE_UNSTABLE);
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_PLL_CK_CTRL_1,
+			AIROHA_USB_PMA_PLL_FORCE_STABLE);
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			  AIROHA_USB_PMA_PLL_CK_CTRL_1,
+			  AIROHA_USB_PMA_PLL_FORCE_UNSTABLE);
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			  AIROHA_USB_PMA_PLL_CK_CTRL_1,
+			  AIROHA_USB_PMA_PLL_FORCE_STABLE);
+
+	/* TX Auto Mode */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_6,
+			AIROHA_USB_PMA_TX_DATA_EN_FORCE);
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_6,
+			  AIROHA_USB_PMA_TX_DATA_EN_SEL);
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_6,
+			  AIROHA_USB_PMA_TX_DATA_EN_FORCE);
+}
+
+static void an7583_usb_phy_kband_calibrate(struct an7583_usb_phy_priv *priv)
+{
+	/* PLL Disable */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_INTF_CTRL_8,
+			   AIROHA_USB_PMA_XTAL_EXT_EN_SEL |
+			   AIROHA_USB_PMA_XTAL_EXT_EN_FORCE,
+			   AIROHA_USB_PMA_XTAL_EXT_EN_SEL |
+			   FIELD_PREP(AIROHA_USB_PMA_XTAL_EXT_EN_FORCE, 0x3));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_INTF_CTRL_7,
+			   AIROHA_USB_PMA_PLL_EN_SEL |
+			   AIROHA_USB_PMA_PLL_EN_FORCE,
+			   AIROHA_USB_PMA_PLL_EN_SEL);
+
+	/* PLL Config for CPR */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_PLL_CTRL_4,
+			AIROHA_USB_PMA_PLL_ICOLP_EN_INTF);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_SSUSB_BGR_EN,
+			   AIROHA_USB_ANA_BIAS_V2V_CAL,
+			   FIELD_PREP(AIROHA_USB_ANA_BIAS_V2V_CAL, 0x0));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL,
+			   AIROHA_USB_ANA_PLL_OSCAL_ENB |
+			   AIROHA_USB_ANA_PLL_LDOLPF_VSEL,
+			   FIELD_PREP(AIROHA_USB_ANA_PLL_LDOLPF_VSEL, 0x3));
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			  AIROHA_USB_PMA_PLL_CTRL_2,
+			  AIROHA_USB_PMA_PLL_RICO_SEL_INTF |
+			  AIROHA_USB_PMA_PLL_ICOIQ_EN_INTF);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL,
+			   AIROHA_USB_ANA_PLL_MON_LDO_SEL |
+			   AIROHA_USB_ANA_PLL_MONVC_EN,
+			   FIELD_PREP(AIROHA_USB_ANA_PLL_MON_LDO_SEL, 0x3) |
+			   AIROHA_USB_ANA_PLL_MONVC_EN);
+
+	/* PLL Enable */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_INTF_CTRL_7,
+			AIROHA_USB_PMA_PLL_EN_SEL |
+			AIROHA_USB_PMA_PLL_EN_FORCE);
+}
+
+static int an7583_usb_phy_u3_init(struct phy *phy)
+{
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+
+	/* Digital CLK trigger reverse */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PON_RXFEDIG_CTRL_0,
+			  AIROHA_USB_PMA_EQ_RX500M_CK_SEL);
+
+	/* RX USB PCIE enable */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_36,
+			AIROHA_USB_PMA_PCIE_USB_SYSTEM);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_SYS_CTRL_0,
+			  AIROHA_USB_PMA_ROC_CK_EN);
+
+	/* 50MHz XTAL */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_SSUSB_BGR_EN,
+			   AIROHA_USB_ANA_SSUSB_BG_DIV |
+			   AIROHA_USB_ANA_SSUSB_CHPEN,
+			   FIELD_PREP(AIROHA_USB_ANA_SSUSB_BG_DIV, 0x1) |
+			   AIROHA_USB_ANA_SSUSB_CHPEN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL,
+			   AIROHA_USB_ANA_PLL_PREDIV,
+			   FIELD_PREP(AIROHA_USB_ANA_PLL_PREDIV, 0x1));
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_4,
+			  AIROHA_USB_PMA_PLL_ICOLP_EN_INTF);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_CK_RST_CTRL_7,
+			  AIROHA_USB_DIG_MULTI_USB2P5_EN |
+			  AIROHA_USB_DIG_MULTI_USB5_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_CK_RST_CTRL_7,
+			AIROHA_USB_DIG_MULTI_USB2P5_EN |
+			AIROHA_USB_DIG_MULTI_USB5_EN |
+			AIROHA_USB_DIG_MULTI_PHY_USB_EN);
+
+	/* PLL */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_2,
+			   AIROHA_USB_PMA_PLL_PHY_CK_EN_INTF |
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   AIROHA_USB_PMA_PLL_KBAND_PREDIV_INTF |
+			   AIROHA_USB_PMA_PLL_IR_INTF |
+			   AIROHA_USB_PMA_PLL_ICOIQ_EN_INTF |
+			   AIROHA_USB_PMA_PLL_FBKSEL_INTF |
+			   AIROHA_USB_PMA_PLL_BPB_INTF |
+			   AIROHA_USB_PMA_PLL_BPA_INTF |
+			   AIROHA_USB_PMA_PLL_BC_INTF,
+			   AIROHA_USB_PMA_PLL_PHY_CK_EN_INTF |
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_KBAND_PREDIV_INTF, 0x0) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_IR_INTF, 0x4) |
+			   AIROHA_USB_PMA_PLL_ICOIQ_EN_INTF |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_FBKSEL_INTF, 0x0) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BPB_INTF, 0x1) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BPA_INTF, 0x5) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BC_INTF, 0x3));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_4,
+			   AIROHA_USB_PMA_PLL_SDM_HREN_INTF,
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_SDM_HREN_INTF, 0x1));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_2,
+			AIROHA_USB_PMA_PLL_SDM_IFM_INTF);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_3,
+			   AIROHA_USB_PMA_PLL_SSC_PERIOD_INTF |
+			   AIROHA_USB_PMA_PLL_SSC_DELTA_INTF,
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_SSC_PERIOD_INTF, 0x18c) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_SSC_DELTA_INTF, 0x21e));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_1,
+			AIROHA_USB_PMA_PLL_SSC_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_PCW_1,
+			   AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+				      0x48000000));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_PWCTL_SETTING_2,
+			   AIROHA_USB_PMA_NCPO_ANA_MSB,
+			   FIELD_PREP(AIROHA_USB_PMA_NCPO_ANA_MSB, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_2,
+			   AIROHA_USB_PMA_LCPLL_NCPO_VALUE,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_NCPO_VALUE, 0x48000000));
+
+	/* RX 5G */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_LPF_MJV_LIM,
+			   AIROHA_USB_ANA_CDR_LPF_RATIO,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_RATIO, 0x0));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			AIROHA_USB_ANA_RXAFE_RESERVE,
+			AIROHA_USB_ANA_CDR_PD_10B_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_CKREF_DIV1,
+			   AIROHA_USB_ANA_CDR_PR_DAC_BAND,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_DAC_BAND, 0xc));
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			  AIROHA_USB_ANA_CDR_FORCE_IBANDLPF_R_OFF,
+			  AIROHA_USB_ANA_CDR_PHYCK_RSTB);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE_REG,
+			   AIROHA_USB_ANA_CDR_PR_XFICK_EN |
+			   AIROHA_USB_ANA_CDR_PR_KBAND_PCIE_MODE,
+			   AIROHA_USB_ANA_CDR_PR_KBAND_PCIE_MODE);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_CKREF_DIV1,
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_KBAND_DIV, 0x3));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE_REG,
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE, 0x19));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_46,
+			AIROHA_USB_PMA_REBACK_P0_LCK2REF_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_49,
+			   AIROHA_USB_PMA_LFPS_FINISH_TIME,
+			   FIELD_PREP(AIROHA_USB_PMA_LFPS_FINISH_TIME, 0x1f0));
+
+	/* EQ all */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_50,
+			  AIROHA_USB_PMA_P3_TO_P0_DO_EQ_USB |
+			  AIROHA_USB_PMA_P2_TO_P0_DO_EQ_USB |
+			  AIROHA_USB_PMA_P1_TO_P0_DO_EQ_USB);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_46,
+			AIROHA_USB_PMA_PCIE_USB_BYPASS_EQ_P3_TO_P0_EN |
+			AIROHA_USB_PMA_PCIE_USB_BYPASS_EQ_P2_TO_P0_EN |
+			AIROHA_USB_PMA_PCIE_USB_BYPASS_EQ_P1_TO_P0_EN);
+
+	/* FIXME: ask Airoha why reserve7 is at 6c4 NOT 6c0 */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_38,
+			  FIELD_PREP(AIROHA_USB_PMA_RESERVE_3, BIT(7)));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_11,
+			AIROHA_USB_PMA_FORCE_SIGDET_5G);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_36,
+			   AIROHA_USB_PMA_LCK2DATA_DLY_TIME,
+			   FIELD_PREP(AIROHA_USB_PMA_LCK2DATA_DLY_TIME, 0x2));
+
+	/* PI Cal */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_DLY_0,
+			   AIROHA_USB_PMA_RX_PI_CAL_EN_H_DLY,
+			   FIELD_PREP(AIROHA_USB_PMA_RX_PI_CAL_EN_H_DLY, 0x10));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_PLL_SDM_ORD,
+			AIROHA_USB_ANA_PLL_SSC_TRI_EN |
+			AIROHA_USB_ANA_PLL_SSC_PHASE_INI);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_TX_DA_CTRL_3,
+			  AIROHA_USB_PMA_TX_DATA_RATE_SEL);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_RXAFE_RESERVE,
+			  AIROHA_USB_ANA_CDR_PD_EDGE_DIS);
+
+	/* Common Setting */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_CK_RST_CTRL_3,
+			AIROHA_USB_DIG_NS_CK_DIV_SEL |
+			AIROHA_USB_DIG_US_CK_DIV_SEL);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_TX_DA_CTRL_0,
+			   AIROHA_USB_PMA_RXDET_RD_WAIT_TIMER |
+			   AIROHA_USB_PMA_RXDET_EN_WINDOW,
+			   FIELD_PREP(AIROHA_USB_PMA_RXDET_RD_WAIT_TIMER, 0x4) |
+			   FIELD_PREP(AIROHA_USB_PMA_RXDET_EN_WINDOW, 0xa));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_RXLBTX_EN,
+			   AIROHA_USB_ANA_TX_DMEDGEGEN_EN |
+			   AIROHA_USB_ANA_TX_RXDET_METHOD,
+			   AIROHA_USB_ANA_TX_DMEDGEGEN_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CK_CTRL_2,
+			AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_OFF_EN |
+			AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_ON_EN |
+			AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_EN);
+
+	/* RX Speed Up */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_5,
+			   AIROHA_USB_PMA_FREDET_CHK_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_CHK_CYCLE, 0x28));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_6,
+			   AIROHA_USB_PMA_FREDET_GOLDEN_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_GOLDEN_CYCLE, 0x64));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_7,
+			   AIROHA_USB_PMA_FREDET_TOLERATE_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_TOLERATE_CYCLE, 0x2710));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_2,
+			   AIROHA_USB_PMA_RX_EQ_EN_H_DLY,
+			   FIELD_PREP(AIROHA_USB_PMA_RX_EQ_EN_H_DLY, 0x9c4));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_45,
+			   AIROHA_USB_PMA_EQ_EN_DLY,
+			   FIELD_PREP(AIROHA_USB_PMA_EQ_EN_DLY, 0x9c4));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_50,
+			   AIROHA_USB_PMA_EQ_EN_DLY_SHORT |
+			   AIROHA_USB_PMA_RX_EQ_EN_H_DLY_SHORT,
+			   FIELD_PREP(AIROHA_USB_PMA_EQ_EN_DLY_SHORT, 0x9c4) |
+			   FIELD_PREP(AIROHA_USB_PMA_RX_EQ_EN_H_DLY_SHORT, 0x9c4));
+
+	/* TCL avoid LT noice impact */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_QP_TX_MODE_16B_EN,
+			AIROHA_USB_ANA_TX_RESERVE_8);
+
+	/* PLL auto init */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_0,
+			AIROHA_USB_PMA_AUTO_INIT);
+
+	usleep_range(100, 300);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CK_CTRL_2,
+			  AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_EN);
+
+	if (!an7583_usb_phy_u3_kband_is_calibrated(priv)) {
+		int i;
+
+		/* TX Force Disable */
+		regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+				   AIROHA_USB_PMA_INTF_CTRL_6,
+				   AIROHA_USB_PMA_TX_DATA_EN_SEL |
+				   AIROHA_USB_PMA_TX_DATA_EN_FORCE,
+				   AIROHA_USB_PMA_TX_DATA_EN_SEL);
+
+		/* PLL Force Unstable */
+		regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+				AIROHA_USB_PMA_PLL_CK_CTRL_1,
+				AIROHA_USB_PMA_PLL_FORCE_UNSTABLE);
+
+		for (i = 0; i < AIROHA_USB_PHY_U3_MAX_CALIB_TRY; i++) {
+			an7583_usb_phy_kband_calibrate(priv);
+
+			/* Exit as soon as we manage to calibrate */
+			if (an7583_usb_phy_u3_kband_is_calibrated(priv))
+				break;
+		}
+	}
+
+	an7583_usb_phy_tx_pll_enable(priv);
+
+	return !an7583_usb_phy_u3_kband_is_calibrated(priv) ? -EINVAL : 0;
+}
+
+static int an7583_usb_phy_pcie_init(struct phy *phy)
+{
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+	int i;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+
+	/* TX Force Disable */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_INTF_CTRL_6,
+			   AIROHA_USB_PMA_TX_DATA_EN_SEL |
+			   AIROHA_USB_PMA_TX_DATA_EN_FORCE,
+			   AIROHA_USB_PMA_TX_DATA_EN_SEL);
+
+	/* PLL Force Unstable */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_PLL_CK_CTRL_1,
+			AIROHA_USB_PMA_PLL_FORCE_UNSTABLE);
+
+	/* PLL Disable */
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_0,
+			  AIROHA_USB_PMA_AUTO_INIT);
+
+	usleep_range(1000, 1500);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_0,
+			AIROHA_USB_PMA_AUTO_INIT);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_INTF_CTRL_7,
+			   AIROHA_USB_PMA_PLL_EN_SEL |
+			   AIROHA_USB_PMA_PLL_EN_FORCE,
+			   AIROHA_USB_PMA_PLL_EN_SEL);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_36,
+			AIROHA_USB_PMA_PCIE_USB_SYSTEM);
+
+	/* 50MHz XTAL */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_SSUSB_BGR_EN,
+			   AIROHA_USB_ANA_SSUSB_BG_DIV,
+			   FIELD_PREP(AIROHA_USB_ANA_SSUSB_BG_DIV, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_PLL_IPLL_DIG_PWR_SEL,
+			   AIROHA_USB_ANA_PLL_PREDIV,
+			   FIELD_PREP(AIROHA_USB_ANA_PLL_PREDIV, 0x1));
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_4,
+			  AIROHA_USB_PMA_PLL_ICOLP_EN_INTF);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_CK_RST_CTRL_7,
+			  AIROHA_USB_DIG_MULTI_USB2P5_EN |
+			  AIROHA_USB_DIG_MULTI_USB5_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_CK_RST_CTRL_7,
+			AIROHA_USB_DIG_MULTI_USB2P5_EN |
+			AIROHA_USB_DIG_MULTI_USB5_EN |
+			AIROHA_USB_DIG_MULTI_PHY_USB_EN);
+
+	/* PLL RG */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_2,
+			   AIROHA_USB_PMA_PLL_PHY_CK_EN_INTF |
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   AIROHA_USB_PMA_PLL_KBAND_PREDIV_INTF |
+			   AIROHA_USB_PMA_PLL_IR_INTF |
+			   AIROHA_USB_PMA_PLL_ICOIQ_EN_INTF |
+			   AIROHA_USB_PMA_PLL_FBKSEL_INTF |
+			   AIROHA_USB_PMA_PLL_BPB_INTF |
+			   AIROHA_USB_PMA_PLL_BPA_INTF |
+			   AIROHA_USB_PMA_PLL_BC_INTF,
+			   AIROHA_USB_PMA_PLL_PCK_SEL_INTF |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_KBAND_PREDIV_INTF, 0x0) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_IR_INTF, 0x4) |
+			   AIROHA_USB_PMA_PLL_ICOIQ_EN_INTF |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_FBKSEL_INTF, 0x0) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BPB_INTF, 0x1) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BPA_INTF, 0x5) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_BC_INTF, 0x3));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_4,
+			   AIROHA_USB_PMA_PLL_SDM_HREN_INTF,
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_SDM_HREN_INTF, 0x1));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_2,
+			AIROHA_USB_PMA_PLL_SDM_IFM_INTF);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_3,
+			   AIROHA_USB_PMA_PLL_SSC_PERIOD_INTF |
+			   AIROHA_USB_PMA_PLL_SSC_DELTA_INTF,
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_SSC_PERIOD_INTF, 0x91c) |
+			   FIELD_PREP(AIROHA_USB_PMA_PLL_SSC_DELTA_INTF, 0x1fd));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_1,
+			AIROHA_USB_PMA_PLL_SSC_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_PCW_1,
+			   AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
+				      0x48000000));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_PWCTL_SETTING_2,
+			   AIROHA_USB_PMA_NCPO_ANA_MSB,
+			   FIELD_PREP(AIROHA_USB_PMA_NCPO_ANA_MSB, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			   AIROHA_USB_PMA_SS_LCPLL_TDC_FLT_2,
+			   AIROHA_USB_PMA_LCPLL_NCPO_VALUE,
+			   FIELD_PREP(AIROHA_USB_PMA_LCPLL_NCPO_VALUE, 0x48000000));
+
+	/* RX RG */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_LPF_MJV_LIM,
+			   AIROHA_USB_ANA_CDR_LPF_RATIO,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_LPF_RATIO, 0x1));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			AIROHA_USB_ANA_RXAFE_RESERVE,
+			AIROHA_USB_ANA_CDR_PD_10B_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_CKREF_DIV1,
+			   AIROHA_USB_ANA_CDR_PR_DAC_BAND,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_DAC_BAND, 0xc));
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			  AIROHA_USB_ANA_CDR_FORCE_IBANDLPF_R_OFF,
+			  AIROHA_USB_ANA_CDR_PHYCK_RSTB);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE_REG,
+			   AIROHA_USB_ANA_CDR_PR_XFICK_EN |
+			   AIROHA_USB_ANA_CDR_PR_KBAND_PCIE_MODE,
+			   AIROHA_USB_ANA_CDR_PR_KBAND_PCIE_MODE);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_CKREF_DIV1,
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_KBAND_DIV, 0x3));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA],
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE_REG,
+			   AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE,
+			   FIELD_PREP(AIROHA_USB_ANA_CDR_PR_KBAND_DIV_PCIE, 0x19));
+
+	/* Init L0/L0S U0/U1 */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_46,
+			AIROHA_USB_PMA_REBACK_P0_LCK2REF_EN |
+			AIROHA_USB_PMA_PCIE_USB_BYPASS_EQ_P1_TO_P0_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_11,
+			AIROHA_USB_PMA_FORCE_SIGDET_5G);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_36,
+			   AIROHA_USB_PMA_LCK2DATA_DLY_TIME,
+			   FIELD_PREP(AIROHA_USB_PMA_LCK2DATA_DLY_TIME, 0x2));
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_RXAFE_RESERVE,
+			  AIROHA_USB_ANA_CDR_PD_EDGE_DIS);
+
+	/* PI Calibration */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_DLY_0,
+			   AIROHA_USB_PMA_RX_PI_CAL_EN_H_DLY,
+			   FIELD_PREP(AIROHA_USB_PMA_RX_PI_CAL_EN_H_DLY, 0x10));
+
+	/* CRS detect and CLK TRX Control */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_10,
+			AIROHA_USB_PMA_CRSDET_RSTB);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_PLL_SDM_ORD,
+			AIROHA_USB_ANA_PLL_SSC_TRI_EN |
+			AIROHA_USB_ANA_PLL_SSC_PHASE_INI);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CK_CTRL_0,
+			   AIROHA_USB_PMA_PCIE_CLKTX_EN_INTF |
+			   AIROHA_USB_PMA_PCIE_CLKRX_EN_INTF,
+			   AIROHA_USB_PMA_PCIE_CLKTX_EN_INTF);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_CLKDRV_IMPSEL,
+			   AIROHA_USB_ANA_PCIE_CLKDRV_AMP |
+			   AIROHA_USB_ANA_PCIE_CLKDRV_FORCEIN |
+			   AIROHA_USB_ANA_PCIE_CLKDRV_HZ |
+			   AIROHA_USB_ANA_PCIE_CLKDRV_RP |
+			   AIROHA_USB_ANA_PCIE_CLKDRV_IMPSEL,
+			   FIELD_PREP(AIROHA_USB_ANA_PCIE_CLKDRV_AMP, 0x4) |
+			   FIELD_PREP(AIROHA_USB_ANA_PCIE_CLKDRV_FORCEIN, 0x1) |
+			   FIELD_PREP(AIROHA_USB_ANA_PCIE_CLKDRV_RP, 0xc) |
+			   FIELD_PREP(AIROHA_USB_ANA_PCIE_CLKDRV_IMPSEL, 0x12));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_TX_DA_CTRL_3,
+			   AIROHA_USB_PMA_TX_DATA_RATE_SEL,
+			   FIELD_PREP(AIROHA_USB_PMA_TX_DATA_RATE_SEL, 0x1));
+
+	/* Common Setting */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_DIG], AIROHA_USB_DIG_CK_RST_CTRL_3,
+			AIROHA_USB_DIG_NS_CK_DIV_SEL |
+			AIROHA_USB_DIG_US_CK_DIV_SEL);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_TX_DA_CTRL_0,
+			   AIROHA_USB_PMA_RXDET_RD_WAIT_TIMER |
+			   AIROHA_USB_PMA_RXDET_EN_WINDOW,
+			   FIELD_PREP(AIROHA_USB_PMA_RXDET_RD_WAIT_TIMER, 0x4) |
+			   FIELD_PREP(AIROHA_USB_PMA_RXDET_EN_WINDOW, 0xa));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_RXLBTX_EN,
+			   AIROHA_USB_ANA_TX_DMEDGEGEN_EN |
+			   AIROHA_USB_ANA_TX_RXDET_METHOD,
+			   AIROHA_USB_ANA_TX_DMEDGEGEN_EN);
+
+	/* PLL auto ON/OFF at L2/U3 state */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CK_CTRL_2,
+			AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_OFF_EN |
+			AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_ON_EN |
+			AIROHA_USB_PMA_PCIE_MODE_PLL_AUTO_EN);
+
+	/* RX speed up */
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_5,
+			   AIROHA_USB_PMA_FREDET_CHK_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_CHK_CYCLE, 0x28));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_6,
+			   AIROHA_USB_PMA_FREDET_GOLDEN_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_GOLDEN_CYCLE, 0x64));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_7,
+			   AIROHA_USB_PMA_FREDET_TOLERATE_CYCLE,
+			   FIELD_PREP(AIROHA_USB_PMA_FREDET_TOLERATE_CYCLE, 0x2710));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_2,
+			   AIROHA_USB_PMA_RX_EQ_EN_H_DLY,
+			   FIELD_PREP(AIROHA_USB_PMA_RX_EQ_EN_H_DLY, 0x9c4));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_45,
+			   AIROHA_USB_PMA_EQ_EN_DLY,
+			   FIELD_PREP(AIROHA_USB_PMA_EQ_EN_DLY, 0x9c4));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_RX_CTRL_50,
+			   AIROHA_USB_PMA_EQ_EN_DLY_SHORT |
+			   AIROHA_USB_PMA_RX_EQ_EN_H_DLY_SHORT,
+			   FIELD_PREP(AIROHA_USB_PMA_EQ_EN_DLY_SHORT, 0x9c4) |
+			   FIELD_PREP(AIROHA_USB_PMA_RX_EQ_EN_H_DLY_SHORT, 0x9c4));
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_QP_TX_MODE_16B_EN,
+			AIROHA_USB_ANA_TX_RESERVE_8);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PON_RXFEDIG_CTRL_0,
+			  AIROHA_USB_PMA_EQ_RX500M_CK_SEL);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_PLL_CTRL_0,
+			AIROHA_USB_PMA_AUTO_INIT);
+
+	/* Select PLL_EN to Force mode */
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA],
+			AIROHA_USB_PMA_INTF_CTRL_7,
+			AIROHA_USB_PMA_PLL_EN_SEL |
+			AIROHA_USB_PMA_PLL_EN_FORCE);
+
+	/* Try to calibrate KBand up to AIROHA_USB_PHY_U3_MAX_CALIB_TRY times */
+	for (i = 0; i < AIROHA_USB_PHY_U3_MAX_CALIB_TRY; i++) {
+		/* Check if KBand is calibrated */
+		if (an7583_usb_phy_u3_kband_is_calibrated(priv))
+			break;
+
+		/* Trigger KBand calibration */
+		an7583_usb_phy_kband_calibrate(priv);
+	}
+
+	an7583_usb_phy_tx_pll_enable(priv);
+
+	return !an7583_usb_phy_u3_kband_is_calibrated(priv) ? -EINVAL : 0;
+}
+
+static int an7583_usb_phy_init(struct phy *phy)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+
+	switch (instance->type) {
+	case PHY_TYPE_USB2:
+		an7583_usb_phy_u2_init(phy);
+		break;
+	case PHY_TYPE_USB3:
+		if (phy_get_mode(phy) == PHY_MODE_ETHERNET)
+			return 0;
+
+		an7583_usb_phy_u3_init(phy);
+		break;
+	case PHY_TYPE_PCIE:
+		if (phy_get_mode(phy) == PHY_MODE_ETHERNET)
+			return 0;
+
+		an7583_usb_phy_pcie_init(phy);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int an7583_usb_phy_exit(struct phy *phy)
+{
+	return 0;
+}
+
+static int an7583_usb_phy_u2_power_on(struct phy *phy)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+	u32 offset;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+	offset = instance->offset;
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_USBPHYACR6 + offset,
+			  AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_USBPHYACR2 + offset,
+			AIROHA_USB_PHY_SIFSLV_MAC_BANDGAP_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_U2PHYACR3 + offset,
+			   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE,
+			   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE_TOGGLE);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_U2PHYDTM0 + offset,
+			  AIROHA_USB_PHY_FORCE_XCVRSEL |
+			  AIROHA_USB_PHY_XCVRSEL);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_USBPHYACR6 + offset,
+			   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL,
+			   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL_NO_ENPLL_FS_BIAS_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_USBPHYACR5 + offset,
+			AIROHA_USB_PHY_USB20_DISC_FIT_EN);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_U2PHYDTM0 + offset,
+			  AIROHA_USB_PHY_FORCE_SUSPENDDM);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_U2PHYACR3 + offset,
+			  AIROHA_USB_PHY_USB20_USB11_TMODE_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_U2PHYACR3 + offset,
+			AIROHA_USB_PHY_USB20_TMODE_FS_LS_TX_EN);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_U2PHYDTM0 + offset,
+			  AIROHA_USB_PHY_FORCE_TERMSEL |
+			  AIROHA_USB_PHY_TERMSEL);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_U2PHYACR3 + offset,
+			  AIROHA_USB_PHY_USB20_PUPD_BIST_EN);
+
+	return 0;
+}
+
+static int an7583_usb_phy_u3_power_on(struct phy *phy)
+{
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_TDC_FT_CK_EN,
+			AIROHA_USB_ANA_VUSB10_ON);
+
+	usleep_range(1000, 1500);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY], AIROHA_USB_PHY_GPIO_CTLD,
+			  AIROHA_USB_PHY_SSUSB_IP_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY], AIROHA_USB_PHY_GPIO_CTLD,
+			  AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_5,
+			  AIROHA_USB_PMA_RX_HZ_FORCE);
+
+	usleep_range(1000, 1500);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_5,
+			  AIROHA_USB_PMA_RX_HZ_SEL);
+
+	return 0;
+}
+
+static int an7583_usb_phy_power_on(struct phy *phy)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+
+	switch (instance->type) {
+	case PHY_TYPE_USB2:
+		return an7583_usb_phy_u2_power_on(phy);
+	case PHY_TYPE_USB3:
+		return an7583_usb_phy_u3_power_on(phy);
+	case PHY_TYPE_PCIE:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int an7583_usb_phy_u2_power_off(struct phy *phy)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+	u32 offset;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+	offset = instance->offset;
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_U2PHYACR3 + offset,
+			AIROHA_USB_PHY_USB20_PUPD_BIST_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_U2PHYDTM0 + offset,
+			AIROHA_USB_PHY_FORCE_TERMSEL |
+			AIROHA_USB_PHY_TERMSEL);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_U2PHYACR3 + offset,
+			  AIROHA_USB_PHY_USB20_TMODE_FS_LS_TX_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_U2PHYACR3 + offset,
+			AIROHA_USB_PHY_USB20_USB11_TMODE_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_U2PHYDTM0 + offset,
+			AIROHA_USB_PHY_FORCE_SUSPENDDM);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_USBPHYACR5 + offset,
+			  AIROHA_USB_PHY_USB20_DISC_FIT_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_USBPHYACR6 + offset,
+			   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL,
+			   AIROHA_USB_PHY_USB20_HSRX_BIAS_EN_SEL_USB20_HSRX_TMODE_EN);
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_U2PHYDTM0 + offset,
+			   AIROHA_USB_PHY_FORCE_XCVRSEL |
+			   AIROHA_USB_PHY_XCVRSEL,
+			   AIROHA_USB_PHY_FORCE_XCVRSEL |
+			   FIELD_PREP(AIROHA_USB_PHY_XCVRSEL, 0x1));
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			   AIROHA_USB_PHY_U2PHYACR3 + offset,
+			   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE,
+			   AIROHA_USB_PHY_USB20_HSTX_I_EN_MODE_FORCE_DISABLE);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			  AIROHA_USB_PHY_USBPHYACR2 + offset,
+			  AIROHA_USB_PHY_SIFSLV_MAC_BANDGAP_EN);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY],
+			AIROHA_USB_PHY_USBPHYACR6 + offset,
+			AIROHA_USB_PHY_USB20_BC11_SW_EN);
+
+	return 0;
+}
+
+static int an7583_usb_phy_u3_power_off(struct phy *phy)
+{
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev;
+
+	dev = phy->dev.parent;
+	priv = dev_get_drvdata(dev);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY], AIROHA_USB_PHY_GPIO_CTLD,
+			AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PHY], AIROHA_USB_PHY_GPIO_CTLD,
+			AIROHA_USB_PHY_SSUSB_IP_SW_RST);
+
+	usleep_range(1000, 1500);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_5,
+			AIROHA_USB_PMA_RX_HZ_FORCE);
+
+	usleep_range(1000, 1500);
+
+	regmap_set_bits(priv->regs[AIROHA_USB_PHY_PMA], AIROHA_USB_PMA_INTF_CTRL_5,
+			AIROHA_USB_PMA_RX_HZ_SEL);
+
+	usleep_range(1000, 1500);
+
+	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA], AIROHA_USB_ANA_TDC_FT_CK_EN,
+			  AIROHA_USB_ANA_VUSB10_ON);
+
+	return 0;
+}
+
+static int an7583_usb_phy_power_off(struct phy *phy)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+
+	switch (instance->type) {
+	case PHY_TYPE_USB2:
+		return an7583_usb_phy_u2_power_off(phy);
+	case PHY_TYPE_USB3:
+		return an7583_usb_phy_u3_power_off(phy);
+	case PHY_TYPE_PCIE:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int an7583_usb_phy_u2_set_mode(struct phy *phy, enum phy_mode mode)
+{
+	struct an7583_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent);
+	u32 val = 0;
+
+	/*
+	 * 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;
+		fallthrough;
+	case PHY_MODE_USB_HOST:
+		val |= AIROHA_USB_PHY_FORCE_IDDIG;
+		break;
+	case PHY_MODE_USB_OTG:
+		break;
+	default:
+		return 0;
+	}
+
+	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY], AIROHA_USB_PHY_U2PHYDTM1,
+			   AIROHA_USB_PHY_FORCE_IDDIG |
+			   AIROHA_USB_PHY_IDDIG, val);
+
+	return 0;
+}
+
+static int an7583_usb_phy_u3_set_mode(struct phy *phy, enum phy_mode mode,
+				      int submode)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+	int ret;
+
+	switch (mode) {
+	case PHY_MODE_ETHERNET:
+		if (submode != PHY_INTERFACE_MODE_SGMII &&
+		    submode != PHY_INTERFACE_MODE_1000BASEX &&
+		    submode != PHY_INTERFACE_MODE_2500BASEX)
+			return -EOPNOTSUPP;
+	case PHY_MODE_USB_DEVICE_SS:
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	ret = phy_set_mode_ext(instance->serdes_phy, mode, submode);
+	if (ret)
+		return ret;
+
+	if (mode == PHY_MODE_ETHERNET)
+		an7583_usb_phy_set_mode_eth(phy, submode);
+
+	return 0;
+}
+
+static int an7583_usb_phy_pcie_set_mode(struct phy *phy, enum phy_mode mode,
+					int submode)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+	int ret;
+
+	switch (mode) {
+	case PHY_MODE_ETHERNET:
+		if (submode != PHY_INTERFACE_MODE_SGMII &&
+		    submode != PHY_INTERFACE_MODE_1000BASEX &&
+		    submode != PHY_INTERFACE_MODE_2500BASEX)
+			return -EOPNOTSUPP;
+	case PHY_MODE_PCIE:
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	ret = phy_set_mode_ext(instance->serdes_phy, mode, submode);
+	if (ret)
+		return ret;
+
+	if (mode == PHY_MODE_ETHERNET)
+		an7583_usb_phy_set_mode_eth(phy, submode);
+
+	return 0;
+}
+
+static int an7583_usb_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
+{
+	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
+
+	switch (instance->type) {
+	case PHY_TYPE_USB2:
+		return an7583_usb_phy_u2_set_mode(phy, mode);
+	case PHY_TYPE_USB3:
+		return an7583_usb_phy_u3_set_mode(phy, mode, submode);
+	case PHY_TYPE_PCIE:
+		return an7583_usb_phy_pcie_set_mode(phy, mode, submode);
+	default:
+		return 0;
+	}
+}
+
+static struct phy *an7583_usb_phy_xlate(struct device *dev,
+					const struct of_phandle_args *args)
+{
+	struct an7583_usb_phy_priv *priv = dev_get_drvdata(dev);
+	const struct an7583_usb_phy_match_data *data;
+	struct device_node *phy_np = args->np;
+	struct phy *phy = NULL;
+	int type, index;
+
+	data = of_device_get_match_data(dev);
+
+	if (args->args_count != 1) {
+		dev_err(dev, "invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (index = 0; index < data->max_instance; index++) {
+		if (!priv->phys[index])
+			continue;
+
+		if (phy_np == priv->phys[index]->dev.of_node) {
+			phy = priv->phys[index];
+			break;
+		}
+	}
+
+	if (!phy) {
+		dev_err(dev, "failed to find appropriate phy\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	type = args->args[0];
+	if (!(type == PHY_TYPE_USB2 || type == PHY_TYPE_USB3 ||
+	      type == PHY_TYPE_PCIE)) {
+		dev_err(dev, "unsupported device type: %d\n", type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return phy;
+}
+
+static const struct phy_ops airoha_phy = {
+	.init		= an7583_usb_phy_init,
+	.exit		= an7583_usb_phy_exit,
+	.power_on	= an7583_usb_phy_power_on,
+	.power_off	= an7583_usb_phy_power_off,
+	.set_mode	= an7583_usb_phy_set_mode,
+	.owner		= THIS_MODULE,
+};
+
+static const char * const an7583_usb_phy_regs_name[AIROHA_USB_PHY_REGS_MAX] = {
+	[AIROHA_USB_PHY_PHY] = "phy",
+	[AIROHA_USB_PHY_ANA] = "ana",
+	[AIROHA_USB_PHY_PMA] = "pma",
+	[AIROHA_USB_PHY_DIG] = "dig",
+};
+
+static const char * const airoha_pcie_phy_regs_name[AIROHA_USB_PHY_REGS_MAX] = {
+	[AIROHA_USB_PHY_ANA] = "ana",
+	[AIROHA_USB_PHY_PMA] = "pma",
+	[AIROHA_USB_PHY_DIG] = "dig",
+};
+
+static int an7583_usb_phy_parse_ports(struct device *dev,
+				      struct an7583_usb_phy_priv *priv,
+				      int index, struct device_node *subnode)
+{
+	const struct an7583_usb_phy_match_data *data;
+	struct an7583_usb_phy_instance  *instance;
+	struct phy *phy;
+	int ret;
+
+	data = of_device_get_match_data(dev);
+
+	if (index > data->max_instance)
+		return -EINVAL;
+
+	if (!of_device_is_available(subnode))
+		return 0;
+
+	instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+	if (!instance)
+		return -ENOMEM;
+
+	instance->serdes_phy = devm_phy_optional_get(dev, NULL);
+	if (IS_ERR(instance->serdes_phy))
+		return dev_err_probe(dev, PTR_ERR(instance->serdes_phy), "error on serdes phy for USB 3.0\n");
+
+	if (!instance->serdes_phy &&
+	    !of_property_present(subnode, "airoha,usb2-monitor-clk-sel"))
+		return dev_err_probe(dev, ret, "monitor clock selection or serdes PHY is mandatory for USB PHY\n");
+
+	if (instance->serdes_phy) {
+		instance->type = PHY_TYPE_USB3;
+	} else {
+		ret = of_property_read_u32(subnode, "airoha,usb2-monitor-clk-sel",
+					   &instance->monclk_sel);
+		if (ret)
+			return dev_err_probe(dev, ret, "failed to parse Monitor clock selection\n");
+
+		ret = of_property_read_u32(subnode, "reg",
+					   &instance->offset);
+		if (ret)
+			return dev_err_probe(dev, ret, "missing reg for U2 PHY\n");
+
+		instance->type = PHY_TYPE_USB2;
+	}
+
+	phy = devm_phy_create(dev, subnode, &airoha_phy);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
+
+	priv->phys[index] = phy;
+	phy_set_drvdata(phy, instance);
+
+	return 0;
+}
+
+static int airoha_pcie_phy_parse_ports(struct device *dev,
+				       struct an7583_usb_phy_priv *priv,
+				       int index, struct device_node *subnode)
+{
+	const struct an7583_usb_phy_match_data *data;
+	struct an7583_usb_phy_instance  *instance;
+	struct phy *phy;
+
+	data = of_device_get_match_data(dev);
+
+	if (index > data->max_instance)
+		return -EINVAL;
+
+	if (!of_device_is_available(subnode))
+		return 0;
+
+	instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+	if (!instance)
+		return -ENOMEM;
+
+	instance->serdes_phy = devm_phy_get(dev, NULL);
+	if (IS_ERR(instance->serdes_phy))
+		return dev_err_probe(dev, PTR_ERR(instance->serdes_phy), "error on serdes phy for PCIe PHY\n");
+
+	instance->type = PHY_TYPE_PCIE;
+
+	phy = devm_phy_create(dev, subnode, &airoha_phy);
+	if (IS_ERR(phy))
+		return dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
+
+	priv->phys[index] = phy;
+	phy_set_drvdata(phy, instance);
+
+	return 0;
+}
+
+static int an7583_usb_phy_probe(struct platform_device *pdev)
+{
+	const struct an7583_usb_phy_match_data *data;
+	struct phy_provider *phy_provider;
+	struct an7583_usb_phy_priv *priv;
+	struct device *dev = &pdev->dev;
+	struct device_node *child_np;
+	int i, ret;
+
+	data = of_device_get_match_data(dev);
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	for (i = 0; i < AIROHA_USB_PHY_REGS_MAX; i++) {
+		struct regmap_config conf = {
+			.reg_bits = 32,
+			.val_bits = 32,
+			.reg_stride = 4,
+		};
+		void *base;
+
+		if (!data->regs_name[i])
+			continue;
+
+		conf.name = data->regs_name[i];
+		base = devm_platform_ioremap_resource_byname(pdev,
+							     data->regs_name[i]);
+		if (IS_ERR(base))
+			return PTR_ERR(base);
+
+		priv->regs[i] = devm_regmap_init_mmio(dev, base, &conf);
+		if (IS_ERR(priv->regs[i]))
+			return PTR_ERR(priv->regs[i]);
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	if (device_is_compatible(dev, "airoha,an7583-usb-phy")) {
+		u8 port;
+
+		port = 0;
+		for_each_child_of_node(dev->of_node, child_np) {
+			ret = data->parse_ports(dev, priv, port, child_np);
+			if (ret) {
+				of_node_put(child_np);
+				return ret;
+			}
+
+			port++;
+		}
+	} else {
+		ret = data->parse_ports(dev, priv, 0, dev->of_node);
+		if (ret)
+			return ret;
+	}
+
+	phy_provider = devm_of_phy_provider_register(dev, an7583_usb_phy_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct an7583_usb_phy_match_data an7583_usb_phy = {
+	.max_instance = AIROHA_USB_PHY_MAX_INSTANCE,
+	.regs_name = an7583_usb_phy_regs_name,
+	.parse_ports = an7583_usb_phy_parse_ports,
+};
+
+static const struct an7583_usb_phy_match_data an7583_pcie_phy = {
+	.max_instance = AIROHA_PCIE_PHY_MAX_INSTANCE,
+	.regs_name = airoha_pcie_phy_regs_name,
+	.parse_ports = airoha_pcie_phy_parse_ports,
+};
+
+static const struct of_device_id airoha_phy_id_table[] = {
+	{ .compatible = "airoha,an7583-usb-phy", .data = &an7583_usb_phy },
+	{ .compatible = "airoha,an7583-pcie-phy", .data = &an7583_pcie_phy },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, airoha_phy_id_table);
+
+static struct platform_driver an7583_usb_driver = {
+	.probe		= an7583_usb_phy_probe,
+	.driver		= {
+		.name	= "airoha-an7583-usb-phy",
+		.of_match_table = airoha_phy_id_table,
+	},
+};
+
+module_platform_driver(an7583_usb_driver);
+
+MODULE_DESCRIPTION("Airoha AN7583 USB PHY driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_LICENSE("GPL");
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/3] dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY
  2026-08-27 13:15 ` [PATCH v3 2/3] dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY Christian Marangi
@ 2026-08-27 13:23   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-27 13:23 UTC (permalink / raw)
  To: Christian Marangi
  Cc: robh, vkoul, linux-phy, olteanv, neil.armstrong, conor+dt,
	devicetree

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Low] The binding title incorrectly refers to 'AN7581' instead of 'AN7583'.
- [Low] The register sizes in the example are off-by-one, incorrectly using the maximum offset instead of the byte count.
- [Low] The binding filename 'airoha,an7583-pcie-gen2-phy.yaml' does not match the compatible string 'airoha,an7583-pcie-phy'.
--

commit a30f9e597cd1c12059c1c3ca3b0550d5e5800f4d
Author: Christian Marangi <ansuelsmth@gmail.com>
Subject: dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY

This commit documents support for the AN7583 Gen2 PCIe PHY, which is used
to make the Gen2 PCIe port work. It adds the required registers to configure
the PCIe PHY and provides a usage example.

> diff --git a/Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml
> new file mode 100644
> index 0000000000000..f31d838871fc1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/airoha,an7583-pcie-gen2-phy.yaml
> @@ -0,0 +1,63 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/airoha,an7583-pcie-gen2-phy.yaml#

[Severity: Low]
Should the filename (and consequently the $id path) match the defined
compatible string airoha,an7583-pcie-phy? The extraneous 'gen2-' in the
filename causes it to diverge from the compatible string, which typically
triggers a schema validation warning when running dt_binding_check.

> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN7581 SoC PCIe Gen2 PHY

[Severity: Low]
Does this title incorrectly refer to AN7581 instead of the intended target
AN7583?

[ ... ]

> +examples:
> +  - |
> +    phy@1fa5f000 {
> +        compatible = "airoha,an7583-pcie-phy";
> +        reg = <0x1fa5f000 0xff>,
> +              <0x1fa5e000 0x3ff>,
> +              <0x1fa5a000 0x8ff>;

[Severity: Low]
Are these register sizes in the example off-by-one? The sizes 0xff, 0x3ff,
and 0x8ff (255, 1023, and 2303 bytes) are not multiples of 4, meaning the
final byte of the last 32-bit register is excluded from the memory region.

A developer copying this example verbatim might create an invalid device
tree that could cause out-of-bounds accesses when the driver reads the final
register.

> +        reg-names = "ana", "pma", "dig";
> +
> +        phys = <&serdes_phy>;
> +
> +        #phy-cells = <0>;
> +    };

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260827131551.26725-1-ansuelsmth@gmail.com?part=2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 1/3] dt-bindings: phy: airoha: Document support for AN7583 USB PHY
  2026-08-27 13:15 ` [PATCH v3 1/3] dt-bindings: phy: airoha: Document support for " Christian Marangi
@ 2026-08-27 13:25   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-27 13:25 UTC (permalink / raw)
  To: Christian Marangi
  Cc: linux-phy, olteanv, vkoul, devicetree, robh, neil.armstrong,
	conor+dt

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Malformed character range in patternProperties regex allows invalid unit addresses.
- [Low] Typo in the binding title and grammatical errors in the description.
--

commit 4a5fe874f5d1686d215561949399a35ae4b5a15b
Author: Christian Marangi <ansuelsmth@gmail.com>

dt-bindings: phy: airoha: Document support for AN7583 USB PHY
    
Adds documentation for the Airoha AN7583 USB PHY for the USB controller.
The binding details support for up to two USB 2.0 ports, optional USB 3.0
modes via Serdes configuration, and monitor clock calibration.

> diff --git a/Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml b/Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml
> new file mode 100644
> index 0000000000000..7ec655253a8ef
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/airoha,an7583-usb-phy.yaml
> @@ -0,0 +1,133 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/airoha,an7583-usb-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Airoha AN7581 SoC USB PHY

[Severity: Low]
This isn't a bug, but is the title targeting the correct SoC variant? The
compatible string and filename target AN7583, but the title mistakenly
says AN7581.

> +
> +maintainers:
> +  - Christian Marangi <ansuelsmth@gmail.com>
> +
> +description: >
> +  The Airoha AN7583 SoC USB PHY describes the USB PHY for the USB controller..

[Severity: Low]
This isn't a bug, but there is a typo here with the double period at the
end of the sentence.

[ ... ]
> +patternProperties:
> +  '^usb2-phy@[0-9-a-f]+$':

[Severity: Medium]
Does this regex correctly restrict unit addresses?

The regex [0-9-a-f] contains a hyphen after a completed range (0-9), causing
the hyphen to be treated as a literal character rather than part of a valid
hex range. This incorrectly validates malformed device tree node names
containing hyphens in the unit address (e.g., usb2-phy@0-a).

Should this pattern be updated to [0-9a-f]+ to enforce proper hex unit
addresses?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260827131551.26725-1-ansuelsmth@gmail.com?part=1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 3/3] phy: airoha: Add support for Airoha AN7583 USB PHY
  2026-08-27 13:15 ` [PATCH v3 3/3] phy: airoha: Add support for Airoha AN7583 USB PHY Christian Marangi
@ 2026-08-27 13:26   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-27 13:26 UTC (permalink / raw)
  To: Christian Marangi
  Cc: vkoul, olteanv, conor+dt, linux-phy, robh, neil.armstrong,
	devicetree

Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [High] Off-by-one error in array bounds check allows out-of-bounds array write.
- [High] Incorrect device node is used to fetch the per-port serdes PHY.
- [High] Missing per-port register offset in `an7583_usb_phy_u2_set_mode` causes cross-instance state corruption.
- [Medium] Uninitialized variable `ret` is used as an error return code in `an7583_usb_phy_parse_ports`.
- [Medium] `fm_out` may be evaluated uninitialized if the regmap polling macro fails.
- [Medium] The PHY initialization error codes for USB3 and PCIe are silently ignored.
- [Medium] Nested acquisition of same-class PHY mutex triggers lockdep warning.
- [Medium] Excessive busy-waiting using mdelay() in PHY initialization loops.
- [Low] Missing `fallthrough;` annotation in switch statements triggers implicit fallthrough warnings.
--

commit e08eb2476fb864bd66e0895961c95bf0fbc89352
Author: Christian Marangi <ansuelsmth@gmail.com>

phy: airoha: Add support for Airoha AN7583 USB PHY

Adds support for USB PHY on Airoha AN7583 SoC, supporting two U2 ports and
one U3 port via a single USB PHY instance, plus a second instance for
PCIe Gen2.

> diff --git a/drivers/phy/airoha/phy-an7583-usb.c b/drivers/phy/airoha/phy-an7583-usb.c
> new file mode 100644
> index 0000000000000..33915c9f4a0de
> --- /dev/null
> +++ b/drivers/phy/airoha/phy-an7583-usb.c
> @@ -280,18 +280,18 @@ static int an7583_usb_phy_u2_slew_rate_calibration(struct phy *phy)
>  	/* Timeout can happen and we will apply workaround at the end */
>  	regmap_read_poll_timeout(priv->regs[AIROHA_USB_PHY_PHY],
>  				 AIROHA_USB_PHY_FMMONR0 + offset,
>  				 fm_out, fm_out, AIROHA_USB_PHY_FREQDET_SLEEP,
>  				 AIROHA_USB_PHY_FREQDET_TIMEOUT);
>  
>  	/* Disable Frequency meter */
>  	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
>  			  AIROHA_USB_PHY_FMCR0 + offset,
>  			  AIROHA_USB_PHY_FREQDET_EN);
>  
>  	/* Disable Free run clock */
>  	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
>  			  AIROHA_USB_PHY_FMMONR1 + offset,
>  			  AIROHA_USB_PHY_FRCK_EN);
>  
>  	/* Disable HS TX SR calibration */
>  	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_PHY],
>  			  AIROHA_USB_PHY_USBPHYACR5 + offset,
>  			  AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN);
>  
>  	usleep_range(1000, 1500);
>  
>  	/* Frequency was not detected, use default SR calibration value */
>  	if (!fm_out) {

[Severity: Medium]
If the regmap read returns an error here in
an7583_usb_phy_u2_slew_rate_calibration(), regmap_read_poll_timeout()
will terminate early without initializing fm_out.

Will this cause the subsequent check if (!fm_out) to evaluate garbage data?

[ ... ]

> @@ -340,11 +340,11 @@ static bool an7583_usb_phy_u3_kband_is_calibrated(struct an7583_usb_phy_priv *pr
>  	/* Read KBand */
>  	regmap_clear_bits(priv->regs[AIROHA_USB_PHY_ANA],
>  			  AIROHA_USB_ANA_TDC_FT_CK_EN,
>  			  AIROHA_USB_ANA_PLL_DEBUG_SEL);
>  
>  	mdelay(5);

[Severity: Medium]
Can this delay in an7583_usb_phy_u3_kband_is_calibrated() cause excessive
CPU stalling?

It uses mdelay(5) twice per loop, and is called up to 50 times in
an7583_usb_phy_u3_init(). Because mdelay spins the CPU instead of sleeping,
this could freeze the CPU for up to 500ms during hardware initialization
failures.

Should this be using usleep_range() or msleep() instead?

[ ... ]

> @@ -1020,16 +1020,16 @@ static int an7583_usb_phy_init(struct phy *phy)
>  	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
>  
>  	switch (instance->type) {
>  	case PHY_TYPE_USB2:
>  		an7583_usb_phy_u2_init(phy);
>  		break;
>  	case PHY_TYPE_USB3:
>  		if (phy_get_mode(phy) == PHY_MODE_ETHERNET)
>  			return 0;
>  
>  		an7583_usb_phy_u3_init(phy);
>  		break;
>  	case PHY_TYPE_PCIE:
>  		if (phy_get_mode(phy) == PHY_MODE_ETHERNET)
>  			return 0;
>  
>  		an7583_usb_phy_pcie_init(phy);

[Severity: Medium]
Both an7583_usb_phy_u3_init() and an7583_usb_phy_pcie_init() return an
error code (-EINVAL) when calibration fails, but those values are ignored
here.

Does this falsely notify the PHY framework of a successful initialization?

>  		break;
>  	default:
>  		return -EINVAL;
>  	}

[ ... ]

> @@ -1176,8 +1176,8 @@ static int an7583_usb_phy_u2_set_mode(struct phy *phy, enum phy_mode mode)
>  	case PHY_MODE_USB_HOST:
>  		val |= AIROHA_USB_PHY_FORCE_IDDIG;
>  		break;
>  	case PHY_MODE_USB_OTG:
>  		break;
>  	default:
>  		return 0;
>  	}
>  
>  	regmap_update_bits(priv->regs[AIROHA_USB_PHY_PHY], AIROHA_USB_PHY_U2PHYDTM1,

[Severity: High]
Does this code in an7583_usb_phy_u2_set_mode() write to the base register
space of port 0 instead of the correct port?

Unlike other functions (e.g., power_on or init), this directly accesses
AIROHA_USB_PHY_U2PHYDTM1 without adding instance->offset. If mode
configuration is applied to a secondary port, it seems like this will corrupt
port 0's state.

>  			   AIROHA_USB_PHY_FORCE_IDDIG |
>  			   AIROHA_USB_PHY_IDDIG, val);

[ ... ]

> @@ -1193,12 +1193,12 @@ static int an7583_usb_phy_u3_set_mode(struct phy *phy, enum phy_mode mode,
>  				      int submode)
>  {
>  	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
>  	int ret;
>  
>  	switch (mode) {
>  	case PHY_MODE_ETHERNET:
>  		if (submode != PHY_INTERFACE_MODE_SGMII &&
>  		    submode != PHY_INTERFACE_MODE_1000BASEX &&
>  		    submode != PHY_INTERFACE_MODE_2500BASEX)
>  			return -EOPNOTSUPP;
>  	case PHY_MODE_USB_DEVICE_SS:

[Severity: Low]
Is this an intentional fallthrough?

If so, this switch block needs a fallthrough annotation to prevent compiler
warnings.

>  		break;
>  	default:
>  		return -EOPNOTSUPP;
>  	}
>  
>  	ret = phy_set_mode_ext(instance->serdes_phy, mode, submode);

[Severity: Medium]
Will this nested call to phy_set_mode_ext() in an7583_usb_phy_u3_set_mode()
trigger a lockdep warning?

The core PHY framework invokes the driver's set_mode callback with the
primary phy->mutex held. Calling phy_set_mode_ext() on the secondary PHY
attempts to acquire the secondary PHY's mutex, which belongs to the same
lock class.

[ ... ]

> @@ -1215,12 +1215,12 @@ static int an7583_usb_phy_pcie_set_mode(struct phy *phy, enum phy_mode mode,
>  					int submode)
>  {
>  	struct an7583_usb_phy_instance *instance = phy_get_drvdata(phy);
>  	int ret;
>  
>  	switch (mode) {
>  	case PHY_MODE_ETHERNET:
>  		if (submode != PHY_INTERFACE_MODE_SGMII &&
>  		    submode != PHY_INTERFACE_MODE_1000BASEX &&
>  		    submode != PHY_INTERFACE_MODE_2500BASEX)
>  			return -EOPNOTSUPP;
>  	case PHY_MODE_PCIE:

[Severity: Low]
Is this an intentional fallthrough?

If so, this switch block needs a fallthrough annotation to prevent compiler
warnings.

>  		break;
>  	default:
>  		return -EOPNOTSUPP;
>  	}
>  
>  	ret = phy_set_mode_ext(instance->serdes_phy, mode, submode);

[Severity: Medium]
Will this nested call to phy_set_mode_ext() in an7583_usb_phy_pcie_set_mode()
trigger a lockdep warning?

The core PHY framework invokes the driver's set_mode callback with the
primary phy->mutex held. Calling phy_set_mode_ext() on the secondary PHY
attempts to acquire the secondary PHY's mutex, which belongs to the same
lock class.

[ ... ]

> @@ -1297,29 +1297,29 @@ static int an7583_usb_phy_parse_ports(struct device *dev,
>  				      struct an7583_usb_phy_priv *priv,
>  				      int index, struct device_node *subnode)
>  {
>  	const struct an7583_usb_phy_match_data *data;
>  	struct an7583_usb_phy_instance  *instance;
>  	struct phy *phy;
>  	int ret;
>  
>  	data = of_device_get_match_data(dev);
>  
>  	if (index > data->max_instance)

[Severity: High]
Should this bounds check use >= instead of > in an7583_usb_phy_parse_ports()?

The max_instance is the size of the array (3 for USB), so allowing index to
equal max_instance will cause an out-of-bounds write when priv->phys[index]
is assigned later.

>  		return -EINVAL;
>  
>  	if (!of_device_is_available(subnode))
>  		return 0;
>  
>  	instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
>  	if (!instance)
>  		return -ENOMEM;
>  
>  	instance->serdes_phy = devm_phy_optional_get(dev, NULL);

[Severity: High]
Does devm_phy_optional_get() fetch the per-port serdes PHY from the parent
device node rather than the specific port subnode?

Because it uses dev and not subnode, it appears all subnodes will resolve to
the exact same PHY instance, which would misclassify every port as
PHY_TYPE_USB3 and break USB2 port initialization.

Should this use devm_of_phy_optional_get(dev, subnode, NULL)?

>  	if (IS_ERR(instance->serdes_phy))
>  		return dev_err_probe(dev, PTR_ERR(instance->serdes_phy), "error on serdes phy for USB 3.0\n");
>  
>  	if (!instance->serdes_phy &&
>  	    !of_property_present(subnode, "airoha,usb2-monitor-clk-sel"))
>  		return dev_err_probe(dev, ret, "monitor clock selection or serdes PHY is mandatory for USB PHY\n");

[Severity: Medium]
If the subnode lacks both the serdes_phy and the airoha,usb2-monitor-clk-sel
properties, the error path returns the uninitialized ret variable.

Can this return a garbage error code (or 0) leading to silent initialization
failures?

>  
>  	if (instance->serdes_phy) {
>  		instance->type = PHY_TYPE_USB3;
>  	} else {
>  		ret = of_property_read_u32(subnode, "airoha,usb2-monitor-clk-sel",
>  					   &instance->monclk_sel);
>  		if (ret)
>  			return dev_err_probe(dev, ret, "failed to parse Monitor clock selection\n");
>  
>  		ret = of_property_read_u32(subnode, "reg",
>  					   &instance->offset);
>  		if (ret)
>  			return dev_err_probe(dev, ret, "missing reg for U2 PHY\n");
>  
>  		instance->type = PHY_TYPE_USB2;
>  	}
>  
>  	phy = devm_phy_create(dev, subnode, &airoha_phy);
>  	if (IS_ERR(phy))
>  		return dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
>  
>  	priv->phys[index] = phy;

[ ... ]

> @@ -1341,12 +1341,12 @@ static int airoha_pcie_phy_parse_ports(struct device *dev,
>  				       struct an7583_usb_phy_priv *priv,
>  				       int index, struct device_node *subnode)
>  {
>  	const struct an7583_usb_phy_match_data *data;
>  	struct an7583_usb_phy_instance  *instance;
>  	struct phy *phy;
>  
>  	data = of_device_get_match_data(dev);
>  
>  	if (index > data->max_instance)

[Severity: High]
Should this bounds check use >= instead of > in airoha_pcie_phy_parse_ports()?

The max_instance is the size of the array (1 for PCIe), so allowing index to
equal max_instance will cause an out-of-bounds write when priv->phys[index]
is assigned later.

>  		return -EINVAL;
>  
>  	if (!of_device_is_available(subnode))
>  		return 0;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260827131551.26725-1-ansuelsmth@gmail.com?part=3

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-08-27 13:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27 13:15 [PATCH v3 0/3] phy: Add support for Airoha AN7583 USB PHY Christian Marangi
2026-08-27 13:15 ` [PATCH v3 1/3] dt-bindings: phy: airoha: Document support for " Christian Marangi
2026-08-27 13:25   ` sashiko-bot
2026-08-27 13:15 ` [PATCH v3 2/3] dt-bindings: phy: airoha: Document support for AN7583 Gen2 PCIe PHY Christian Marangi
2026-08-27 13:23   ` sashiko-bot
2026-08-27 13:15 ` [PATCH v3 3/3] phy: airoha: Add support for Airoha AN7583 USB PHY Christian Marangi
2026-08-27 13:26   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox