public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280
@ 2025-11-24 15:54 Balaji Selvanathan
  2025-11-24 15:54 ` [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock Balaji Selvanathan
                   ` (6 more replies)
  0 siblings, 7 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:54 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

This series enables USB3 Super-Speed functionality on QCM6490 and SC7280
platforms by adding support for the QMP USB3-DP Combo PHY. The combo PHY
is a dual-mode PHY that can operate in either USB3 or DisplayPort mode,
and this implementation focuses on USB3 mode to enable Super-Speed USB
support.

The series adds the necessary clock support, implements the
QMP Combo PHY driver ported from upstream Linux, and makes USB speed
fixup configurable.
---
Changes in v2:
- Gave correct commit id for reference linux implementation for
  adding mdelay in drivers/usb/dwc3/core.c
- In drivers/phy/qcom/phy-qcom-qmp-combo.c:
	- Added pipe clock disable in qmp_combo_power_off sequence
	- Added all required clocks except pipe clock
          in qmp_combo_phy_clk_l
	- All clocks except pipe clock are enabled and disabled
	  seperate from pipe clock
	- Added support for regulator power supplies
	- Added a minimal xlate to only return the USB3 phy
- Added "drivers/phy/qcom" to ARM SNAPDRAGON section in MAINTAINERS file
- Link to v1: https://lore.kernel.org/u-boot/20251119152530.4175628-1-balaji.selvanathan@oss.qualcomm.com/
--- 

Balaji Selvanathan (7):
  drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock
  drivers: usb: dwc3: Add delay after core soft reset
  drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver
  arch: arm: mach-snapdragon: Make USB speed fixup configurable
  arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks
  configs: qcm6490: Enable super-speed USB support
  MAINTAINERS: Add entry for Qualcomm PHY drivers

 MAINTAINERS                                |   1 +
 arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi   |   8 +
 arch/arm/mach-snapdragon/Kconfig           |  10 +
 arch/arm/mach-snapdragon/of_fixup.c        |   4 +
 configs/qcm6490_defconfig                  |   5 +
 drivers/clk/qcom/clock-sc7280.c            |   1 +
 drivers/phy/qcom/Kconfig                   |   8 +
 drivers/phy/qcom/Makefile                  |   1 +
 drivers/phy/qcom/phy-qcom-qmp-combo.c      | 642 +++++++++++++++++++++
 drivers/phy/qcom/phy-qcom-qmp-common.h     |  62 ++
 drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h  |  18 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h |  34 ++
 drivers/phy/qcom/phy-qcom-qmp.h            |  17 +
 drivers/usb/dwc3/core.c                    |   2 +
 14 files changed, 813 insertions(+)
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-combo.c
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-common.h
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h

-- 
2.34.1


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

* [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock
  2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
@ 2025-11-24 15:54 ` Balaji Selvanathan
  2025-11-26 14:30   ` Casey Connolly
  2025-12-23  8:31   ` Sumit Garg
  2025-11-24 15:54 ` [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset Balaji Selvanathan
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:54 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

Add support for GCC_USB3_PRIM_PHY_PIPE_CLK which is required by
the USB3 PHY on SC7280/QCM6490 platforms.

Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
---
 drivers/clk/qcom/clock-sc7280.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c
index 55a233df394..a2af73cd976 100644
--- a/drivers/clk/qcom/clock-sc7280.c
+++ b/drivers/clk/qcom/clock-sc7280.c
@@ -111,6 +111,7 @@ static const struct gate_clk sc7280_clks[] = {
 	GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0xf01c, 1),
 	GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0xf054, 1),
 	GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0xf058, 1),
+	GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0xf05c, 1),
 	GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x9e07c, 1),
 	GATE_CLK(GCC_USB30_SEC_MASTER_CLK, 0x9e010, 1),
 	GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x9e080, 1),
-- 
2.34.1


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

* [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset
  2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
  2025-11-24 15:54 ` [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock Balaji Selvanathan
@ 2025-11-24 15:54 ` Balaji Selvanathan
  2025-12-23  9:05   ` Sumit Garg
  2025-11-24 15:54 ` [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver Balaji Selvanathan
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:54 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

Add a 100 ms delay after clearing the core soft reset bit to ensure
the DWC3 controller has sufficient time to complete its reset
sequence before subsequent register accesses.

Without this delay, USB initialization can fail on some Qualcomm
platforms, particularly when using super-speed capable PHYs like
the QMP USB3-DP Combo PHY on SC7280/QCM6490.

The change is taken from following upstream Linux implementation:
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/usb/dwc3/core.c?id=f88359e1588b85cf0e8209ab7d6620085f3441d9

Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
---
v2:
- Gave correct commit id for linux implementation
---
 drivers/usb/dwc3/core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 847fa1f82c3..ff0bca0dd8e 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -94,6 +94,8 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
 	reg &= ~DWC3_GCTL_CORESOFTRESET;
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
+	mdelay(100);
+
 	return 0;
 }
 
-- 
2.34.1


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

* [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver
  2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
  2025-11-24 15:54 ` [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock Balaji Selvanathan
  2025-11-24 15:54 ` [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset Balaji Selvanathan
@ 2025-11-24 15:54 ` Balaji Selvanathan
  2025-11-24 19:51   ` Tom Rini
  2025-11-26 14:46   ` Casey Connolly
  2025-11-24 15:55 ` [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable Balaji Selvanathan
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:54 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

Add support for the Qualcomm QMP USB3-DP Combo PHY found on
SC7280 and QCM6490 platforms. This driver currently implements
USB3 super-speed functionality of the combo PHY.

The QMP Combo PHY is a dual-mode PHY
that can operate in either USB3 mode or DisplayPort mode. This
initial implementation focuses on USB3 mode to enable Super-Speed
USB support.

This is a port of the upstream Linux files to U-Boot:
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/qualcomm/phy-qcom-qmp-combo.c?id=3d25d46a255a83f94d7d4d4216f38aafc8e116b0

Enabled and tested the driver on Qualcomm RB3 Gen2 (QCS6490) board.

Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
---
v2:
- Added pipe clock disable in qmp_combo_power_off sequence
- Added all required clocks except pipe clock in qmp_combo_phy_clk_l
- All clocks except pipe clock are enabled and disabled seperate from pipe clock
- Added support for regulator power supplies
- Added a minimal xlate to only return the USB3 phy
---
 drivers/phy/qcom/Kconfig                   |   8 +
 drivers/phy/qcom/Makefile                  |   1 +
 drivers/phy/qcom/phy-qcom-qmp-combo.c      | 642 +++++++++++++++++++++
 drivers/phy/qcom/phy-qcom-qmp-common.h     |  62 ++
 drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h  |  18 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h |  34 ++
 drivers/phy/qcom/phy-qcom-qmp.h            |  17 +
 7 files changed, 782 insertions(+)
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-combo.c
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-common.h
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
 create mode 100644 drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h

diff --git a/drivers/phy/qcom/Kconfig b/drivers/phy/qcom/Kconfig
index 0dd69f7ffd0..49f830abf01 100644
--- a/drivers/phy/qcom/Kconfig
+++ b/drivers/phy/qcom/Kconfig
@@ -12,6 +12,14 @@ config PHY_QCOM_IPQ4019_USB
 	help
 	  Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s.
 
+config PHY_QCOM_QMP_COMBO
+	bool "Qualcomm QMP USB3-DP Combo PHY driver"
+	depends on PHY && ARCH_SNAPDRAGON
+	help
+	  Enable this to support the USB3-DP Combo QMP PHY on various Qualcomm
+	  chipsets. This driver supports the USB3 PHY functionality of the combo
+	  PHY (USB3 + DisplayPort). Currently only USB3 mode is supported.
+
 config PHY_QCOM_QMP_PCIE
 	tristate "Qualcomm QMP PCIe PHY driver"
 	depends on PHY && ARCH_SNAPDRAGON
diff --git a/drivers/phy/qcom/Makefile b/drivers/phy/qcom/Makefile
index 1c4e7d8d391..714013dc572 100644
--- a/drivers/phy/qcom/Makefile
+++ b/drivers/phy/qcom/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
+obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o
 obj-$(CONFIG_PHY_QCOM_QMP_PCIE) += phy-qcom-qmp-pcie.o
 obj-$(CONFIG_PHY_QCOM_QMP_UFS) += phy-qcom-qmp-ufs.o
 obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
diff --git a/drivers/phy/qcom/phy-qcom-qmp-combo.c b/drivers/phy/qcom/phy-qcom-qmp-combo.c
new file mode 100644
index 00000000000..f5596aa5e50
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-combo.c
@@ -0,0 +1,642 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <generic-phy.h>
+#include <reset.h>
+#include <power/regulator.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+
+#include "phy-qcom-qmp-common.h"
+
+#include "phy-qcom-qmp.h"
+#include "phy-qcom-qmp-pcs-misc-v3.h"
+#include "phy-qcom-qmp-pcs-usb-v4.h"
+#include "phy-qcom-qmp-dp-com-v3.h"
+
+/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
+/* DP PHY soft reset */
+#define SW_DPPHY_RESET                          BIT(0)
+/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
+#define SW_DPPHY_RESET_MUX                      BIT(1)
+/* USB3 PHY soft reset */
+#define SW_USB3PHY_RESET                        BIT(2)
+/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
+#define SW_USB3PHY_RESET_MUX                    BIT(3)
+
+/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
+#define USB3_MODE                               BIT(0) /* enables USB3 mode */
+#define DP_MODE                                 BIT(1) /* enables DP mode */
+
+/* QPHY_V3_DP_COM_TYPEC_CTRL register bits */
+#define SW_PORTSELECT_MUX                       BIT(1)
+
+/* PHY slot identifiers for device tree phandle arguments */
+#define QMP_USB43DP_USB3_PHY    0
+#define QMP_USB43DP_DP_PHY      1
+
+#define PHY_INIT_COMPLETE_TIMEOUT		10000
+
+struct qmp_combo_offsets {
+	u16 com;
+	u16 txa;
+	u16 rxa;
+	u16 txb;
+	u16 rxb;
+	u16 usb3_serdes;
+	u16 usb3_pcs_misc;
+	u16 usb3_pcs;
+	u16 usb3_pcs_usb;
+};
+
+/*
+ * Initialisation tables
+ */
+
+static const struct qmp_combo_offsets qmp_combo_offsets_v3 = {
+	.com		= 0x0000,
+	.txa		= 0x1200,
+	.rxa		= 0x1400,
+	.txb		= 0x1600,
+	.rxb		= 0x1800,
+	.usb3_serdes	= 0x1000,
+	.usb3_pcs_misc	= 0x1a00,
+	.usb3_pcs	= 0x1c00,
+	.usb3_pcs_usb	= 0x1f00,
+};
+
+static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e),
+	QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
+};
+
+static const struct qmp_phy_init_tbl sm8250_usb3_tx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x60),
+	QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x60),
+	QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11),
+	QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02),
+	QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5),
+	QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x40, 1),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x54, 2),
+};
+
+static const struct qmp_phy_init_tbl sm8250_usb3_rx_tbl[] = {
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff, 1),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f, 2),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f, 1),
+	QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff, 2),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x7f),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x97),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f),
+	QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10),
+};
+
+static const struct qmp_phy_init_tbl sm8250_usb3_pcs_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10),
+};
+
+static const struct qmp_phy_init_tbl sm8250_usb3_pcs_usb_tbl[] = {
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
+	QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07),
+};
+
+struct qmp_phy_cfg {
+	const struct qmp_combo_offsets *offsets;
+	const struct qmp_phy_init_tbl *serdes_tbl;
+	int serdes_tbl_num;
+	const struct qmp_phy_init_tbl *tx_tbl;
+	int tx_tbl_num;
+	const struct qmp_phy_init_tbl *rx_tbl;
+	int rx_tbl_num;
+	const struct qmp_phy_init_tbl *pcs_tbl;
+	int pcs_tbl_num;
+	const struct qmp_phy_init_tbl *pcs_usb_tbl;
+	int pcs_usb_tbl_num;
+	const char * const *vreg_list;
+	int num_vregs;
+	/* true, if PHY needs delay after POWER_DOWN */
+	bool has_pwrdn_delay;
+};
+
+/* list of clocks required by phy */
+static const char * const qmp_combo_phy_clk_l[] = {
+	"aux", "com_aux",
+};
+
+/* list of regulators */
+static const char * const qmp_phy_vreg_l[] = {
+	"vdda-phy",
+	"vdda-pll",
+};
+
+struct qmp_combo {
+	struct udevice *dev;
+	void __iomem *com;
+	void __iomem *serdes;
+	void __iomem *tx;
+	void __iomem *rx;
+	void __iomem *tx2;
+	void __iomem *rx2;
+	void __iomem *pcs;
+	void __iomem *pcs_usb;
+	void __iomem *pcs_misc;
+	struct clk *clks;
+	struct clk *pipe_clk;
+	int num_clks;
+	struct reset_ctl_bulk resets;
+	int num_resets;
+	struct udevice **vregs;
+	int num_vregs;
+	const struct qmp_phy_cfg *cfg;
+};
+
+static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
+{
+	u32 reg;
+
+	reg = readl(base + offset);
+	reg |= val;
+	writel(reg, base + offset);
+
+	/* ensure that above write is through */
+	readl(base + offset);
+}
+
+static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
+{
+	u32 reg;
+
+	reg = readl(base + offset);
+	reg &= ~val;
+	writel(reg, base + offset);
+
+	/* ensure that above write is through */
+	readl(base + offset);
+}
+
+static int qmp_combo_com_exit(struct qmp_combo *qmp)
+{
+	int i;
+
+	for (i = 0; i < qmp->num_clks; i++)
+		clk_disable(&qmp->clks[i]);
+
+	reset_assert_bulk(&qmp->resets);
+
+	for (i = qmp->num_vregs - 1; i >= 0; i--)
+		regulator_set_enable(qmp->vregs[i], false);
+
+	return 0;
+}
+
+static int qmp_combo_com_init(struct qmp_combo *qmp)
+{
+	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	void __iomem *com = qmp->com;
+	void __iomem *pcs = qmp->pcs;
+	u32 val;
+	int ret, i;
+
+	ret = reset_assert_bulk(&qmp->resets);
+	if (ret) {
+		printf("Failed to assert resets: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_deassert_bulk(&qmp->resets);
+	if (ret) {
+		printf("Failed to deassert resets: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < qmp->num_vregs; i++) {
+		ret = regulator_set_enable(qmp->vregs[i], true);
+		if (ret) {
+			dev_err(qmp->dev, "Failed to enable regulator %d: %d\n", i, ret);
+			while (--i >= 0)
+				regulator_set_enable(qmp->vregs[i], false);
+			reset_assert_bulk(&qmp->resets);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < qmp->num_clks; i++) {
+		ret = clk_enable(&qmp->clks[i]);
+		if (ret) {
+			printf("Failed to enable clock %d: %d\n", i, ret);
+			while (--i >= 0)
+				clk_disable(&qmp->clks[i]);
+			for (i = qmp->num_vregs - 1; i >= 0; i--)
+				regulator_set_enable(qmp->vregs[i], false);
+			reset_assert_bulk(&qmp->resets);
+			return ret;
+		}
+	}
+
+	/* Common block register writes */
+	qphy_setbits(com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, SW_PWRDN);
+	qphy_setbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
+		     SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
+		     SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
+
+	val = SW_PORTSELECT_MUX;
+	writel(val, com + QPHY_V3_DP_COM_TYPEC_CTRL);
+
+	writel(USB3_MODE | DP_MODE, com + QPHY_V3_DP_COM_PHY_MODE_CTRL);
+
+	qphy_clrbits(com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
+		     SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
+		     SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
+
+	qphy_clrbits(com, QPHY_V3_DP_COM_SWI_CTRL, 0x03);
+
+	qphy_clrbits(com, QPHY_V3_DP_COM_SW_RESET, SW_RESET);
+
+	qphy_setbits(pcs, QPHY_V4_PCS_POWER_DOWN_CONTROL, SW_PWRDN);
+
+	return 0;
+}
+
+static int qmp_combo_usb_power_on(struct qmp_combo *qmp)
+{
+	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	void __iomem *serdes = qmp->serdes;
+	void __iomem *tx = qmp->tx;
+	void __iomem *rx = qmp->rx;
+	void __iomem *tx2 = qmp->tx2;
+	void __iomem *rx2 = qmp->rx2;
+	void __iomem *pcs = qmp->pcs;
+	void __iomem *pcs_usb = qmp->pcs_usb;
+	u32 val;
+	int ret;
+
+	/* Serdes configuration */
+	qmp_configure(qmp->dev, serdes, cfg->serdes_tbl, cfg->serdes_tbl_num);
+
+	ret = clk_prepare_enable(qmp->pipe_clk);
+	if (ret) {
+		dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret);
+		return ret;
+	}
+
+	/* Tx, Rx configurations */
+	qmp_configure_lane(qmp->dev, tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
+	qmp_configure_lane(qmp->dev, tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
+
+	qmp_configure_lane(qmp->dev, rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
+	qmp_configure_lane(qmp->dev, rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
+
+	/* PCS configuration */
+	qmp_configure(qmp->dev, pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
+
+	if (pcs_usb) {
+		qmp_configure(qmp->dev, pcs_usb,
+			      cfg->pcs_usb_tbl,
+			      cfg->pcs_usb_tbl_num);
+	}
+
+	if (cfg->has_pwrdn_delay)
+		udelay(20);
+
+	/* Pull PHY out of reset */
+	qphy_clrbits(pcs, QPHY_V4_PCS_SW_RESET, SW_RESET);
+
+	/* Start SerDes and Phy-Coding-Sublayer */
+	qphy_setbits(pcs, QPHY_V4_PCS_START_CONTROL,
+		     SERDES_START | PCS_START);
+
+	/* Wait for PHY initialization */
+	ret = readl_poll_timeout(pcs + QPHY_V4_PCS_PCS_STATUS1, val,
+				 !(val & PHYSTATUS), PHY_INIT_COMPLETE_TIMEOUT);
+
+	if (ret) {
+		printf("QMP USB3 PHY initialization timeout\n");
+		clk_disable(qmp->pipe_clk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int qmp_combo_power_on(struct phy *phy)
+{
+	struct qmp_combo *qmp = dev_get_priv(phy->dev);
+	int ret;
+
+	/* Initialize common block */
+	ret = qmp_combo_com_init(qmp);
+	if (ret)
+		return ret;
+
+	/* Initialize USB3-specific configuration */
+	ret = qmp_combo_usb_power_on(qmp);
+	if (ret) {
+		qmp_combo_com_exit(qmp);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int qmp_combo_power_off(struct phy *phy)
+{
+	struct qmp_combo *qmp = dev_get_priv(phy->dev);
+	void __iomem *com = qmp->com;
+
+	clk_disable(qmp->pipe_clk);
+
+	/* PHY reset */
+	qphy_setbits(qmp->pcs, QPHY_V4_PCS_SW_RESET, SW_RESET);
+
+	/* Stop SerDes and Phy-Coding-Sublayer */
+	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_START_CONTROL,
+		     SERDES_START | PCS_START);
+
+	/* Put PHY into POWER DOWN state: active low */
+	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_POWER_DOWN_CONTROL, SW_PWRDN);
+
+	/* Power down common block */
+	qphy_clrbits(com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, SW_PWRDN);
+
+	return qmp_combo_com_exit(qmp);
+}
+
+static int qmp_combo_reset_init(struct qmp_combo *qmp)
+{
+	struct udevice *dev = qmp->dev;
+	int ret;
+
+	ret = reset_get_bulk(dev, &qmp->resets);
+	if (ret) {
+		printf("Failed to get resets: %d\n", ret);
+		return ret;
+	}
+
+	qmp->num_resets = qmp->resets.count;
+
+	return 0;
+}
+
+static int qmp_combo_clk_init(struct qmp_combo *qmp)
+{
+	struct udevice *dev = qmp->dev;
+	int num = ARRAY_SIZE(qmp_combo_phy_clk_l);
+	int i, ret;
+
+	qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
+	if (!qmp->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < num; i++) {
+		ret = clk_get_by_name(dev, qmp_combo_phy_clk_l[i], &qmp->clks[i]);
+		if (ret) {
+			dev_err(dev, "failed to get %s clock: %d\n",
+				qmp_combo_phy_clk_l[i], ret);
+			return ret;
+		}
+	}
+
+	qmp->num_clks = num;
+	return 0;
+}
+
+static int qmp_combo_vreg_init(struct qmp_combo *qmp)
+{
+	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	struct udevice *dev = qmp->dev;
+	int num = cfg->num_vregs;
+	int i, ret;
+
+	if (!num)
+		return 0;
+
+	qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
+	if (!qmp->vregs)
+		return -ENOMEM;
+
+	for (i = 0; i < num; i++) {
+		ret = device_get_supply_regulator(dev, cfg->vreg_list[i],
+						  &qmp->vregs[i]);
+		if (ret) {
+			dev_dbg(dev, "regulator %s not found (optional)\n",
+				cfg->vreg_list[i]);
+			qmp->num_vregs = 0;
+			return 0;
+		}
+	}
+
+	qmp->num_vregs = num;
+	dev_dbg(dev, "found %d regulators\n", num);
+	return 0;
+}
+
+static int qmp_combo_parse_dt(struct qmp_combo *qmp)
+{
+	const struct qmp_phy_cfg *cfg = qmp->cfg;
+	const struct qmp_combo_offsets *offs = cfg->offsets;
+	struct udevice *dev = qmp->dev;
+	void __iomem *base;
+	int ret;
+
+	if (!offs)
+		return -EINVAL;
+
+	base = (void __iomem *)dev_read_addr(dev);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	qmp->com = base + offs->com;
+	qmp->serdes = base + offs->usb3_serdes;
+	qmp->tx = base + offs->txa;
+	qmp->rx = base + offs->rxa;
+	qmp->tx2 = base + offs->txb;
+	qmp->rx2 = base + offs->rxb;
+	qmp->pcs = base + offs->usb3_pcs;
+	qmp->pcs_usb = base + offs->usb3_pcs_usb;
+	qmp->pcs_misc = base + offs->usb3_pcs_misc;
+
+	ret = qmp_combo_clk_init(qmp);
+	if (ret)
+		return ret;
+
+	qmp->pipe_clk = devm_clk_get(dev, "usb3_pipe");
+	if (IS_ERR(qmp->pipe_clk)) {
+		dev_err(dev, "failed to get pipe clock (%ld)\n",
+			PTR_ERR(qmp->pipe_clk));
+		return ret;
+	}
+
+	ret = qmp_combo_reset_init(qmp);
+	if (ret)
+		return ret;
+
+	ret = qmp_combo_vreg_init(qmp);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int qmp_combo_probe(struct udevice *dev)
+{
+	struct qmp_combo *qmp = dev_get_priv(dev);
+	int ret;
+
+	qmp->dev = dev;
+	qmp->cfg = (const struct qmp_phy_cfg *)dev_get_driver_data(dev);
+	if (!qmp->cfg) {
+		printf("Failed to get PHY configuration\n");
+		return -EINVAL;
+	}
+
+	ret = qmp_combo_parse_dt(qmp);
+
+	return ret;
+}
+
+static const struct qmp_phy_cfg sc7280_usb3dpphy_cfg = {
+	.offsets		= &qmp_combo_offsets_v3,
+	.serdes_tbl		= sm8150_usb3_serdes_tbl,
+	.serdes_tbl_num		= ARRAY_SIZE(sm8150_usb3_serdes_tbl),
+	.tx_tbl			= sm8250_usb3_tx_tbl,
+	.tx_tbl_num		= ARRAY_SIZE(sm8250_usb3_tx_tbl),
+	.rx_tbl			= sm8250_usb3_rx_tbl,
+	.rx_tbl_num		= ARRAY_SIZE(sm8250_usb3_rx_tbl),
+	.pcs_tbl		= sm8250_usb3_pcs_tbl,
+	.pcs_tbl_num		= ARRAY_SIZE(sm8250_usb3_pcs_tbl),
+	.pcs_usb_tbl		= sm8250_usb3_pcs_usb_tbl,
+	.pcs_usb_tbl_num	= ARRAY_SIZE(sm8250_usb3_pcs_usb_tbl),
+	.vreg_list		= qmp_phy_vreg_l,
+	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
+
+	.has_pwrdn_delay	= true,
+};
+
+static int qmp_combo_xlate(struct phy *phy, struct ofnode_phandle_args *args)
+{
+	if (args->args_count != 1) {
+		debug("Invalid args_count: %d\n", args->args_count);
+		return -EINVAL;
+	}
+
+	/* We only support the USB3 phy at slot 0 */
+	if (args->args[0] == QMP_USB43DP_DP_PHY)
+		return -EINVAL;
+
+	phy->id = QMP_USB43DP_USB3_PHY;
+
+	return 0;
+}
+
+static struct phy_ops qmp_combo_ops = {
+	.init = qmp_combo_power_on,
+	.exit = qmp_combo_power_off,
+	.of_xlate = qmp_combo_xlate,
+};
+
+static const struct udevice_id qmp_combo_ids[] = {
+	{
+		.compatible = "qcom,sc7280-qmp-usb3-dp-phy",
+		.data = (ulong)&sc7280_usb3dpphy_cfg,
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(qmp_combo) = {
+	.name = "qcom-qmp-usb3-dp-phy",
+	.id = UCLASS_PHY,
+	.of_match = qmp_combo_ids,
+	.ops = &qmp_combo_ops,
+	.probe = qmp_combo_probe,
+	.priv_auto = sizeof(struct qmp_combo),
+};
diff --git a/drivers/phy/qcom/phy-qcom-qmp-common.h b/drivers/phy/qcom/phy-qcom-qmp-common.h
new file mode 100644
index 00000000000..71356fb7dd0
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-common.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_COMMON_H_
+#define QCOM_PHY_QMP_COMMON_H_
+
+struct qmp_phy_init_tbl {
+	unsigned int offset;
+	unsigned int val;
+	char *name;
+	/*
+	 * mask of lanes for which this register is written
+	 * for cases when second lane needs different values
+	 */
+	u8 lane_mask;
+};
+
+#define QMP_PHY_INIT_CFG(o, v)		\
+	{				\
+		.offset = o,		\
+		.val = v,		\
+		.name = #o,		\
+		.lane_mask = 0xff,	\
+	}
+
+#define QMP_PHY_INIT_CFG_LANE(o, v, l)	\
+	{				\
+		.offset = o,		\
+		.val = v,		\
+		.name = #o,		\
+		.lane_mask = l,		\
+	}
+
+static inline void qmp_configure_lane(struct udevice *dev, void __iomem *base,
+				      const struct qmp_phy_init_tbl tbl[],
+				      int num, u8 lane_mask)
+{
+	int i;
+	const struct qmp_phy_init_tbl *t = tbl;
+
+	if (!t)
+		return;
+
+	for (i = 0; i < num; i++, t++) {
+		if (!(t->lane_mask & lane_mask))
+			continue;
+
+		dev_dbg(dev, "Writing Reg: %s Offset: 0x%04x Val: 0x%02x\n",
+			t->name, t->offset, t->val);
+		writel(t->val, base + t->offset);
+	}
+}
+
+static inline void qmp_configure(struct udevice *dev, void __iomem *base,
+				 const struct qmp_phy_init_tbl tbl[], int num)
+{
+	qmp_configure_lane(dev, base, tbl, num, 0xff);
+}
+
+#endif
diff --git a/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
new file mode 100644
index 00000000000..396179ef38b
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_DP_COM_V3_H_
+#define QCOM_PHY_QMP_DP_COM_V3_H_
+
+/* Only for QMP V3 & V4 PHY - DP COM registers */
+#define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
+#define QPHY_V3_DP_COM_SW_RESET				0x04
+#define QPHY_V3_DP_COM_POWER_DOWN_CTRL			0x08
+#define QPHY_V3_DP_COM_SWI_CTRL				0x0c
+#define QPHY_V3_DP_COM_TYPEC_CTRL			0x10
+#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL			0x14
+#define QPHY_V3_DP_COM_RESET_OVRD_CTRL			0x1c
+
+#endif
diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
new file mode 100644
index 00000000000..d7fd4ac0fc5
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_USB_V4_H_
+#define QCOM_PHY_QMP_PCS_USB_V4_H_
+
+/* Only for QMP V4 PHY - USB3 PCS registers */
+#define QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1		0x000
+#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_STATUS		0x004
+#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL		0x008
+#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL2		0x00c
+#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_SOURCE_STATUS	0x010
+#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR		0x014
+#define QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL	0x018
+#define QPHY_V4_PCS_USB3_LFPS_TX_ECSTART		0x01c
+#define QPHY_V4_PCS_USB3_LFPS_PER_TIMER_VAL		0x020
+#define QPHY_V4_PCS_USB3_LFPS_TX_END_CNT_U3_START	0x024
+#define QPHY_V4_PCS_USB3_RXEQTRAINING_LOCK_TIME		0x028
+#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME		0x02c
+#define QPHY_V4_PCS_USB3_RXEQTRAINING_CTLE_TIME		0x030
+#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME_S2	0x034
+#define QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2	0x038
+#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_L		0x03c
+#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_H		0x040
+#define QPHY_V4_PCS_USB3_ARCVR_DTCT_EN_PERIOD		0x044
+#define QPHY_V4_PCS_USB3_ARCVR_DTCT_CM_DLY		0x048
+#define QPHY_V4_PCS_USB3_TXONESZEROS_RUN_LENGTH		0x04c
+#define QPHY_V4_PCS_USB3_ALFPS_DEGLITCH_VAL		0x050
+#define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL	0x054
+#define QPHY_V4_PCS_USB3_TEST_CONTROL			0x058
+
+#endif
diff --git a/drivers/phy/qcom/phy-qcom-qmp.h b/drivers/phy/qcom/phy-qcom-qmp.h
index 99f4d447caf..06dac21ddc4 100644
--- a/drivers/phy/qcom/phy-qcom-qmp.h
+++ b/drivers/phy/qcom/phy-qcom-qmp.h
@@ -12,12 +12,17 @@
 #include "phy-qcom-qmp-qserdes-com-v3.h"
 #include "phy-qcom-qmp-qserdes-txrx-v3.h"
 
+#include "phy-qcom-qmp-qserdes-com-v4.h"
+#include "phy-qcom-qmp-qserdes-txrx-v4.h"
+
 #include "phy-qcom-qmp-qserdes-pll.h"
 
 #include "phy-qcom-qmp-pcs-v2.h"
 
 #include "phy-qcom-qmp-pcs-v3.h"
 
+#include "phy-qcom-qmp-pcs-v4.h"
+
 /* Only for QMP V3 & V4 PHY - DP COM registers */
 #define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
 #define QPHY_V3_DP_COM_SW_RESET				0x04
@@ -112,4 +117,16 @@
 #define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS		0x0e0
 #define QSERDES_V6_DP_PHY_STATUS			0x0e4
 
+/* QPHY_SW_RESET bit */
+#define SW_RESET                                BIT(0)
+/* QPHY_POWER_DOWN_CONTROL */
+#define SW_PWRDN                                BIT(0)
+
+/* QPHY_START_CONTROL bits */
+#define SERDES_START                            BIT(0)
+#define PCS_START                               BIT(1)
+
+/* QPHY_PCS_STATUS bit */
+#define PHYSTATUS                               BIT(6)
+
 #endif
-- 
2.34.1


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

* [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable
  2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
                   ` (2 preceding siblings ...)
  2025-11-24 15:54 ` [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver Balaji Selvanathan
@ 2025-11-24 15:55 ` Balaji Selvanathan
  2025-11-26 14:24   ` Casey Connolly
  2025-11-24 15:55 ` [PATCH v2 5/7] arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks Balaji Selvanathan
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:55 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

Add CONFIG_QCOM_USB_FIXUP option to allow platforms to disable
the USB speed limitation fixup when they have proper super-speed
USB support in U-Boot.

Currently, U-Boot limits USB to high-speed mode on all Qualcomm
platforms by fixing up the device tree at runtime. This was
necessary because most platforms lacked super-speed PHY drivers.

However, newer platforms now have proper QMP PHY drivers that support
super-speed USB. For these platforms, the fixup is counterproductive
as it prevents the hardware from operating at its full capability.

This change:
- Adds CONFIG_QCOM_USB_FIXUP (default y) to maintain backward
  compatibility with existing platforms
- Wraps the fixup code with #ifdef to allow selective disabling
- Allows platforms with super-speed support to disable the fixup
  via their defconfig

Platforms without super-speed PHY drivers will continue to work
as before with the fixup enabled by default.

Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
---
 arch/arm/mach-snapdragon/Kconfig    | 10 ++++++++++
 arch/arm/mach-snapdragon/of_fixup.c |  4 ++++
 2 files changed, 14 insertions(+)

diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
index 976c0e35fce..6c53aeef597 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -29,6 +29,16 @@ config SYS_MALLOC_LEN
 config LNX_KRNL_IMG_TEXT_OFFSET_BASE
 	default 0x80000000
 
+config QCOM_USB_FIXUP
+	bool "Enable USB speed fixup for Qualcomm platforms"
+	default y
+	help
+	  Enable runtime fixup of USB device tree nodes to limit USB to
+	  high-speed mode. This is needed on some Qualcomm platforms where
+	  U-Boot doesn't support super-speed USB.
+	  Disable this for platforms that have proper super-speed USB support
+	  in U-Boot.
+
 config SYS_BOARD
 	string "Snapdragon SoCs based board"
 	help
diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c
index eec2c0c757e..6a64168f67e 100644
--- a/arch/arm/mach-snapdragon/of_fixup.c
+++ b/arch/arm/mach-snapdragon/of_fixup.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <time.h>
 
+#ifdef CONFIG_QCOM_USB_FIXUP
 /* U-Boot only supports USB high-speed mode on Qualcomm platforms with DWC3
  * USB controllers. Rather than requiring source level DT changes, we fix up
  * DT here. This improves compatibility with upstream DT and simplifies the
@@ -115,6 +116,7 @@ static void fixup_usb_nodes(struct device_node *root)
 			log_warning("Failed to fixup node %s: %d\n", glue_np->name, ret);
 	}
 }
+#endif
 
 /* Remove all references to the rpmhpd device */
 static void fixup_power_domains(struct device_node *root)
@@ -157,7 +159,9 @@ static int qcom_of_fixup_nodes(void * __maybe_unused ctx, struct event *event)
 {
 	struct device_node *root = event->data.of_live_built.root;
 
+#ifdef CONFIG_QCOM_USB_FIXUP
 	time_call(fixup_usb_nodes, root);
+#endif
 	time_call(fixup_power_domains, root);
 
 	return 0;
-- 
2.34.1


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

* [PATCH v2 5/7] arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks
  2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
                   ` (3 preceding siblings ...)
  2025-11-24 15:55 ` [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable Balaji Selvanathan
@ 2025-11-24 15:55 ` Balaji Selvanathan
  2025-11-26 14:26   ` Casey Connolly
  2025-11-24 15:55 ` [PATCH v2 6/7] configs: qcm6490: Enable super-speed USB support Balaji Selvanathan
  2025-11-24 15:55 ` [PATCH v2 7/7] MAINTAINERS: Add entry for Qualcomm PHY drivers Balaji Selvanathan
  6 siblings, 1 reply; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:55 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

Override the USB QMP PHY clock properties to use only GCC clocks
supported in U-Boot, removing the unsupported RPMH_CXO_CLK from
the qcs6490-rb3gen2's device tree.

Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
---
 arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
index 50674b692ed..14669b50821 100644
--- a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
+++ b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
@@ -22,6 +22,14 @@
 	/delete-property/ usb-role-switch;
 };
 
+&usb_1_qmpphy {
+	clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+		 <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
+		 <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+	clock-names = "aux",
+		      "com_aux",
+		      "usb3_pipe";
+};
 // RAM Entry 0 : Base 0x0080000000  Size 0x003A800000
 // RAM Entry 1 : Base 0x00C0000000  Size 0x0001800000
 // RAM Entry 2 : Base 0x00C3400000  Size 0x003CC00000
-- 
2.34.1


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

* [PATCH v2 6/7] configs: qcm6490: Enable super-speed USB support
  2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
                   ` (4 preceding siblings ...)
  2025-11-24 15:55 ` [PATCH v2 5/7] arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks Balaji Selvanathan
@ 2025-11-24 15:55 ` Balaji Selvanathan
  2025-11-24 15:55 ` [PATCH v2 7/7] MAINTAINERS: Add entry for Qualcomm PHY drivers Balaji Selvanathan
  6 siblings, 0 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:55 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

Enable the QMP Combo PHY driver and disable the USB speed fixup
to allow super-speed USB operation on QCM6490 platforms.

With the QMP USB3-DP Combo PHY driver now available, QCM6490 can
support super-speed USB in U-Boot. The USB speed limitation fixup
is no longer needed and would prevent the hardware from operating
at full capability.

Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
---
 configs/qcm6490_defconfig | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/configs/qcm6490_defconfig b/configs/qcm6490_defconfig
index 54eb5dedaec..1d9d9a2425d 100644
--- a/configs/qcm6490_defconfig
+++ b/configs/qcm6490_defconfig
@@ -13,3 +13,8 @@ CONFIG_TEXT_BASE=0x9fc00000
 CONFIG_REMAKE_ELF=y
 
 CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs6490-rb3gen2"
+
+# Disable USB fixup - QCM6490 supports super-speed USB
+# CONFIG_QCOM_USB_FIXUP is not set
+
+CONFIG_PHY_QCOM_QMP_COMBO=y
-- 
2.34.1


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

* [PATCH v2 7/7] MAINTAINERS: Add entry for Qualcomm PHY drivers
  2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
                   ` (5 preceding siblings ...)
  2025-11-24 15:55 ` [PATCH v2 6/7] configs: qcm6490: Enable super-speed USB support Balaji Selvanathan
@ 2025-11-24 15:55 ` Balaji Selvanathan
  6 siblings, 0 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-24 15:55 UTC (permalink / raw)
  To: trini, casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, balaji.selvanathan, rui.silva,
	ilias.apalodimas, luca.weiss, quic_varada, u-boot, u-boot-qcom

Add the file pattern for Qualcomm PHY drivers to the MAINTAINERS file.

Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b43dae882b3..9093ae35b65 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -672,6 +672,7 @@ F:	drivers/*/*/pm8???-*
 F:	drivers/gpio/msm_gpio.c
 F:	drivers/mmc/msm_sdhci.c
 F:	drivers/phy/msm8916-usbh-phy.c
+F:	drivers/phy/qcom/
 F:	drivers/serial/serial_msm.c
 F:	drivers/serial/serial_msm_geni.c
 F:	drivers/smem/msm_smem.c
-- 
2.34.1


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

* Re: [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver
  2025-11-24 15:54 ` [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver Balaji Selvanathan
@ 2025-11-24 19:51   ` Tom Rini
  2025-11-25 10:33     ` Balaji Selvanathan
  2025-11-26 14:46   ` Casey Connolly
  1 sibling, 1 reply; 23+ messages in thread
From: Tom Rini @ 2025-11-24 19:51 UTC (permalink / raw)
  To: Balaji Selvanathan
  Cc: casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2, marex,
	malysagreg, arturs.artamonovs, utsav.agarwal, vasileios.bimpikas,
	ian.roberts, nathan.morrison, peng.fan, alif.zakuan.yuslaimi,
	kory.maincent, sjg, jerome.forissier, ziyao, stefan.roese,
	mkorpershoek, rui.silva, ilias.apalodimas, luca.weiss,
	quic_varada, u-boot, u-boot-qcom

[-- Attachment #1: Type: text/plain, Size: 1699 bytes --]

On Mon, Nov 24, 2025 at 09:24:59PM +0530, Balaji Selvanathan wrote:

> Add support for the Qualcomm QMP USB3-DP Combo PHY found on
> SC7280 and QCM6490 platforms. This driver currently implements
> USB3 super-speed functionality of the combo PHY.
> 
> The QMP Combo PHY is a dual-mode PHY
> that can operate in either USB3 mode or DisplayPort mode. This
> initial implementation focuses on USB3 mode to enable Super-Speed
> USB support.
> 
> This is a port of the upstream Linux files to U-Boot:
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/qualcomm/phy-qcom-qmp-combo.c?id=3d25d46a255a83f94d7d4d4216f38aafc8e116b0
> 
> Enabled and tested the driver on Qualcomm RB3 Gen2 (QCS6490) board.
> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
[snip]
> diff --git a/drivers/phy/qcom/Kconfig b/drivers/phy/qcom/Kconfig
> index 0dd69f7ffd0..49f830abf01 100644
> --- a/drivers/phy/qcom/Kconfig
> +++ b/drivers/phy/qcom/Kconfig
> @@ -12,6 +12,14 @@ config PHY_QCOM_IPQ4019_USB
>  	help
>  	  Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s.
>  
> +config PHY_QCOM_QMP_COMBO
> +	bool "Qualcomm QMP USB3-DP Combo PHY driver"
> +	depends on PHY && ARCH_SNAPDRAGON
> +	help
> +	  Enable this to support the USB3-DP Combo QMP PHY on various Qualcomm
> +	  chipsets. This driver supports the USB3 PHY functionality of the combo
> +	  PHY (USB3 + DisplayPort). Currently only USB3 mode is supported.
> +
>  config PHY_QCOM_QMP_PCIE
>  	tristate "Qualcomm QMP PCIe PHY driver"

Can you please do a follow-up to fix this tristate (and any other in
qualcomm specific Kconfig files) ? Thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver
  2025-11-24 19:51   ` Tom Rini
@ 2025-11-25 10:33     ` Balaji Selvanathan
  0 siblings, 0 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-25 10:33 UTC (permalink / raw)
  To: Tom Rini
  Cc: casey.connolly, neil.armstrong, sumit.garg, lukma, seanga2, marex,
	malysagreg, arturs.artamonovs, utsav.agarwal, vasileios.bimpikas,
	ian.roberts, nathan.morrison, peng.fan, alif.zakuan.yuslaimi,
	kory.maincent, sjg, jerome.forissier, ziyao, stefan.roese,
	mkorpershoek, rui.silva, ilias.apalodimas, luca.weiss,
	quic_varada, u-boot, u-boot-qcom


On 11/25/2025 1:21 AM, Tom Rini wrote:
> On Mon, Nov 24, 2025 at 09:24:59PM +0530, Balaji Selvanathan wrote:
>
>> Add support for the Qualcomm QMP USB3-DP Combo PHY found on
>> SC7280 and QCM6490 platforms. This driver currently implements
>> USB3 super-speed functionality of the combo PHY.
>>
>> The QMP Combo PHY is a dual-mode PHY
>> that can operate in either USB3 mode or DisplayPort mode. This
>> initial implementation focuses on USB3 mode to enable Super-Speed
>> USB support.
>>
>> This is a port of the upstream Linux files to U-Boot:
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/qualcomm/phy-qcom-qmp-combo.c?id=3d25d46a255a83f94d7d4d4216f38aafc8e116b0
>>
>> Enabled and tested the driver on Qualcomm RB3 Gen2 (QCS6490) board.
>>
>> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> [snip]
>> diff --git a/drivers/phy/qcom/Kconfig b/drivers/phy/qcom/Kconfig
>> index 0dd69f7ffd0..49f830abf01 100644
>> --- a/drivers/phy/qcom/Kconfig
>> +++ b/drivers/phy/qcom/Kconfig
>> @@ -12,6 +12,14 @@ config PHY_QCOM_IPQ4019_USB
>>   	help
>>   	  Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s.
>>   
>> +config PHY_QCOM_QMP_COMBO
>> +	bool "Qualcomm QMP USB3-DP Combo PHY driver"
>> +	depends on PHY && ARCH_SNAPDRAGON
>> +	help
>> +	  Enable this to support the USB3-DP Combo QMP PHY on various Qualcomm
>> +	  chipsets. This driver supports the USB3 PHY functionality of the combo
>> +	  PHY (USB3 + DisplayPort). Currently only USB3 mode is supported.
>> +
>>   config PHY_QCOM_QMP_PCIE
>>   	tristate "Qualcomm QMP PCIe PHY driver"
> Can you please do a follow-up to fix this tristate (and any other in
> qualcomm specific Kconfig files) ? Thanks!

Sure Tom, will create a seperate patch to fix the tristates.

Thanks,

Balaji

>

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

* Re: [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable
  2025-11-24 15:55 ` [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable Balaji Selvanathan
@ 2025-11-26 14:24   ` Casey Connolly
  2025-12-03 11:21     ` Balaji Selvanathan
  0 siblings, 1 reply; 23+ messages in thread
From: Casey Connolly @ 2025-11-26 14:24 UTC (permalink / raw)
  To: Balaji Selvanathan, trini, neil.armstrong, sumit.garg, lukma,
	seanga2, marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom

Hi Balaji,

On 24/11/2025 16:55, Balaji Selvanathan wrote:
> Add CONFIG_QCOM_USB_FIXUP option to allow platforms to disable
> the USB speed limitation fixup when they have proper super-speed
> USB support in U-Boot.

In general, we prefer to handle cases like this at runtime rather than
compile time. Could you rework this to check for the "qcom,sc7280-dwc3"
compatible and just skip the check in that case? I would also propose
adding a log_warning() in the fixup case so that folks working on other
platforms know to add their compatible too.

Obviously that's still not an ideal solution, maybe it would be possible
to implement the Super Smart (tm) fix and actually check if a driver
/will/ bind to the ss-phy node before the fixup, it depends how slow
that would be.

Kind regards,

> 
> Currently, U-Boot limits USB to high-speed mode on all Qualcomm
> platforms by fixing up the device tree at runtime. This was
> necessary because most platforms lacked super-speed PHY drivers.
> 
> However, newer platforms now have proper QMP PHY drivers that support
> super-speed USB. For these platforms, the fixup is counterproductive
> as it prevents the hardware from operating at its full capability.
> 
> This change:
> - Adds CONFIG_QCOM_USB_FIXUP (default y) to maintain backward
>   compatibility with existing platforms
> - Wraps the fixup code with #ifdef to allow selective disabling
> - Allows platforms with super-speed support to disable the fixup
>   via their defconfig
> 
> Platforms without super-speed PHY drivers will continue to work
> as before with the fixup enabled by default.
> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> ---
>  arch/arm/mach-snapdragon/Kconfig    | 10 ++++++++++
>  arch/arm/mach-snapdragon/of_fixup.c |  4 ++++
>  2 files changed, 14 insertions(+)
> 
> diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
> index 976c0e35fce..6c53aeef597 100644
> --- a/arch/arm/mach-snapdragon/Kconfig
> +++ b/arch/arm/mach-snapdragon/Kconfig
> @@ -29,6 +29,16 @@ config SYS_MALLOC_LEN
>  config LNX_KRNL_IMG_TEXT_OFFSET_BASE
>  	default 0x80000000
>  
> +config QCOM_USB_FIXUP
> +	bool "Enable USB speed fixup for Qualcomm platforms"
> +	default y
> +	help
> +	  Enable runtime fixup of USB device tree nodes to limit USB to
> +	  high-speed mode. This is needed on some Qualcomm platforms where
> +	  U-Boot doesn't support super-speed USB.
> +	  Disable this for platforms that have proper super-speed USB support
> +	  in U-Boot.
> +
>  config SYS_BOARD
>  	string "Snapdragon SoCs based board"
>  	help
> diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c
> index eec2c0c757e..6a64168f67e 100644
> --- a/arch/arm/mach-snapdragon/of_fixup.c
> +++ b/arch/arm/mach-snapdragon/of_fixup.c
> @@ -27,6 +27,7 @@
>  #include <stdlib.h>
>  #include <time.h>
>  
> +#ifdef CONFIG_QCOM_USB_FIXUP
>  /* U-Boot only supports USB high-speed mode on Qualcomm platforms with DWC3
>   * USB controllers. Rather than requiring source level DT changes, we fix up
>   * DT here. This improves compatibility with upstream DT and simplifies the
> @@ -115,6 +116,7 @@ static void fixup_usb_nodes(struct device_node *root)
>  			log_warning("Failed to fixup node %s: %d\n", glue_np->name, ret);
>  	}
>  }
> +#endif
>  
>  /* Remove all references to the rpmhpd device */
>  static void fixup_power_domains(struct device_node *root)
> @@ -157,7 +159,9 @@ static int qcom_of_fixup_nodes(void * __maybe_unused ctx, struct event *event)
>  {
>  	struct device_node *root = event->data.of_live_built.root;
>  
> +#ifdef CONFIG_QCOM_USB_FIXUP
>  	time_call(fixup_usb_nodes, root);
> +#endif
>  	time_call(fixup_power_domains, root);
>  
>  	return 0;

-- 
// Casey (she/her)


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

* Re: [PATCH v2 5/7] arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks
  2025-11-24 15:55 ` [PATCH v2 5/7] arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks Balaji Selvanathan
@ 2025-11-26 14:26   ` Casey Connolly
  2025-12-03 11:36     ` Balaji Selvanathan
  0 siblings, 1 reply; 23+ messages in thread
From: Casey Connolly @ 2025-11-26 14:26 UTC (permalink / raw)
  To: Balaji Selvanathan, trini, neil.armstrong, sumit.garg, lukma,
	seanga2, marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom

Hi Balaji,

On 24/11/2025 16:55, Balaji Selvanathan wrote:
> Override the USB QMP PHY clock properties to use only GCC clocks
> supported in U-Boot, removing the unsupported RPMH_CXO_CLK from
> the qcs6490-rb3gen2's device tree.

That clock should be handled by the stub clock driver, are you seeing an
error without this patch (with CONFIG_CLK_STUB=y)?


> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> ---
>  arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
> index 50674b692ed..14669b50821 100644
> --- a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
> +++ b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
> @@ -22,6 +22,14 @@
>  	/delete-property/ usb-role-switch;
>  };
>  
> +&usb_1_qmpphy {
> +	clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
> +		 <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
> +		 <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
> +	clock-names = "aux",
> +		      "com_aux",
> +		      "usb3_pipe";
> +};
>  // RAM Entry 0 : Base 0x0080000000  Size 0x003A800000
>  // RAM Entry 1 : Base 0x00C0000000  Size 0x0001800000
>  // RAM Entry 2 : Base 0x00C3400000  Size 0x003CC00000

-- 
// Casey (she/her)


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

* Re: [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock
  2025-11-24 15:54 ` [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock Balaji Selvanathan
@ 2025-11-26 14:30   ` Casey Connolly
  2025-12-23  8:31   ` Sumit Garg
  1 sibling, 0 replies; 23+ messages in thread
From: Casey Connolly @ 2025-11-26 14:30 UTC (permalink / raw)
  To: Balaji Selvanathan, trini, neil.armstrong, sumit.garg, lukma,
	seanga2, marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom



On 24/11/2025 16:54, Balaji Selvanathan wrote:
> Add support for GCC_USB3_PRIM_PHY_PIPE_CLK which is required by
> the USB3 PHY on SC7280/QCM6490 platforms.
> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>

Reviewed-by: Casey Connolly <casey.connolly@linaro.org>> ---
>  drivers/clk/qcom/clock-sc7280.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c
> index 55a233df394..a2af73cd976 100644
> --- a/drivers/clk/qcom/clock-sc7280.c
> +++ b/drivers/clk/qcom/clock-sc7280.c
> @@ -111,6 +111,7 @@ static const struct gate_clk sc7280_clks[] = {
>  	GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0xf01c, 1),
>  	GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0xf054, 1),
>  	GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0xf058, 1),
> +	GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0xf05c, 1),
>  	GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x9e07c, 1),
>  	GATE_CLK(GCC_USB30_SEC_MASTER_CLK, 0x9e010, 1),
>  	GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x9e080, 1),

-- 
// Casey (she/her)


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

* Re: [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver
  2025-11-24 15:54 ` [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver Balaji Selvanathan
  2025-11-24 19:51   ` Tom Rini
@ 2025-11-26 14:46   ` Casey Connolly
  2025-11-28  3:31     ` Balaji Selvanathan
  2025-12-03 11:13     ` Balaji Selvanathan
  1 sibling, 2 replies; 23+ messages in thread
From: Casey Connolly @ 2025-11-26 14:46 UTC (permalink / raw)
  To: Balaji Selvanathan, trini, neil.armstrong, sumit.garg, lukma,
	seanga2, marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom

Hi Balaji,

In general this looks great! I'm very excited to have SuperSpeed up and
running in U-Boot at long last :D

I'll try and give this a spin soon on my boards.

On 24/11/2025 16:54, Balaji Selvanathan wrote:
> Add support for the Qualcomm QMP USB3-DP Combo PHY found on
> SC7280 and QCM6490 platforms. This driver currently implements
> USB3 super-speed functionality of the combo PHY.
> 
> The QMP Combo PHY is a dual-mode PHY
> that can operate in either USB3 mode or DisplayPort mode. This
> initial implementation focuses on USB3 mode to enable Super-Speed
> USB support.
> 
> This is a port of the upstream Linux files to U-Boot:
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/qualcomm/phy-qcom-qmp-combo.c?id=3d25d46a255a83f94d7d4d4216f38aafc8e116b0

For future reference, the best format for this is something like:

Taken from Linux commit 3d25d46a255a ("pmdomain: qcom: rpmhpd: Add
rpmhpd support for SM8750")

You can get this with "git top --pretty="%h (\"%s\")" COMMIT_SHA", you
can stick an alias for this in your .gitconfig.

Few more comments below.

> 
> Enabled and tested the driver on Qualcomm RB3 Gen2 (QCS6490) board.
> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> ---
> v2:
> - Added pipe clock disable in qmp_combo_power_off sequence
> - Added all required clocks except pipe clock in qmp_combo_phy_clk_l
> - All clocks except pipe clock are enabled and disabled seperate from pipe clock
> - Added support for regulator power supplies
> - Added a minimal xlate to only return the USB3 phy
> ---
>  drivers/phy/qcom/Kconfig                   |   8 +
>  drivers/phy/qcom/Makefile                  |   1 +
>  drivers/phy/qcom/phy-qcom-qmp-combo.c      | 642 +++++++++++++++++++++
>  drivers/phy/qcom/phy-qcom-qmp-common.h     |  62 ++
>  drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h  |  18 +
>  drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h |  34 ++
>  drivers/phy/qcom/phy-qcom-qmp.h            |  17 +
>  7 files changed, 782 insertions(+)
>  create mode 100644 drivers/phy/qcom/phy-qcom-qmp-combo.c
>  create mode 100644 drivers/phy/qcom/phy-qcom-qmp-common.h
>  create mode 100644 drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
>  create mode 100644 drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h

[snip]

> diff --git a/drivers/phy/qcom/phy-qcom-qmp-combo.c b/drivers/phy/qcom/phy-qcom-qmp-combo.c
> new file mode 100644
> index 00000000000..f5596aa5e50
> --- /dev/null
> +++ b/drivers/phy/qcom/phy-qcom-qmp-combo.c
> @@ -0,0 +1,642 @@

[snip]

> +/* list of clocks required by phy */
> +static const char * const qmp_combo_phy_clk_l[] = {
> +	"aux", "com_aux",
> +};
> +
> +/* list of regulators */
> +static const char * const qmp_phy_vreg_l[] = {
> +	"vdda-phy",
> +	"vdda-pll",

On U-Boot it's necessary to use the full DT property name:
"vdda-phy-supply".

> +};


[..]

> +static int qmp_combo_power_off(struct phy *phy)
> +{
> +	struct qmp_combo *qmp = dev_get_priv(phy->dev);
> +	void __iomem *com = qmp->com;
> +
> +	clk_disable(qmp->pipe_clk);
> +
> +	/* PHY reset */
> +	qphy_setbits(qmp->pcs, QPHY_V4_PCS_SW_RESET, SW_RESET);
> +
> +	/* Stop SerDes and Phy-Coding-Sublayer */
> +	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_START_CONTROL,
> +		     SERDES_START | PCS_START);
> +
> +	/* Put PHY into POWER DOWN state: active low */
> +	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_POWER_DOWN_CONTROL, SW_PWRDN);
> +
> +	/* Power down common block */
> +	qphy_clrbits(com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, SW_PWRDN);

Should we also turn off the regulators here?

> +
> +	return qmp_combo_com_exit(qmp);
> +}

[...]

> +static int qmp_combo_vreg_init(struct qmp_combo *qmp)
> +{
> +	const struct qmp_phy_cfg *cfg = qmp->cfg;
> +	struct udevice *dev = qmp->dev;
> +	int num = cfg->num_vregs;
> +	int i, ret;
> +
> +	if (!num)
> +		return 0;
> +
> +	qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
> +	if (!qmp->vregs)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < num; i++) {
> +		ret = device_get_supply_regulator(dev, cfg->vreg_list[i],
> +						  &qmp->vregs[i]);
> +		if (ret) {
> +			dev_dbg(dev, "regulator %s not found (optional)\n",
> +				cfg->vreg_list[i]);

Are these really optional?

> +			qmp->num_vregs = 0;
> +			return 0;
> +		}
> +	}
> +
> +	qmp->num_vregs = num;
> +	dev_dbg(dev, "found %d regulators\n", num);

Please drop this debug print.

Kind regards,

> +	return 0;
> +}
> +
> +static int qmp_combo_parse_dt(struct qmp_combo *qmp)
> +{
> +	const struct qmp_phy_cfg *cfg = qmp->cfg;
> +	const struct qmp_combo_offsets *offs = cfg->offsets;
> +	struct udevice *dev = qmp->dev;
> +	void __iomem *base;
> +	int ret;
> +
> +	if (!offs)
> +		return -EINVAL;
> +
> +	base = (void __iomem *)dev_read_addr(dev);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	qmp->com = base + offs->com;
> +	qmp->serdes = base + offs->usb3_serdes;
> +	qmp->tx = base + offs->txa;
> +	qmp->rx = base + offs->rxa;
> +	qmp->tx2 = base + offs->txb;
> +	qmp->rx2 = base + offs->rxb;
> +	qmp->pcs = base + offs->usb3_pcs;
> +	qmp->pcs_usb = base + offs->usb3_pcs_usb;
> +	qmp->pcs_misc = base + offs->usb3_pcs_misc;
> +
> +	ret = qmp_combo_clk_init(qmp);
> +	if (ret)
> +		return ret;
> +
> +	qmp->pipe_clk = devm_clk_get(dev, "usb3_pipe");
> +	if (IS_ERR(qmp->pipe_clk)) {
> +		dev_err(dev, "failed to get pipe clock (%ld)\n",
> +			PTR_ERR(qmp->pipe_clk));
> +		return ret;
> +	}
> +
> +	ret = qmp_combo_reset_init(qmp);
> +	if (ret)
> +		return ret;
> +
> +	ret = qmp_combo_vreg_init(qmp);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int qmp_combo_probe(struct udevice *dev)
> +{
> +	struct qmp_combo *qmp = dev_get_priv(dev);
> +	int ret;
> +
> +	qmp->dev = dev;
> +	qmp->cfg = (const struct qmp_phy_cfg *)dev_get_driver_data(dev);
> +	if (!qmp->cfg) {
> +		printf("Failed to get PHY configuration\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = qmp_combo_parse_dt(qmp);
> +
> +	return ret;
> +}
> +
> +static const struct qmp_phy_cfg sc7280_usb3dpphy_cfg = {
> +	.offsets		= &qmp_combo_offsets_v3,
> +	.serdes_tbl		= sm8150_usb3_serdes_tbl,
> +	.serdes_tbl_num		= ARRAY_SIZE(sm8150_usb3_serdes_tbl),
> +	.tx_tbl			= sm8250_usb3_tx_tbl,
> +	.tx_tbl_num		= ARRAY_SIZE(sm8250_usb3_tx_tbl),
> +	.rx_tbl			= sm8250_usb3_rx_tbl,
> +	.rx_tbl_num		= ARRAY_SIZE(sm8250_usb3_rx_tbl),
> +	.pcs_tbl		= sm8250_usb3_pcs_tbl,
> +	.pcs_tbl_num		= ARRAY_SIZE(sm8250_usb3_pcs_tbl),
> +	.pcs_usb_tbl		= sm8250_usb3_pcs_usb_tbl,
> +	.pcs_usb_tbl_num	= ARRAY_SIZE(sm8250_usb3_pcs_usb_tbl),
> +	.vreg_list		= qmp_phy_vreg_l,
> +	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
> +
> +	.has_pwrdn_delay	= true,
> +};
> +
> +static int qmp_combo_xlate(struct phy *phy, struct ofnode_phandle_args *args)
> +{
> +	if (args->args_count != 1) {
> +		debug("Invalid args_count: %d\n", args->args_count);
> +		return -EINVAL;
> +	}
> +
> +	/* We only support the USB3 phy at slot 0 */
> +	if (args->args[0] == QMP_USB43DP_DP_PHY)
> +		return -EINVAL;
> +
> +	phy->id = QMP_USB43DP_USB3_PHY;
> +
> +	return 0;
> +}
> +
> +static struct phy_ops qmp_combo_ops = {
> +	.init = qmp_combo_power_on,
> +	.exit = qmp_combo_power_off,
> +	.of_xlate = qmp_combo_xlate,
> +};
> +
> +static const struct udevice_id qmp_combo_ids[] = {
> +	{
> +		.compatible = "qcom,sc7280-qmp-usb3-dp-phy",
> +		.data = (ulong)&sc7280_usb3dpphy_cfg,
> +	},
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(qmp_combo) = {
> +	.name = "qcom-qmp-usb3-dp-phy",
> +	.id = UCLASS_PHY,
> +	.of_match = qmp_combo_ids,
> +	.ops = &qmp_combo_ops,
> +	.probe = qmp_combo_probe,
> +	.priv_auto = sizeof(struct qmp_combo),
> +};
> diff --git a/drivers/phy/qcom/phy-qcom-qmp-common.h b/drivers/phy/qcom/phy-qcom-qmp-common.h
> new file mode 100644
> index 00000000000..71356fb7dd0
> --- /dev/null
> +++ b/drivers/phy/qcom/phy-qcom-qmp-common.h
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
> + */
> +
> +#ifndef QCOM_PHY_QMP_COMMON_H_
> +#define QCOM_PHY_QMP_COMMON_H_
> +
> +struct qmp_phy_init_tbl {
> +	unsigned int offset;
> +	unsigned int val;
> +	char *name;
> +	/*
> +	 * mask of lanes for which this register is written
> +	 * for cases when second lane needs different values
> +	 */
> +	u8 lane_mask;
> +};
> +
> +#define QMP_PHY_INIT_CFG(o, v)		\
> +	{				\
> +		.offset = o,		\
> +		.val = v,		\
> +		.name = #o,		\
> +		.lane_mask = 0xff,	\
> +	}
> +
> +#define QMP_PHY_INIT_CFG_LANE(o, v, l)	\
> +	{				\
> +		.offset = o,		\
> +		.val = v,		\
> +		.name = #o,		\
> +		.lane_mask = l,		\
> +	}
> +
> +static inline void qmp_configure_lane(struct udevice *dev, void __iomem *base,
> +				      const struct qmp_phy_init_tbl tbl[],
> +				      int num, u8 lane_mask)
> +{
> +	int i;
> +	const struct qmp_phy_init_tbl *t = tbl;
> +
> +	if (!t)
> +		return;
> +
> +	for (i = 0; i < num; i++, t++) {
> +		if (!(t->lane_mask & lane_mask))
> +			continue;
> +
> +		dev_dbg(dev, "Writing Reg: %s Offset: 0x%04x Val: 0x%02x\n",
> +			t->name, t->offset, t->val);
> +		writel(t->val, base + t->offset);
> +	}
> +}
> +
> +static inline void qmp_configure(struct udevice *dev, void __iomem *base,
> +				 const struct qmp_phy_init_tbl tbl[], int num)
> +{
> +	qmp_configure_lane(dev, base, tbl, num, 0xff);
> +}
> +
> +#endif
> diff --git a/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
> new file mode 100644
> index 00000000000..396179ef38b
> --- /dev/null
> +++ b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
> + */
> +
> +#ifndef QCOM_PHY_QMP_DP_COM_V3_H_
> +#define QCOM_PHY_QMP_DP_COM_V3_H_
> +
> +/* Only for QMP V3 & V4 PHY - DP COM registers */
> +#define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
> +#define QPHY_V3_DP_COM_SW_RESET				0x04
> +#define QPHY_V3_DP_COM_POWER_DOWN_CTRL			0x08
> +#define QPHY_V3_DP_COM_SWI_CTRL				0x0c
> +#define QPHY_V3_DP_COM_TYPEC_CTRL			0x10
> +#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL			0x14
> +#define QPHY_V3_DP_COM_RESET_OVRD_CTRL			0x1c
> +
> +#endif
> diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
> new file mode 100644
> index 00000000000..d7fd4ac0fc5
> --- /dev/null
> +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
> @@ -0,0 +1,34 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
> + */
> +
> +#ifndef QCOM_PHY_QMP_PCS_USB_V4_H_
> +#define QCOM_PHY_QMP_PCS_USB_V4_H_
> +
> +/* Only for QMP V4 PHY - USB3 PCS registers */
> +#define QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1		0x000
> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_STATUS		0x004
> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL		0x008
> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL2		0x00c
> +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_SOURCE_STATUS	0x010
> +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR		0x014
> +#define QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL	0x018
> +#define QPHY_V4_PCS_USB3_LFPS_TX_ECSTART		0x01c
> +#define QPHY_V4_PCS_USB3_LFPS_PER_TIMER_VAL		0x020
> +#define QPHY_V4_PCS_USB3_LFPS_TX_END_CNT_U3_START	0x024
> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_LOCK_TIME		0x028
> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME		0x02c
> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_CTLE_TIME		0x030
> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME_S2	0x034
> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2	0x038
> +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_L		0x03c
> +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_H		0x040
> +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_EN_PERIOD		0x044
> +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_CM_DLY		0x048
> +#define QPHY_V4_PCS_USB3_TXONESZEROS_RUN_LENGTH		0x04c
> +#define QPHY_V4_PCS_USB3_ALFPS_DEGLITCH_VAL		0x050
> +#define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL	0x054
> +#define QPHY_V4_PCS_USB3_TEST_CONTROL			0x058
> +
> +#endif
> diff --git a/drivers/phy/qcom/phy-qcom-qmp.h b/drivers/phy/qcom/phy-qcom-qmp.h
> index 99f4d447caf..06dac21ddc4 100644
> --- a/drivers/phy/qcom/phy-qcom-qmp.h
> +++ b/drivers/phy/qcom/phy-qcom-qmp.h
> @@ -12,12 +12,17 @@
>  #include "phy-qcom-qmp-qserdes-com-v3.h"
>  #include "phy-qcom-qmp-qserdes-txrx-v3.h"
>  
> +#include "phy-qcom-qmp-qserdes-com-v4.h"
> +#include "phy-qcom-qmp-qserdes-txrx-v4.h"
> +
>  #include "phy-qcom-qmp-qserdes-pll.h"
>  
>  #include "phy-qcom-qmp-pcs-v2.h"
>  
>  #include "phy-qcom-qmp-pcs-v3.h"
>  
> +#include "phy-qcom-qmp-pcs-v4.h"
> +
>  /* Only for QMP V3 & V4 PHY - DP COM registers */
>  #define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
>  #define QPHY_V3_DP_COM_SW_RESET				0x04
> @@ -112,4 +117,16 @@
>  #define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS		0x0e0
>  #define QSERDES_V6_DP_PHY_STATUS			0x0e4
>  
> +/* QPHY_SW_RESET bit */
> +#define SW_RESET                                BIT(0)
> +/* QPHY_POWER_DOWN_CONTROL */
> +#define SW_PWRDN                                BIT(0)
> +
> +/* QPHY_START_CONTROL bits */
> +#define SERDES_START                            BIT(0)
> +#define PCS_START                               BIT(1)
> +
> +/* QPHY_PCS_STATUS bit */
> +#define PHYSTATUS                               BIT(6)
> +
>  #endif

-- 
// Casey (she/her)


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

* Re: [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver
  2025-11-26 14:46   ` Casey Connolly
@ 2025-11-28  3:31     ` Balaji Selvanathan
  2025-12-03 11:13     ` Balaji Selvanathan
  1 sibling, 0 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-11-28  3:31 UTC (permalink / raw)
  To: Casey Connolly, trini, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom

Hi Casey,

Thanks for your valuable feedback. Will address your comments and do a 
respin soon.

Thanks,

Balaji

On 11/26/2025 8:16 PM, Casey Connolly wrote:
> Hi Balaji,
>
> In general this looks great! I'm very excited to have SuperSpeed up and
> running in U-Boot at long last :D
>
> I'll try and give this a spin soon on my boards.
>
> On 24/11/2025 16:54, Balaji Selvanathan wrote:
>> Add support for the Qualcomm QMP USB3-DP Combo PHY found on
>> SC7280 and QCM6490 platforms. This driver currently implements
>> USB3 super-speed functionality of the combo PHY.
>>
>> The QMP Combo PHY is a dual-mode PHY
>> that can operate in either USB3 mode or DisplayPort mode. This
>> initial implementation focuses on USB3 mode to enable Super-Speed
>> USB support.
>>
>> This is a port of the upstream Linux files to U-Boot:
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/qualcomm/phy-qcom-qmp-combo.c?id=3d25d46a255a83f94d7d4d4216f38aafc8e116b0
> For future reference, the best format for this is something like:
>
> Taken from Linux commit 3d25d46a255a ("pmdomain: qcom: rpmhpd: Add
> rpmhpd support for SM8750")
>
> You can get this with "git top --pretty="%h (\"%s\")" COMMIT_SHA", you
> can stick an alias for this in your .gitconfig.
>
> Few more comments below.
>
>> Enabled and tested the driver on Qualcomm RB3 Gen2 (QCS6490) board.
>>
>> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
>> ---
>> v2:
>> - Added pipe clock disable in qmp_combo_power_off sequence
>> - Added all required clocks except pipe clock in qmp_combo_phy_clk_l
>> - All clocks except pipe clock are enabled and disabled seperate from pipe clock
>> - Added support for regulator power supplies
>> - Added a minimal xlate to only return the USB3 phy
>> ---
>>   drivers/phy/qcom/Kconfig                   |   8 +
>>   drivers/phy/qcom/Makefile                  |   1 +
>>   drivers/phy/qcom/phy-qcom-qmp-combo.c      | 642 +++++++++++++++++++++
>>   drivers/phy/qcom/phy-qcom-qmp-common.h     |  62 ++
>>   drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h  |  18 +
>>   drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h |  34 ++
>>   drivers/phy/qcom/phy-qcom-qmp.h            |  17 +
>>   7 files changed, 782 insertions(+)
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-combo.c
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-common.h
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
> [snip]
>
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-combo.c b/drivers/phy/qcom/phy-qcom-qmp-combo.c
>> new file mode 100644
>> index 00000000000..f5596aa5e50
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-combo.c
>> @@ -0,0 +1,642 @@
> [snip]
>
>> +/* list of clocks required by phy */
>> +static const char * const qmp_combo_phy_clk_l[] = {
>> +	"aux", "com_aux",
>> +};
>> +
>> +/* list of regulators */
>> +static const char * const qmp_phy_vreg_l[] = {
>> +	"vdda-phy",
>> +	"vdda-pll",
> On U-Boot it's necessary to use the full DT property name:
> "vdda-phy-supply".
>
>> +};
>
> [..]
>
>> +static int qmp_combo_power_off(struct phy *phy)
>> +{
>> +	struct qmp_combo *qmp = dev_get_priv(phy->dev);
>> +	void __iomem *com = qmp->com;
>> +
>> +	clk_disable(qmp->pipe_clk);
>> +
>> +	/* PHY reset */
>> +	qphy_setbits(qmp->pcs, QPHY_V4_PCS_SW_RESET, SW_RESET);
>> +
>> +	/* Stop SerDes and Phy-Coding-Sublayer */
>> +	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_START_CONTROL,
>> +		     SERDES_START | PCS_START);
>> +
>> +	/* Put PHY into POWER DOWN state: active low */
>> +	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_POWER_DOWN_CONTROL, SW_PWRDN);
>> +
>> +	/* Power down common block */
>> +	qphy_clrbits(com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, SW_PWRDN);
> Should we also turn off the regulators here?
>
>> +
>> +	return qmp_combo_com_exit(qmp);
>> +}
> [...]
>
>> +static int qmp_combo_vreg_init(struct qmp_combo *qmp)
>> +{
>> +	const struct qmp_phy_cfg *cfg = qmp->cfg;
>> +	struct udevice *dev = qmp->dev;
>> +	int num = cfg->num_vregs;
>> +	int i, ret;
>> +
>> +	if (!num)
>> +		return 0;
>> +
>> +	qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
>> +	if (!qmp->vregs)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0; i < num; i++) {
>> +		ret = device_get_supply_regulator(dev, cfg->vreg_list[i],
>> +						  &qmp->vregs[i]);
>> +		if (ret) {
>> +			dev_dbg(dev, "regulator %s not found (optional)\n",
>> +				cfg->vreg_list[i]);
> Are these really optional?
>
>> +			qmp->num_vregs = 0;
>> +			return 0;
>> +		}
>> +	}
>> +
>> +	qmp->num_vregs = num;
>> +	dev_dbg(dev, "found %d regulators\n", num);
> Please drop this debug print.
>
> Kind regards,
>
>> +	return 0;
>> +}
>> +
>> +static int qmp_combo_parse_dt(struct qmp_combo *qmp)
>> +{
>> +	const struct qmp_phy_cfg *cfg = qmp->cfg;
>> +	const struct qmp_combo_offsets *offs = cfg->offsets;
>> +	struct udevice *dev = qmp->dev;
>> +	void __iomem *base;
>> +	int ret;
>> +
>> +	if (!offs)
>> +		return -EINVAL;
>> +
>> +	base = (void __iomem *)dev_read_addr(dev);
>> +	if (IS_ERR(base))
>> +		return PTR_ERR(base);
>> +
>> +	qmp->com = base + offs->com;
>> +	qmp->serdes = base + offs->usb3_serdes;
>> +	qmp->tx = base + offs->txa;
>> +	qmp->rx = base + offs->rxa;
>> +	qmp->tx2 = base + offs->txb;
>> +	qmp->rx2 = base + offs->rxb;
>> +	qmp->pcs = base + offs->usb3_pcs;
>> +	qmp->pcs_usb = base + offs->usb3_pcs_usb;
>> +	qmp->pcs_misc = base + offs->usb3_pcs_misc;
>> +
>> +	ret = qmp_combo_clk_init(qmp);
>> +	if (ret)
>> +		return ret;
>> +
>> +	qmp->pipe_clk = devm_clk_get(dev, "usb3_pipe");
>> +	if (IS_ERR(qmp->pipe_clk)) {
>> +		dev_err(dev, "failed to get pipe clock (%ld)\n",
>> +			PTR_ERR(qmp->pipe_clk));
>> +		return ret;
>> +	}
>> +
>> +	ret = qmp_combo_reset_init(qmp);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = qmp_combo_vreg_init(qmp);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int qmp_combo_probe(struct udevice *dev)
>> +{
>> +	struct qmp_combo *qmp = dev_get_priv(dev);
>> +	int ret;
>> +
>> +	qmp->dev = dev;
>> +	qmp->cfg = (const struct qmp_phy_cfg *)dev_get_driver_data(dev);
>> +	if (!qmp->cfg) {
>> +		printf("Failed to get PHY configuration\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = qmp_combo_parse_dt(qmp);
>> +
>> +	return ret;
>> +}
>> +
>> +static const struct qmp_phy_cfg sc7280_usb3dpphy_cfg = {
>> +	.offsets		= &qmp_combo_offsets_v3,
>> +	.serdes_tbl		= sm8150_usb3_serdes_tbl,
>> +	.serdes_tbl_num		= ARRAY_SIZE(sm8150_usb3_serdes_tbl),
>> +	.tx_tbl			= sm8250_usb3_tx_tbl,
>> +	.tx_tbl_num		= ARRAY_SIZE(sm8250_usb3_tx_tbl),
>> +	.rx_tbl			= sm8250_usb3_rx_tbl,
>> +	.rx_tbl_num		= ARRAY_SIZE(sm8250_usb3_rx_tbl),
>> +	.pcs_tbl		= sm8250_usb3_pcs_tbl,
>> +	.pcs_tbl_num		= ARRAY_SIZE(sm8250_usb3_pcs_tbl),
>> +	.pcs_usb_tbl		= sm8250_usb3_pcs_usb_tbl,
>> +	.pcs_usb_tbl_num	= ARRAY_SIZE(sm8250_usb3_pcs_usb_tbl),
>> +	.vreg_list		= qmp_phy_vreg_l,
>> +	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
>> +
>> +	.has_pwrdn_delay	= true,
>> +};
>> +
>> +static int qmp_combo_xlate(struct phy *phy, struct ofnode_phandle_args *args)
>> +{
>> +	if (args->args_count != 1) {
>> +		debug("Invalid args_count: %d\n", args->args_count);
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* We only support the USB3 phy at slot 0 */
>> +	if (args->args[0] == QMP_USB43DP_DP_PHY)
>> +		return -EINVAL;
>> +
>> +	phy->id = QMP_USB43DP_USB3_PHY;
>> +
>> +	return 0;
>> +}
>> +
>> +static struct phy_ops qmp_combo_ops = {
>> +	.init = qmp_combo_power_on,
>> +	.exit = qmp_combo_power_off,
>> +	.of_xlate = qmp_combo_xlate,
>> +};
>> +
>> +static const struct udevice_id qmp_combo_ids[] = {
>> +	{
>> +		.compatible = "qcom,sc7280-qmp-usb3-dp-phy",
>> +		.data = (ulong)&sc7280_usb3dpphy_cfg,
>> +	},
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(qmp_combo) = {
>> +	.name = "qcom-qmp-usb3-dp-phy",
>> +	.id = UCLASS_PHY,
>> +	.of_match = qmp_combo_ids,
>> +	.ops = &qmp_combo_ops,
>> +	.probe = qmp_combo_probe,
>> +	.priv_auto = sizeof(struct qmp_combo),
>> +};
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-common.h b/drivers/phy/qcom/phy-qcom-qmp-common.h
>> new file mode 100644
>> index 00000000000..71356fb7dd0
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-common.h
>> @@ -0,0 +1,62 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef QCOM_PHY_QMP_COMMON_H_
>> +#define QCOM_PHY_QMP_COMMON_H_
>> +
>> +struct qmp_phy_init_tbl {
>> +	unsigned int offset;
>> +	unsigned int val;
>> +	char *name;
>> +	/*
>> +	 * mask of lanes for which this register is written
>> +	 * for cases when second lane needs different values
>> +	 */
>> +	u8 lane_mask;
>> +};
>> +
>> +#define QMP_PHY_INIT_CFG(o, v)		\
>> +	{				\
>> +		.offset = o,		\
>> +		.val = v,		\
>> +		.name = #o,		\
>> +		.lane_mask = 0xff,	\
>> +	}
>> +
>> +#define QMP_PHY_INIT_CFG_LANE(o, v, l)	\
>> +	{				\
>> +		.offset = o,		\
>> +		.val = v,		\
>> +		.name = #o,		\
>> +		.lane_mask = l,		\
>> +	}
>> +
>> +static inline void qmp_configure_lane(struct udevice *dev, void __iomem *base,
>> +				      const struct qmp_phy_init_tbl tbl[],
>> +				      int num, u8 lane_mask)
>> +{
>> +	int i;
>> +	const struct qmp_phy_init_tbl *t = tbl;
>> +
>> +	if (!t)
>> +		return;
>> +
>> +	for (i = 0; i < num; i++, t++) {
>> +		if (!(t->lane_mask & lane_mask))
>> +			continue;
>> +
>> +		dev_dbg(dev, "Writing Reg: %s Offset: 0x%04x Val: 0x%02x\n",
>> +			t->name, t->offset, t->val);
>> +		writel(t->val, base + t->offset);
>> +	}
>> +}
>> +
>> +static inline void qmp_configure(struct udevice *dev, void __iomem *base,
>> +				 const struct qmp_phy_init_tbl tbl[], int num)
>> +{
>> +	qmp_configure_lane(dev, base, tbl, num, 0xff);
>> +}
>> +
>> +#endif
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
>> new file mode 100644
>> index 00000000000..396179ef38b
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
>> @@ -0,0 +1,18 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef QCOM_PHY_QMP_DP_COM_V3_H_
>> +#define QCOM_PHY_QMP_DP_COM_V3_H_
>> +
>> +/* Only for QMP V3 & V4 PHY - DP COM registers */
>> +#define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
>> +#define QPHY_V3_DP_COM_SW_RESET				0x04
>> +#define QPHY_V3_DP_COM_POWER_DOWN_CTRL			0x08
>> +#define QPHY_V3_DP_COM_SWI_CTRL				0x0c
>> +#define QPHY_V3_DP_COM_TYPEC_CTRL			0x10
>> +#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL			0x14
>> +#define QPHY_V3_DP_COM_RESET_OVRD_CTRL			0x1c
>> +
>> +#endif
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
>> new file mode 100644
>> index 00000000000..d7fd4ac0fc5
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
>> @@ -0,0 +1,34 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef QCOM_PHY_QMP_PCS_USB_V4_H_
>> +#define QCOM_PHY_QMP_PCS_USB_V4_H_
>> +
>> +/* Only for QMP V4 PHY - USB3 PCS registers */
>> +#define QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1		0x000
>> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_STATUS		0x004
>> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL		0x008
>> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL2		0x00c
>> +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_SOURCE_STATUS	0x010
>> +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR		0x014
>> +#define QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL	0x018
>> +#define QPHY_V4_PCS_USB3_LFPS_TX_ECSTART		0x01c
>> +#define QPHY_V4_PCS_USB3_LFPS_PER_TIMER_VAL		0x020
>> +#define QPHY_V4_PCS_USB3_LFPS_TX_END_CNT_U3_START	0x024
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_LOCK_TIME		0x028
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME		0x02c
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_CTLE_TIME		0x030
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME_S2	0x034
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2	0x038
>> +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_L		0x03c
>> +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_H		0x040
>> +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_EN_PERIOD		0x044
>> +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_CM_DLY		0x048
>> +#define QPHY_V4_PCS_USB3_TXONESZEROS_RUN_LENGTH		0x04c
>> +#define QPHY_V4_PCS_USB3_ALFPS_DEGLITCH_VAL		0x050
>> +#define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL	0x054
>> +#define QPHY_V4_PCS_USB3_TEST_CONTROL			0x058
>> +
>> +#endif
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp.h b/drivers/phy/qcom/phy-qcom-qmp.h
>> index 99f4d447caf..06dac21ddc4 100644
>> --- a/drivers/phy/qcom/phy-qcom-qmp.h
>> +++ b/drivers/phy/qcom/phy-qcom-qmp.h
>> @@ -12,12 +12,17 @@
>>   #include "phy-qcom-qmp-qserdes-com-v3.h"
>>   #include "phy-qcom-qmp-qserdes-txrx-v3.h"
>>   
>> +#include "phy-qcom-qmp-qserdes-com-v4.h"
>> +#include "phy-qcom-qmp-qserdes-txrx-v4.h"
>> +
>>   #include "phy-qcom-qmp-qserdes-pll.h"
>>   
>>   #include "phy-qcom-qmp-pcs-v2.h"
>>   
>>   #include "phy-qcom-qmp-pcs-v3.h"
>>   
>> +#include "phy-qcom-qmp-pcs-v4.h"
>> +
>>   /* Only for QMP V3 & V4 PHY - DP COM registers */
>>   #define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
>>   #define QPHY_V3_DP_COM_SW_RESET				0x04
>> @@ -112,4 +117,16 @@
>>   #define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS		0x0e0
>>   #define QSERDES_V6_DP_PHY_STATUS			0x0e4
>>   
>> +/* QPHY_SW_RESET bit */
>> +#define SW_RESET                                BIT(0)
>> +/* QPHY_POWER_DOWN_CONTROL */
>> +#define SW_PWRDN                                BIT(0)
>> +
>> +/* QPHY_START_CONTROL bits */
>> +#define SERDES_START                            BIT(0)
>> +#define PCS_START                               BIT(1)
>> +
>> +/* QPHY_PCS_STATUS bit */
>> +#define PHYSTATUS                               BIT(6)
>> +
>>   #endif

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

* Re: [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver
  2025-11-26 14:46   ` Casey Connolly
  2025-11-28  3:31     ` Balaji Selvanathan
@ 2025-12-03 11:13     ` Balaji Selvanathan
  1 sibling, 0 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-12-03 11:13 UTC (permalink / raw)
  To: Casey Connolly, trini, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom

Hi Casey,

Thanks for your feedback.

Have addressed all your comments in this respin: 
https://lore.kernel.org/u-boot/20251203110735.1959862-1-balaji.selvanathan@oss.qualcomm.com/. 
Request to check if this version is okay.

Please find reply to your comments below.

Thanks,

Balaji

On 11/26/2025 8:16 PM, Casey Connolly wrote:
> Hi Balaji,
>
> In general this looks great! I'm very excited to have SuperSpeed up and
> running in U-Boot at long last :D
>
> I'll try and give this a spin soon on my boards.
>
> On 24/11/2025 16:54, Balaji Selvanathan wrote:
>> Add support for the Qualcomm QMP USB3-DP Combo PHY found on
>> SC7280 and QCM6490 platforms. This driver currently implements
>> USB3 super-speed functionality of the combo PHY.
>>
>> The QMP Combo PHY is a dual-mode PHY
>> that can operate in either USB3 mode or DisplayPort mode. This
>> initial implementation focuses on USB3 mode to enable Super-Speed
>> USB support.
>>
>> This is a port of the upstream Linux files to U-Boot:
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/phy/qualcomm/phy-qcom-qmp-combo.c?id=3d25d46a255a83f94d7d4d4216f38aafc8e116b0
> For future reference, the best format for this is something like:
>
> Taken from Linux commit 3d25d46a255a ("pmdomain: qcom: rpmhpd: Add
> rpmhpd support for SM8750")
>
> You can get this with "git top --pretty="%h (\"%s\")" COMMIT_SHA", you
> can stick an alias for this in your .gitconfig.
>
> Few more comments below.
Have corrected this.
>
>> Enabled and tested the driver on Qualcomm RB3 Gen2 (QCS6490) board.
>>
>> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
>> ---
>> v2:
>> - Added pipe clock disable in qmp_combo_power_off sequence
>> - Added all required clocks except pipe clock in qmp_combo_phy_clk_l
>> - All clocks except pipe clock are enabled and disabled seperate from pipe clock
>> - Added support for regulator power supplies
>> - Added a minimal xlate to only return the USB3 phy
>> ---
>>   drivers/phy/qcom/Kconfig                   |   8 +
>>   drivers/phy/qcom/Makefile                  |   1 +
>>   drivers/phy/qcom/phy-qcom-qmp-combo.c      | 642 +++++++++++++++++++++
>>   drivers/phy/qcom/phy-qcom-qmp-common.h     |  62 ++
>>   drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h  |  18 +
>>   drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h |  34 ++
>>   drivers/phy/qcom/phy-qcom-qmp.h            |  17 +
>>   7 files changed, 782 insertions(+)
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-combo.c
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-common.h
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
>>   create mode 100644 drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
> [snip]
>
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-combo.c b/drivers/phy/qcom/phy-qcom-qmp-combo.c
>> new file mode 100644
>> index 00000000000..f5596aa5e50
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-combo.c
>> @@ -0,0 +1,642 @@
> [snip]
>
>> +/* list of clocks required by phy */
>> +static const char * const qmp_combo_phy_clk_l[] = {
>> +	"aux", "com_aux",
>> +};
>> +
>> +/* list of regulators */
>> +static const char * const qmp_phy_vreg_l[] = {
>> +	"vdda-phy",
>> +	"vdda-pll",
> On U-Boot it's necessary to use the full DT property name:
> "vdda-phy-supply".
Updated to full DT name.
>
>> +};
>
> [..]
>
>> +static int qmp_combo_power_off(struct phy *phy)
>> +{
>> +	struct qmp_combo *qmp = dev_get_priv(phy->dev);
>> +	void __iomem *com = qmp->com;
>> +
>> +	clk_disable(qmp->pipe_clk);
>> +
>> +	/* PHY reset */
>> +	qphy_setbits(qmp->pcs, QPHY_V4_PCS_SW_RESET, SW_RESET);
>> +
>> +	/* Stop SerDes and Phy-Coding-Sublayer */
>> +	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_START_CONTROL,
>> +		     SERDES_START | PCS_START);
>> +
>> +	/* Put PHY into POWER DOWN state: active low */
>> +	qphy_clrbits(qmp->pcs, QPHY_V4_PCS_POWER_DOWN_CONTROL, SW_PWRDN);
>> +
>> +	/* Power down common block */
>> +	qphy_clrbits(com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, SW_PWRDN);
> Should we also turn off the regulators here?
Turning off regulators is happening in qmp_combo_com_exit.
>
>> +
>> +	return qmp_combo_com_exit(qmp);
>> +}
> [...]
>
>> +static int qmp_combo_vreg_init(struct qmp_combo *qmp)
>> +{
>> +	const struct qmp_phy_cfg *cfg = qmp->cfg;
>> +	struct udevice *dev = qmp->dev;
>> +	int num = cfg->num_vregs;
>> +	int i, ret;
>> +
>> +	if (!num)
>> +		return 0;
>> +
>> +	qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
>> +	if (!qmp->vregs)
>> +		return -ENOMEM;
>> +
>> +	for (i = 0; i < num; i++) {
>> +		ret = device_get_supply_regulator(dev, cfg->vreg_list[i],
>> +						  &qmp->vregs[i]);
>> +		if (ret) {
>> +			dev_dbg(dev, "regulator %s not found (optional)\n",
>> +				cfg->vreg_list[i]);
> Are these really optional?
You are right. They shouldnt be optional. Made them mandatory now, else 
probe fails.
>
>> +			qmp->num_vregs = 0;
>> +			return 0;
>> +		}
>> +	}
>> +
>> +	qmp->num_vregs = num;
>> +	dev_dbg(dev, "found %d regulators\n", num);
> Please drop this debug print.
Dropped.
>
> Kind regards,
>
>> +	return 0;
>> +}
>> +
>> +static int qmp_combo_parse_dt(struct qmp_combo *qmp)
>> +{
>> +	const struct qmp_phy_cfg *cfg = qmp->cfg;
>> +	const struct qmp_combo_offsets *offs = cfg->offsets;
>> +	struct udevice *dev = qmp->dev;
>> +	void __iomem *base;
>> +	int ret;
>> +
>> +	if (!offs)
>> +		return -EINVAL;
>> +
>> +	base = (void __iomem *)dev_read_addr(dev);
>> +	if (IS_ERR(base))
>> +		return PTR_ERR(base);
>> +
>> +	qmp->com = base + offs->com;
>> +	qmp->serdes = base + offs->usb3_serdes;
>> +	qmp->tx = base + offs->txa;
>> +	qmp->rx = base + offs->rxa;
>> +	qmp->tx2 = base + offs->txb;
>> +	qmp->rx2 = base + offs->rxb;
>> +	qmp->pcs = base + offs->usb3_pcs;
>> +	qmp->pcs_usb = base + offs->usb3_pcs_usb;
>> +	qmp->pcs_misc = base + offs->usb3_pcs_misc;
>> +
>> +	ret = qmp_combo_clk_init(qmp);
>> +	if (ret)
>> +		return ret;
>> +
>> +	qmp->pipe_clk = devm_clk_get(dev, "usb3_pipe");
>> +	if (IS_ERR(qmp->pipe_clk)) {
>> +		dev_err(dev, "failed to get pipe clock (%ld)\n",
>> +			PTR_ERR(qmp->pipe_clk));
>> +		return ret;
>> +	}
>> +
>> +	ret = qmp_combo_reset_init(qmp);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = qmp_combo_vreg_init(qmp);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int qmp_combo_probe(struct udevice *dev)
>> +{
>> +	struct qmp_combo *qmp = dev_get_priv(dev);
>> +	int ret;
>> +
>> +	qmp->dev = dev;
>> +	qmp->cfg = (const struct qmp_phy_cfg *)dev_get_driver_data(dev);
>> +	if (!qmp->cfg) {
>> +		printf("Failed to get PHY configuration\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = qmp_combo_parse_dt(qmp);
>> +
>> +	return ret;
>> +}
>> +
>> +static const struct qmp_phy_cfg sc7280_usb3dpphy_cfg = {
>> +	.offsets		= &qmp_combo_offsets_v3,
>> +	.serdes_tbl		= sm8150_usb3_serdes_tbl,
>> +	.serdes_tbl_num		= ARRAY_SIZE(sm8150_usb3_serdes_tbl),
>> +	.tx_tbl			= sm8250_usb3_tx_tbl,
>> +	.tx_tbl_num		= ARRAY_SIZE(sm8250_usb3_tx_tbl),
>> +	.rx_tbl			= sm8250_usb3_rx_tbl,
>> +	.rx_tbl_num		= ARRAY_SIZE(sm8250_usb3_rx_tbl),
>> +	.pcs_tbl		= sm8250_usb3_pcs_tbl,
>> +	.pcs_tbl_num		= ARRAY_SIZE(sm8250_usb3_pcs_tbl),
>> +	.pcs_usb_tbl		= sm8250_usb3_pcs_usb_tbl,
>> +	.pcs_usb_tbl_num	= ARRAY_SIZE(sm8250_usb3_pcs_usb_tbl),
>> +	.vreg_list		= qmp_phy_vreg_l,
>> +	.num_vregs		= ARRAY_SIZE(qmp_phy_vreg_l),
>> +
>> +	.has_pwrdn_delay	= true,
>> +};
>> +
>> +static int qmp_combo_xlate(struct phy *phy, struct ofnode_phandle_args *args)
>> +{
>> +	if (args->args_count != 1) {
>> +		debug("Invalid args_count: %d\n", args->args_count);
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* We only support the USB3 phy at slot 0 */
>> +	if (args->args[0] == QMP_USB43DP_DP_PHY)
>> +		return -EINVAL;
>> +
>> +	phy->id = QMP_USB43DP_USB3_PHY;
>> +
>> +	return 0;
>> +}
>> +
>> +static struct phy_ops qmp_combo_ops = {
>> +	.init = qmp_combo_power_on,
>> +	.exit = qmp_combo_power_off,
>> +	.of_xlate = qmp_combo_xlate,
>> +};
>> +
>> +static const struct udevice_id qmp_combo_ids[] = {
>> +	{
>> +		.compatible = "qcom,sc7280-qmp-usb3-dp-phy",
>> +		.data = (ulong)&sc7280_usb3dpphy_cfg,
>> +	},
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(qmp_combo) = {
>> +	.name = "qcom-qmp-usb3-dp-phy",
>> +	.id = UCLASS_PHY,
>> +	.of_match = qmp_combo_ids,
>> +	.ops = &qmp_combo_ops,
>> +	.probe = qmp_combo_probe,
>> +	.priv_auto = sizeof(struct qmp_combo),
>> +};
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-common.h b/drivers/phy/qcom/phy-qcom-qmp-common.h
>> new file mode 100644
>> index 00000000000..71356fb7dd0
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-common.h
>> @@ -0,0 +1,62 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef QCOM_PHY_QMP_COMMON_H_
>> +#define QCOM_PHY_QMP_COMMON_H_
>> +
>> +struct qmp_phy_init_tbl {
>> +	unsigned int offset;
>> +	unsigned int val;
>> +	char *name;
>> +	/*
>> +	 * mask of lanes for which this register is written
>> +	 * for cases when second lane needs different values
>> +	 */
>> +	u8 lane_mask;
>> +};
>> +
>> +#define QMP_PHY_INIT_CFG(o, v)		\
>> +	{				\
>> +		.offset = o,		\
>> +		.val = v,		\
>> +		.name = #o,		\
>> +		.lane_mask = 0xff,	\
>> +	}
>> +
>> +#define QMP_PHY_INIT_CFG_LANE(o, v, l)	\
>> +	{				\
>> +		.offset = o,		\
>> +		.val = v,		\
>> +		.name = #o,		\
>> +		.lane_mask = l,		\
>> +	}
>> +
>> +static inline void qmp_configure_lane(struct udevice *dev, void __iomem *base,
>> +				      const struct qmp_phy_init_tbl tbl[],
>> +				      int num, u8 lane_mask)
>> +{
>> +	int i;
>> +	const struct qmp_phy_init_tbl *t = tbl;
>> +
>> +	if (!t)
>> +		return;
>> +
>> +	for (i = 0; i < num; i++, t++) {
>> +		if (!(t->lane_mask & lane_mask))
>> +			continue;
>> +
>> +		dev_dbg(dev, "Writing Reg: %s Offset: 0x%04x Val: 0x%02x\n",
>> +			t->name, t->offset, t->val);
>> +		writel(t->val, base + t->offset);
>> +	}
>> +}
>> +
>> +static inline void qmp_configure(struct udevice *dev, void __iomem *base,
>> +				 const struct qmp_phy_init_tbl tbl[], int num)
>> +{
>> +	qmp_configure_lane(dev, base, tbl, num, 0xff);
>> +}
>> +
>> +#endif
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
>> new file mode 100644
>> index 00000000000..396179ef38b
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-dp-com-v3.h
>> @@ -0,0 +1,18 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef QCOM_PHY_QMP_DP_COM_V3_H_
>> +#define QCOM_PHY_QMP_DP_COM_V3_H_
>> +
>> +/* Only for QMP V3 & V4 PHY - DP COM registers */
>> +#define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
>> +#define QPHY_V3_DP_COM_SW_RESET				0x04
>> +#define QPHY_V3_DP_COM_POWER_DOWN_CTRL			0x08
>> +#define QPHY_V3_DP_COM_SWI_CTRL				0x0c
>> +#define QPHY_V3_DP_COM_TYPEC_CTRL			0x10
>> +#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL			0x14
>> +#define QPHY_V3_DP_COM_RESET_OVRD_CTRL			0x1c
>> +
>> +#endif
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
>> new file mode 100644
>> index 00000000000..d7fd4ac0fc5
>> --- /dev/null
>> +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-usb-v4.h
>> @@ -0,0 +1,34 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (c) 2017, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef QCOM_PHY_QMP_PCS_USB_V4_H_
>> +#define QCOM_PHY_QMP_PCS_USB_V4_H_
>> +
>> +/* Only for QMP V4 PHY - USB3 PCS registers */
>> +#define QPHY_V4_PCS_USB3_POWER_STATE_CONFIG1		0x000
>> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_STATUS		0x004
>> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL		0x008
>> +#define QPHY_V4_PCS_USB3_AUTONOMOUS_MODE_CTRL2		0x00c
>> +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_SOURCE_STATUS	0x010
>> +#define QPHY_V4_PCS_USB3_LFPS_RXTERM_IRQ_CLEAR		0x014
>> +#define QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL	0x018
>> +#define QPHY_V4_PCS_USB3_LFPS_TX_ECSTART		0x01c
>> +#define QPHY_V4_PCS_USB3_LFPS_PER_TIMER_VAL		0x020
>> +#define QPHY_V4_PCS_USB3_LFPS_TX_END_CNT_U3_START	0x024
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_LOCK_TIME		0x028
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME		0x02c
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_CTLE_TIME		0x030
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_WAIT_TIME_S2	0x034
>> +#define QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2	0x038
>> +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_L		0x03c
>> +#define QPHY_V4_PCS_USB3_RCVR_DTCT_DLY_U3_H		0x040
>> +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_EN_PERIOD		0x044
>> +#define QPHY_V4_PCS_USB3_ARCVR_DTCT_CM_DLY		0x048
>> +#define QPHY_V4_PCS_USB3_TXONESZEROS_RUN_LENGTH		0x04c
>> +#define QPHY_V4_PCS_USB3_ALFPS_DEGLITCH_VAL		0x050
>> +#define QPHY_V4_PCS_USB3_SIGDET_STARTUP_TIMER_VAL	0x054
>> +#define QPHY_V4_PCS_USB3_TEST_CONTROL			0x058
>> +
>> +#endif
>> diff --git a/drivers/phy/qcom/phy-qcom-qmp.h b/drivers/phy/qcom/phy-qcom-qmp.h
>> index 99f4d447caf..06dac21ddc4 100644
>> --- a/drivers/phy/qcom/phy-qcom-qmp.h
>> +++ b/drivers/phy/qcom/phy-qcom-qmp.h
>> @@ -12,12 +12,17 @@
>>   #include "phy-qcom-qmp-qserdes-com-v3.h"
>>   #include "phy-qcom-qmp-qserdes-txrx-v3.h"
>>   
>> +#include "phy-qcom-qmp-qserdes-com-v4.h"
>> +#include "phy-qcom-qmp-qserdes-txrx-v4.h"
>> +
>>   #include "phy-qcom-qmp-qserdes-pll.h"
>>   
>>   #include "phy-qcom-qmp-pcs-v2.h"
>>   
>>   #include "phy-qcom-qmp-pcs-v3.h"
>>   
>> +#include "phy-qcom-qmp-pcs-v4.h"
>> +
>>   /* Only for QMP V3 & V4 PHY - DP COM registers */
>>   #define QPHY_V3_DP_COM_PHY_MODE_CTRL			0x00
>>   #define QPHY_V3_DP_COM_SW_RESET				0x04
>> @@ -112,4 +117,16 @@
>>   #define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS		0x0e0
>>   #define QSERDES_V6_DP_PHY_STATUS			0x0e4
>>   
>> +/* QPHY_SW_RESET bit */
>> +#define SW_RESET                                BIT(0)
>> +/* QPHY_POWER_DOWN_CONTROL */
>> +#define SW_PWRDN                                BIT(0)
>> +
>> +/* QPHY_START_CONTROL bits */
>> +#define SERDES_START                            BIT(0)
>> +#define PCS_START                               BIT(1)
>> +
>> +/* QPHY_PCS_STATUS bit */
>> +#define PHYSTATUS                               BIT(6)
>> +
>>   #endif

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

* Re: [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable
  2025-11-26 14:24   ` Casey Connolly
@ 2025-12-03 11:21     ` Balaji Selvanathan
  2025-12-26 11:13       ` Sumit Garg
  0 siblings, 1 reply; 23+ messages in thread
From: Balaji Selvanathan @ 2025-12-03 11:21 UTC (permalink / raw)
  To: Casey Connolly, trini, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom


On 11/26/2025 7:54 PM, Casey Connolly wrote:
> Hi Balaji,
>
> On 24/11/2025 16:55, Balaji Selvanathan wrote:
>> Add CONFIG_QCOM_USB_FIXUP option to allow platforms to disable
>> the USB speed limitation fixup when they have proper super-speed
>> USB support in U-Boot.
> In general, we prefer to handle cases like this at runtime rather than
> compile time. Could you rework this to check for the "qcom,sc7280-dwc3"
> compatible and just skip the check in that case? I would also propose
> adding a log_warning() in the fixup case so that folks working on other
> platforms know to add their compatible too.
>
> Obviously that's still not an ideal solution, maybe it would be possible
> to implement the Super Smart (tm) fix and actually check if a driver
> /will/ bind to the ss-phy node before the fixup, it depends how slow
> that would be.
This is good idea. Actually, I have implemented the super smart fix 
rather than hardcoding

"qcom,sc7280-dwc3" in code. The respined code is here: https://lore.kernel.org/u-boot/20251203110735.1959862-5-balaji.selvanathan@oss.qualcomm.com/;
The code checks if the SS PHY driver is indeed available and if it exists, then it skips doing
USB HS fixup.
The entire time to check if the SS PHY driver is available is ~125ms. Request to say if this is reasonable.
The power domain fixup is taking ~98us (mentioning just for comparison).
Thanks,
Balaji

>
> Kind regards,
>
>> Currently, U-Boot limits USB to high-speed mode on all Qualcomm
>> platforms by fixing up the device tree at runtime. This was
>> necessary because most platforms lacked super-speed PHY drivers.
>>
>> However, newer platforms now have proper QMP PHY drivers that support
>> super-speed USB. For these platforms, the fixup is counterproductive
>> as it prevents the hardware from operating at its full capability.
>>
>> This change:
>> - Adds CONFIG_QCOM_USB_FIXUP (default y) to maintain backward
>>    compatibility with existing platforms
>> - Wraps the fixup code with #ifdef to allow selective disabling
>> - Allows platforms with super-speed support to disable the fixup
>>    via their defconfig
>>
>> Platforms without super-speed PHY drivers will continue to work
>> as before with the fixup enabled by default.
>>
>> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
>> ---
>>   arch/arm/mach-snapdragon/Kconfig    | 10 ++++++++++
>>   arch/arm/mach-snapdragon/of_fixup.c |  4 ++++
>>   2 files changed, 14 insertions(+)
>>
>> diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
>> index 976c0e35fce..6c53aeef597 100644
>> --- a/arch/arm/mach-snapdragon/Kconfig
>> +++ b/arch/arm/mach-snapdragon/Kconfig
>> @@ -29,6 +29,16 @@ config SYS_MALLOC_LEN
>>   config LNX_KRNL_IMG_TEXT_OFFSET_BASE
>>   	default 0x80000000
>>   
>> +config QCOM_USB_FIXUP
>> +	bool "Enable USB speed fixup for Qualcomm platforms"
>> +	default y
>> +	help
>> +	  Enable runtime fixup of USB device tree nodes to limit USB to
>> +	  high-speed mode. This is needed on some Qualcomm platforms where
>> +	  U-Boot doesn't support super-speed USB.
>> +	  Disable this for platforms that have proper super-speed USB support
>> +	  in U-Boot.
>> +
>>   config SYS_BOARD
>>   	string "Snapdragon SoCs based board"
>>   	help
>> diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c
>> index eec2c0c757e..6a64168f67e 100644
>> --- a/arch/arm/mach-snapdragon/of_fixup.c
>> +++ b/arch/arm/mach-snapdragon/of_fixup.c
>> @@ -27,6 +27,7 @@
>>   #include <stdlib.h>
>>   #include <time.h>
>>   
>> +#ifdef CONFIG_QCOM_USB_FIXUP
>>   /* U-Boot only supports USB high-speed mode on Qualcomm platforms with DWC3
>>    * USB controllers. Rather than requiring source level DT changes, we fix up
>>    * DT here. This improves compatibility with upstream DT and simplifies the
>> @@ -115,6 +116,7 @@ static void fixup_usb_nodes(struct device_node *root)
>>   			log_warning("Failed to fixup node %s: %d\n", glue_np->name, ret);
>>   	}
>>   }
>> +#endif
>>   
>>   /* Remove all references to the rpmhpd device */
>>   static void fixup_power_domains(struct device_node *root)
>> @@ -157,7 +159,9 @@ static int qcom_of_fixup_nodes(void * __maybe_unused ctx, struct event *event)
>>   {
>>   	struct device_node *root = event->data.of_live_built.root;
>>   
>> +#ifdef CONFIG_QCOM_USB_FIXUP
>>   	time_call(fixup_usb_nodes, root);
>> +#endif
>>   	time_call(fixup_power_domains, root);
>>   
>>   	return 0;

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

* Re: [PATCH v2 5/7] arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks
  2025-11-26 14:26   ` Casey Connolly
@ 2025-12-03 11:36     ` Balaji Selvanathan
  0 siblings, 0 replies; 23+ messages in thread
From: Balaji Selvanathan @ 2025-12-03 11:36 UTC (permalink / raw)
  To: Casey Connolly, trini, neil.armstrong, sumit.garg, lukma, seanga2,
	marex, malysagreg, arturs.artamonovs, utsav.agarwal,
	vasileios.bimpikas, ian.roberts, nathan.morrison, peng.fan,
	alif.zakuan.yuslaimi, kory.maincent, sjg, jerome.forissier, ziyao,
	stefan.roese, mkorpershoek, rui.silva, ilias.apalodimas,
	luca.weiss, quic_varada, u-boot, u-boot-qcom


On 11/26/2025 7:56 PM, Casey Connolly wrote:
> Hi Balaji,
>
> On 24/11/2025 16:55, Balaji Selvanathan wrote:
>> Override the USB QMP PHY clock properties to use only GCC clocks
>> supported in U-Boot, removing the unsupported RPMH_CXO_CLK from
>> the qcs6490-rb3gen2's device tree.
> That clock should be handled by the stub clock driver, are you seeing an
> error without this patch (with CONFIG_CLK_STUB=y)?

You are right. With CONFIG_CLK_STUB=y, it is working fine without any 
additions in override dts file. So have removed this patch in this 
respin: 
https://lore.kernel.org/u-boot/20251203110735.1959862-1-balaji.selvanathan@oss.qualcomm.com/

Thanks,

Balaji

>
>
>> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
>> ---
>>   arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi | 8 ++++++++
>>   1 file changed, 8 insertions(+)
>>
>> diff --git a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
>> index 50674b692ed..14669b50821 100644
>> --- a/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
>> +++ b/arch/arm/dts/qcs6490-rb3gen2-u-boot.dtsi
>> @@ -22,6 +22,14 @@
>>   	/delete-property/ usb-role-switch;
>>   };
>>   
>> +&usb_1_qmpphy {
>> +	clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
>> +		 <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
>> +		 <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
>> +	clock-names = "aux",
>> +		      "com_aux",
>> +		      "usb3_pipe";
>> +};
>>   // RAM Entry 0 : Base 0x0080000000  Size 0x003A800000
>>   // RAM Entry 1 : Base 0x00C0000000  Size 0x0001800000
>>   // RAM Entry 2 : Base 0x00C3400000  Size 0x003CC00000

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

* Re: [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock
  2025-11-24 15:54 ` [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock Balaji Selvanathan
  2025-11-26 14:30   ` Casey Connolly
@ 2025-12-23  8:31   ` Sumit Garg
  1 sibling, 0 replies; 23+ messages in thread
From: Sumit Garg @ 2025-12-23  8:31 UTC (permalink / raw)
  To: Balaji Selvanathan
  Cc: trini, casey.connolly, neil.armstrong, lukma, seanga2, marex,
	malysagreg, arturs.artamonovs, utsav.agarwal, vasileios.bimpikas,
	ian.roberts, nathan.morrison, peng.fan, alif.zakuan.yuslaimi,
	kory.maincent, sjg, jerome.forissier, ziyao, stefan.roese,
	mkorpershoek, rui.silva, ilias.apalodimas, luca.weiss,
	quic_varada, u-boot, u-boot-qcom

On Mon, Nov 24, 2025 at 09:24:57PM +0530, Balaji Selvanathan wrote:
> Add support for GCC_USB3_PRIM_PHY_PIPE_CLK which is required by
> the USB3 PHY on SC7280/QCM6490 platforms.
> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
> ---
>  drivers/clk/qcom/clock-sc7280.c | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>

-Sumit

> 
> diff --git a/drivers/clk/qcom/clock-sc7280.c b/drivers/clk/qcom/clock-sc7280.c
> index 55a233df394..a2af73cd976 100644
> --- a/drivers/clk/qcom/clock-sc7280.c
> +++ b/drivers/clk/qcom/clock-sc7280.c
> @@ -111,6 +111,7 @@ static const struct gate_clk sc7280_clks[] = {
>  	GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0xf01c, 1),
>  	GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0xf054, 1),
>  	GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0xf058, 1),
> +	GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0xf05c, 1),
>  	GATE_CLK(GCC_CFG_NOC_USB3_SEC_AXI_CLK, 0x9e07c, 1),
>  	GATE_CLK(GCC_USB30_SEC_MASTER_CLK, 0x9e010, 1),
>  	GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x9e080, 1),
> -- 
> 2.34.1
> 

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

* Re: [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset
  2025-11-24 15:54 ` [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset Balaji Selvanathan
@ 2025-12-23  9:05   ` Sumit Garg
  2025-12-24  5:56     ` Balaji Selvanathan
  0 siblings, 1 reply; 23+ messages in thread
From: Sumit Garg @ 2025-12-23  9:05 UTC (permalink / raw)
  To: Balaji Selvanathan
  Cc: trini, casey.connolly, neil.armstrong, lukma, seanga2, marex,
	malysagreg, arturs.artamonovs, utsav.agarwal, vasileios.bimpikas,
	ian.roberts, nathan.morrison, peng.fan, alif.zakuan.yuslaimi,
	kory.maincent, sjg, jerome.forissier, ziyao, stefan.roese,
	mkorpershoek, rui.silva, ilias.apalodimas, luca.weiss,
	quic_varada, u-boot, u-boot-qcom

On Mon, Nov 24, 2025 at 09:24:58PM +0530, Balaji Selvanathan wrote:
> Add a 100 ms delay after clearing the core soft reset bit to ensure
> the DWC3 controller has sufficient time to complete its reset
> sequence before subsequent register accesses.
> 
> Without this delay, USB initialization can fail on some Qualcomm
> platforms, particularly when using super-speed capable PHYs like
> the QMP USB3-DP Combo PHY on SC7280/QCM6490.
> 
> The change is taken from following upstream Linux implementation:
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/usb/dwc3/core.c?id=f88359e1588b85cf0e8209ab7d6620085f3441d9

If I understand correctly the kernel change here especially following
comment:

	/*
	 * Wait for internal clocks to synchronized. DWC_usb31 and
	 * DWC_usb32 may need at least 50ms (less for DWC_usb3). To
	 * keep it consistent across different IPs, let's wait up to
	 * 100ms before clearing GCTL.CORESOFTRESET.
	 */

the delay is required before clearing GCTL.CORESOFTRESET and not after
which your change seems to do. Also, here we aren't doing any role
switch too, right?

-Sumit

> 
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> ---
> v2:
> - Gave correct commit id for linux implementation
> ---
>  drivers/usb/dwc3/core.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 847fa1f82c3..ff0bca0dd8e 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -94,6 +94,8 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
>  	reg &= ~DWC3_GCTL_CORESOFTRESET;
>  	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
>  
> +	mdelay(100);
> +
>  	return 0;
>  }
>  
> -- 
> 2.34.1
> 

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

* Re: [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset
  2025-12-23  9:05   ` Sumit Garg
@ 2025-12-24  5:56     ` Balaji Selvanathan
  2025-12-26  7:27       ` Sumit Garg
  0 siblings, 1 reply; 23+ messages in thread
From: Balaji Selvanathan @ 2025-12-24  5:56 UTC (permalink / raw)
  To: Sumit Garg
  Cc: trini, casey.connolly, neil.armstrong, lukma, seanga2, marex,
	malysagreg, arturs.artamonovs, utsav.agarwal, vasileios.bimpikas,
	ian.roberts, nathan.morrison, peng.fan, alif.zakuan.yuslaimi,
	kory.maincent, sjg, jerome.forissier, ziyao, stefan.roese,
	mkorpershoek, rui.silva, ilias.apalodimas, luca.weiss,
	quic_varada, u-boot, u-boot-qcom


On 12/23/2025 2:35 PM, Sumit Garg wrote:
> On Mon, Nov 24, 2025 at 09:24:58PM +0530, Balaji Selvanathan wrote:
>> Add a 100 ms delay after clearing the core soft reset bit to ensure
>> the DWC3 controller has sufficient time to complete its reset
>> sequence before subsequent register accesses.
>>
>> Without this delay, USB initialization can fail on some Qualcomm
>> platforms, particularly when using super-speed capable PHYs like
>> the QMP USB3-DP Combo PHY on SC7280/QCM6490.
>>
>> The change is taken from following upstream Linux implementation:
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/usb/dwc3/core.c?id=f88359e1588b85cf0e8209ab7d6620085f3441d9
> If I understand correctly the kernel change here especially following
> comment:
>
> 	/*
> 	 * Wait for internal clocks to synchronized. DWC_usb31 and
> 	 * DWC_usb32 may need at least 50ms (less for DWC_usb3). To
> 	 * keep it consistent across different IPs, let's wait up to
> 	 * 100ms before clearing GCTL.CORESOFTRESET.
> 	 */
>
> the delay is required before clearing GCTL.CORESOFTRESET and not after
> which your change seems to do. Also, here we aren't doing any role
> switch too, right?

Hi Sumit,

You're correct about the Linux implementation. However, in U-Boot's 
case, the context is different:

1. Linux: The delay is during role switching in dwc3_set_mode(), where 
only GCTL.CORESOFTRESET is toggled.

2. U-Boot: The delay is in dwc3_core_soft_reset() during initial boot, 
which has a more complex sequence:

    - Sets GCTL.CORESOFTRESET
    - Asserts PHY resets (USB2/USB3)
    - Waits 100ms
    - Clears PHY resets
    - Waits 100ms (for PHY stabilization)
    - Clears GCTL.CORESOFTRESET
The additional delay after clearing the reset bit is needed in U-Boot to 
ensure the controller is fully operational before subsequent register 
accesses, particularly for super-speed PHYs on QCM6490/SC7280. 
Otherwise, fastboot mode is not working sometimes (stability issue).

Would you be okay with adding this delay after clearing GCTL.CORESOFTRESET?

Regards,

Balaji

>
> -Sumit
>
>> Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
>> ---
>> v2:
>> - Gave correct commit id for linux implementation
>> ---
>>   drivers/usb/dwc3/core.c | 2 ++
>>   1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 847fa1f82c3..ff0bca0dd8e 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -94,6 +94,8 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
>>   	reg &= ~DWC3_GCTL_CORESOFTRESET;
>>   	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
>>   
>> +	mdelay(100);
>> +
>>   	return 0;
>>   }
>>   
>> -- 
>> 2.34.1
>>

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

* Re: [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset
  2025-12-24  5:56     ` Balaji Selvanathan
@ 2025-12-26  7:27       ` Sumit Garg
  0 siblings, 0 replies; 23+ messages in thread
From: Sumit Garg @ 2025-12-26  7:27 UTC (permalink / raw)
  To: Balaji Selvanathan
  Cc: trini, casey.connolly, neil.armstrong, lukma, seanga2, marex,
	malysagreg, arturs.artamonovs, utsav.agarwal, vasileios.bimpikas,
	ian.roberts, nathan.morrison, peng.fan, alif.zakuan.yuslaimi,
	kory.maincent, sjg, jerome.forissier, ziyao, stefan.roese,
	mkorpershoek, rui.silva, ilias.apalodimas, luca.weiss,
	quic_varada, u-boot, u-boot-qcom

On Wed, Dec 24, 2025 at 11:26:12AM +0530, Balaji Selvanathan wrote:
> 
> On 12/23/2025 2:35 PM, Sumit Garg wrote:
> > On Mon, Nov 24, 2025 at 09:24:58PM +0530, Balaji Selvanathan wrote:
> > > Add a 100 ms delay after clearing the core soft reset bit to ensure
> > > the DWC3 controller has sufficient time to complete its reset
> > > sequence before subsequent register accesses.
> > > 
> > > Without this delay, USB initialization can fail on some Qualcomm
> > > platforms, particularly when using super-speed capable PHYs like
> > > the QMP USB3-DP Combo PHY on SC7280/QCM6490.
> > > 
> > > The change is taken from following upstream Linux implementation:
> > > https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/usb/dwc3/core.c?id=f88359e1588b85cf0e8209ab7d6620085f3441d9
> > If I understand correctly the kernel change here especially following
> > comment:
> > 
> > 	/*
> > 	 * Wait for internal clocks to synchronized. DWC_usb31 and
> > 	 * DWC_usb32 may need at least 50ms (less for DWC_usb3). To
> > 	 * keep it consistent across different IPs, let's wait up to
> > 	 * 100ms before clearing GCTL.CORESOFTRESET.
> > 	 */
> > 
> > the delay is required before clearing GCTL.CORESOFTRESET and not after
> > which your change seems to do. Also, here we aren't doing any role
> > switch too, right?
> 
> Hi Sumit,
> 
> You're correct about the Linux implementation. However, in U-Boot's case,
> the context is different:
> 
> 1. Linux: The delay is during role switching in dwc3_set_mode(), where only
> GCTL.CORESOFTRESET is toggled.
> 
> 2. U-Boot: The delay is in dwc3_core_soft_reset() during initial boot, which
> has a more complex sequence:
> 
>    - Sets GCTL.CORESOFTRESET
>    - Asserts PHY resets (USB2/USB3)
>    - Waits 100ms
>    - Clears PHY resets
>    - Waits 100ms (for PHY stabilization)
>    - Clears GCTL.CORESOFTRESET
> The additional delay after clearing the reset bit is needed in U-Boot to
> ensure the controller is fully operational before subsequent register
> accesses, particularly for super-speed PHYs on QCM6490/SC7280. Otherwise,
> fastboot mode is not working sometimes (stability issue).
>

I would rather suggest you to explore following kernel driver init
sequence:

dwc3_core_init() ->
  dwc3_core_soft_reset()

and see if you can have a better explanation for the delay requirement
here similar to following quote:

        /*
         * For DWC_usb31 controller 1.80a and prior, once DCTL.CSFRST bit
         * is cleared, we must wait at least 50ms before accessing the PHY
         * domain (synchronization delay).
         */
        if (DWC3_VER_IS_WITHIN(DWC31, ANY, 180A))
                msleep(50);

> Would you be okay with adding this delay after clearing GCTL.CORESOFTRESET?

Adding random delays in the common code may have impact on boot times
for all the platforms. We really should understand the root cause here
in case if this delay requirement is specific to a particular DWC
controller version or not?

And since your problem relates to DWC controller operating in device
mode, so you should focus on the gaps you see with corresponding kernel
driver device mode init sequence. As the kernel driver has been well
supported on Qcom platforms with adb working fine in user-space.

-Sumit

> 
> Regards,
> 
> Balaji
> 
> > 
> > -Sumit
> > 
> > > Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> > > ---
> > > v2:
> > > - Gave correct commit id for linux implementation
> > > ---
> > >   drivers/usb/dwc3/core.c | 2 ++
> > >   1 file changed, 2 insertions(+)
> > > 
> > > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> > > index 847fa1f82c3..ff0bca0dd8e 100644
> > > --- a/drivers/usb/dwc3/core.c
> > > +++ b/drivers/usb/dwc3/core.c
> > > @@ -94,6 +94,8 @@ static int dwc3_core_soft_reset(struct dwc3 *dwc)
> > >   	reg &= ~DWC3_GCTL_CORESOFTRESET;
> > >   	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
> > > +	mdelay(100);
> > > +
> > >   	return 0;
> > >   }
> > > -- 
> > > 2.34.1
> > > 

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

* Re: [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable
  2025-12-03 11:21     ` Balaji Selvanathan
@ 2025-12-26 11:13       ` Sumit Garg
  0 siblings, 0 replies; 23+ messages in thread
From: Sumit Garg @ 2025-12-26 11:13 UTC (permalink / raw)
  To: Balaji Selvanathan
  Cc: Casey Connolly, trini, neil.armstrong, lukma, seanga2, marex,
	malysagreg, arturs.artamonovs, utsav.agarwal, vasileios.bimpikas,
	ian.roberts, nathan.morrison, peng.fan, alif.zakuan.yuslaimi,
	kory.maincent, sjg, jerome.forissier, ziyao, stefan.roese,
	mkorpershoek, rui.silva, ilias.apalodimas, luca.weiss,
	quic_varada, u-boot, u-boot-qcom

On Wed, Dec 03, 2025 at 04:51:20PM +0530, Balaji Selvanathan wrote:
> 
> On 11/26/2025 7:54 PM, Casey Connolly wrote:
> > Hi Balaji,
> > 
> > On 24/11/2025 16:55, Balaji Selvanathan wrote:
> > > Add CONFIG_QCOM_USB_FIXUP option to allow platforms to disable
> > > the USB speed limitation fixup when they have proper super-speed
> > > USB support in U-Boot.
> > In general, we prefer to handle cases like this at runtime rather than
> > compile time. Could you rework this to check for the "qcom,sc7280-dwc3"
> > compatible and just skip the check in that case? I would also propose
> > adding a log_warning() in the fixup case so that folks working on other
> > platforms know to add their compatible too.
> > 
> > Obviously that's still not an ideal solution, maybe it would be possible
> > to implement the Super Smart (tm) fix and actually check if a driver
> > /will/ bind to the ss-phy node before the fixup, it depends how slow
> > that would be.
> This is good idea. Actually, I have implemented the super smart fix rather
> than hardcoding
> 
> "qcom,sc7280-dwc3" in code. The respined code is here: https://lore.kernel.org/u-boot/20251203110735.1959862-5-balaji.selvanathan@oss.qualcomm.com/;
> The code checks if the SS PHY driver is indeed available and if it exists, then it skips doing
> USB HS fixup.
> The entire time to check if the SS PHY driver is available is ~125ms. Request to say if this is reasonable.

I don't think it's reasonable to add more than 125ms in boot for every
platform considering slower platforms as compared to RB3G2 where it will
be much worse.

Lets just rather add a static check for "qcom,sc7280-dwc3" to skip the
USB fixup.

-Sumit

> The power domain fixup is taking ~98us (mentioning just for comparison).
> Thanks,
> Balaji
> 
> > 
> > Kind regards,
> > 
> > > Currently, U-Boot limits USB to high-speed mode on all Qualcomm
> > > platforms by fixing up the device tree at runtime. This was
> > > necessary because most platforms lacked super-speed PHY drivers.
> > > 
> > > However, newer platforms now have proper QMP PHY drivers that support
> > > super-speed USB. For these platforms, the fixup is counterproductive
> > > as it prevents the hardware from operating at its full capability.
> > > 
> > > This change:
> > > - Adds CONFIG_QCOM_USB_FIXUP (default y) to maintain backward
> > >    compatibility with existing platforms
> > > - Wraps the fixup code with #ifdef to allow selective disabling
> > > - Allows platforms with super-speed support to disable the fixup
> > >    via their defconfig
> > > 
> > > Platforms without super-speed PHY drivers will continue to work
> > > as before with the fixup enabled by default.
> > > 
> > > Signed-off-by: Balaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
> > > ---
> > >   arch/arm/mach-snapdragon/Kconfig    | 10 ++++++++++
> > >   arch/arm/mach-snapdragon/of_fixup.c |  4 ++++
> > >   2 files changed, 14 insertions(+)
> > > 
> > > diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
> > > index 976c0e35fce..6c53aeef597 100644
> > > --- a/arch/arm/mach-snapdragon/Kconfig
> > > +++ b/arch/arm/mach-snapdragon/Kconfig
> > > @@ -29,6 +29,16 @@ config SYS_MALLOC_LEN
> > >   config LNX_KRNL_IMG_TEXT_OFFSET_BASE
> > >   	default 0x80000000
> > > +config QCOM_USB_FIXUP
> > > +	bool "Enable USB speed fixup for Qualcomm platforms"
> > > +	default y
> > > +	help
> > > +	  Enable runtime fixup of USB device tree nodes to limit USB to
> > > +	  high-speed mode. This is needed on some Qualcomm platforms where
> > > +	  U-Boot doesn't support super-speed USB.
> > > +	  Disable this for platforms that have proper super-speed USB support
> > > +	  in U-Boot.
> > > +
> > >   config SYS_BOARD
> > >   	string "Snapdragon SoCs based board"
> > >   	help
> > > diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c
> > > index eec2c0c757e..6a64168f67e 100644
> > > --- a/arch/arm/mach-snapdragon/of_fixup.c
> > > +++ b/arch/arm/mach-snapdragon/of_fixup.c
> > > @@ -27,6 +27,7 @@
> > >   #include <stdlib.h>
> > >   #include <time.h>
> > > +#ifdef CONFIG_QCOM_USB_FIXUP
> > >   /* U-Boot only supports USB high-speed mode on Qualcomm platforms with DWC3
> > >    * USB controllers. Rather than requiring source level DT changes, we fix up
> > >    * DT here. This improves compatibility with upstream DT and simplifies the
> > > @@ -115,6 +116,7 @@ static void fixup_usb_nodes(struct device_node *root)
> > >   			log_warning("Failed to fixup node %s: %d\n", glue_np->name, ret);
> > >   	}
> > >   }
> > > +#endif
> > >   /* Remove all references to the rpmhpd device */
> > >   static void fixup_power_domains(struct device_node *root)
> > > @@ -157,7 +159,9 @@ static int qcom_of_fixup_nodes(void * __maybe_unused ctx, struct event *event)
> > >   {
> > >   	struct device_node *root = event->data.of_live_built.root;
> > > +#ifdef CONFIG_QCOM_USB_FIXUP
> > >   	time_call(fixup_usb_nodes, root);
> > > +#endif
> > >   	time_call(fixup_power_domains, root);
> > >   	return 0;

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

end of thread, other threads:[~2025-12-26 11:13 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-24 15:54 [PATCH v2 0/7] Enable USB3 Super-Speed support for QCM6490/SC7280 Balaji Selvanathan
2025-11-24 15:54 ` [PATCH v2 1/7] drivers: clk: qcom: sc7280: Add USB3 PHY pipe clock Balaji Selvanathan
2025-11-26 14:30   ` Casey Connolly
2025-12-23  8:31   ` Sumit Garg
2025-11-24 15:54 ` [PATCH v2 2/7] drivers: usb: dwc3: Add delay after core soft reset Balaji Selvanathan
2025-12-23  9:05   ` Sumit Garg
2025-12-24  5:56     ` Balaji Selvanathan
2025-12-26  7:27       ` Sumit Garg
2025-11-24 15:54 ` [PATCH v2 3/7] drivers: phy: qcom: Add QMP USB3-DP Combo PHY driver Balaji Selvanathan
2025-11-24 19:51   ` Tom Rini
2025-11-25 10:33     ` Balaji Selvanathan
2025-11-26 14:46   ` Casey Connolly
2025-11-28  3:31     ` Balaji Selvanathan
2025-12-03 11:13     ` Balaji Selvanathan
2025-11-24 15:55 ` [PATCH v2 4/7] arch: arm: mach-snapdragon: Make USB speed fixup configurable Balaji Selvanathan
2025-11-26 14:24   ` Casey Connolly
2025-12-03 11:21     ` Balaji Selvanathan
2025-12-26 11:13       ` Sumit Garg
2025-11-24 15:55 ` [PATCH v2 5/7] arch: arm: dts: qcs6490-rb3gen2: Override USB3 PHY clocks Balaji Selvanathan
2025-11-26 14:26   ` Casey Connolly
2025-12-03 11:36     ` Balaji Selvanathan
2025-11-24 15:55 ` [PATCH v2 6/7] configs: qcm6490: Enable super-speed USB support Balaji Selvanathan
2025-11-24 15:55 ` [PATCH v2 7/7] MAINTAINERS: Add entry for Qualcomm PHY drivers Balaji Selvanathan

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