From: Peng Fan <[email protected]>

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 <[email protected]>
---
 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@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

Reply via email to