[PATCH 11/11] board: imx8mp_evk: add USB Type-C OTG support with TCPCI

Peng Fan (OSS) peng.fan at oss.nxp.com
Wed Jun 17 10:23:10 CEST 2026


From: Peng Fan <peng.fan at nxp.com>

Enable runtime USB host/device mode switching on USB1 Type-C port:

- Add PTN5110 TCPCI node on I2C2 with pd-disable (data port only,
  PD negotiation handled by port2 on I2C3)
- Set dr_mode="otg" on usb_dwc3_0 with USB PHY tuning parameters
- Add board_usb_init(): host mode uses tcpm_setup_host_mode(),
  device mode uses tcpm_setup_device_mode() via TCPM uclass ops
- Add board_usb_cleanup(): disable source VBUS on host stop
- SS mux GPIO (GPIO4_IO20) set based on CC polarity
- Enable USB_DWC3_GENERIC, DM_USB_GADGET in defconfig

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 arch/arm/dts/imx8mp-evk-u-boot.dtsi | 34 +++++++++++++++-
 board/nxp/imx8mp_evk/imx8mp_evk.c   | 78 +++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/imx8mp-evk-u-boot.dtsi b/arch/arm/dts/imx8mp-evk-u-boot.dtsi
index fc9e9da09dd..d315dfb3d03 100644
--- a/arch/arm/dts/imx8mp-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx8mp-evk-u-boot.dtsi
@@ -88,6 +88,24 @@
 
 &i2c2 {
 	bootph-pre-ram;
+
+	tcpc_port1: i2c2-ptcpc at 50 {
+		compatible = "nxp,ptn5110", "tcpci";
+		reg = <0x50>;
+
+		connector {
+			compatible = "usb-c-connector";
+			label = "USB-C-1";
+			power-role = "dual";
+			data-role = "dual";
+			try-power-role = "sink";
+			pd-disable;
+			source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+			sink-pdos =
+				<PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
+			op-sink-microwatt = <15000000>;
+		};
+	};
 };
 
 &i2c3 {
@@ -124,7 +142,15 @@
 };
 
 &usb_dwc3_0 {
-	dr_mode = "peripheral";
+	dr_mode = "otg";
+	maximum-speed = "high-speed";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
+	usb-role-switch;
+	role-switch-default-mode = "none";
+	snps,dis-u1-entry-quirk;
+	snps,dis-u2-entry-quirk;
 	status = "okay";
 };
 
@@ -133,6 +159,12 @@
 };
 
 &usb3_phy0 {
+	fsl,phy-tx-vref-tune = <0xe>;
+	fsl,phy-tx-preemp-amp-tune = <3>;
+	fsl,phy-tx-vboost-level = <5>;
+	fsl,phy-comp-dis-tune = <7>;
+	fsl,pcs-tx-deemph-3p5db = <0x21>;
+	fsl,phy-pcs-tx-swing-full = <0x7f>;
 	status = "okay";
 };
 
diff --git a/board/nxp/imx8mp_evk/imx8mp_evk.c b/board/nxp/imx8mp_evk/imx8mp_evk.c
index e17100e51ec..37a391908c4 100644
--- a/board/nxp/imx8mp_evk/imx8mp_evk.c
+++ b/board/nxp/imx8mp_evk/imx8mp_evk.c
@@ -4,9 +4,14 @@
  */
 
 #include <config.h>
+#include <dm.h>
 #include <efi_loader.h>
 #include <env.h>
+#include <init.h>
+#include <usb.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/gpio.h>
+#include <usb/tcpm.h>
 
 #if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
 #define IMX_BOOT_IMAGE_GUID \
@@ -35,6 +40,79 @@ int board_mmc_get_env_dev(int devno)
 }
 #endif
 
+#define USB_TYPEC_SEL	IMX_GPIO_NR(4, 20)
+#define USB_TYPEC_EN	IMX_GPIO_NR(2, 20)
+
+static struct udevice *tcpc1_tcpm;
+static bool usb1_gpio_inited;
+
+static int usb1_tcpm_init(void)
+{
+	if (tcpc1_tcpm)
+		return 0;
+
+	return tcpm_get(0, &tcpc1_tcpm);
+}
+
+static void ss_mux_select(enum typec_cc_polarity polarity)
+{
+	if (polarity == TYPEC_POLARITY_CC1)
+		gpio_direction_output(USB_TYPEC_SEL, 0);
+	else
+		gpio_direction_output(USB_TYPEC_SEL, 1);
+}
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	enum typec_cc_polarity pol;
+	int ret;
+
+	if (index != 0)
+		return 0;
+
+	if (!usb1_gpio_inited) {
+		gpio_request(USB_TYPEC_SEL, "typec_sel");
+		gpio_request(USB_TYPEC_EN, "typec_en");
+		usb1_gpio_inited = true;
+	}
+	gpio_direction_output(USB_TYPEC_EN, 0);
+
+	ret = usb1_tcpm_init();
+	if (ret) {
+		printf("USB1: TCPM init failed: %d\n", ret);
+		return ret;
+	}
+
+	if (init == USB_INIT_HOST) {
+		ret = tcpm_setup_host_mode(tcpc1_tcpm, &pol);
+		if (ret) {
+			printf("USB1: no device detected\n");
+			return 0;
+		}
+	} else {
+		ret = tcpm_setup_device_mode(tcpc1_tcpm, &pol);
+		if (ret) {
+			printf("USB1: no host detected\n");
+			return 0;
+		}
+	}
+
+	ss_mux_select(pol);
+
+	return 0;
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	if (index != 0)
+		return 0;
+
+	if (init == USB_INIT_HOST && tcpc1_tcpm)
+		tcpm_disable_src_vbus(tcpc1_tcpm);
+
+	return 0;
+}
+
 int board_late_init(void)
 {
 #if CONFIG_IS_ENABLED(ENV_IS_IN_MMC)

-- 
2.51.0



More information about the U-Boot mailing list