[PATCH 6/8] imx8mm_evk: add usbotg1 host support

Peng Fan peng.fan at nxp.com
Mon Oct 12 08:23:52 CEST 2020


Add tcpc port and pd switch code board code
Add U-Boot specific dtsi property, we use nop-phy driver for the phy
Add relevant config options

Test:
u-boot=> usb start
starting USB...
Bus usb at 32e40000: USB EHCI 1.00
scanning bus usb at 32e40000 for devices... 2 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
u-boot=> usb tree
USB device tree:
  1  Hub (480 Mb/s, 0mA)
  |  u-boot EHCI Host Controller
  |
  +-2  Mass Storage (480 Mb/s, 300mA)
       Kingston DataTraveler 2.0 50E54951344CB04199CA8CE6

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 arch/arm/dts/imx8mm-evk-u-boot.dtsi     |  26 ++++
 board/freescale/imx8mm_evk/Kconfig      |   1 +
 board/freescale/imx8mm_evk/imx8mm_evk.c | 181 ++++++++++++++++++++++++
 configs/imx8mm_evk_defconfig            |  12 ++
 include/configs/imx8mm_evk.h            |   3 +
 5 files changed, 223 insertions(+)

diff --git a/arch/arm/dts/imx8mm-evk-u-boot.dtsi b/arch/arm/dts/imx8mm-evk-u-boot.dtsi
index b5c12105a9..241dfd656f 100644
--- a/arch/arm/dts/imx8mm-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx8mm-evk-u-boot.dtsi
@@ -4,6 +4,12 @@
  */
 
 / {
+
+	aliases {
+		usb0 = &usbotg1;
+		usb1 = &usbotg2;
+	};
+
 	wdt-reboot {
 		compatible = "wdt-reboot";
 		wdt = <&wdog1>;
@@ -129,3 +135,23 @@
 &wdog1 {
 	u-boot,dm-spl;
 };
+
+&usbotg1 {
+	extcon = "tcpc";
+	phys = <&usbphynop1>;
+};
+
+&usbphynop1 {
+	compatible = "nop-phy";
+	#phy-cells = <0>;
+};
+
+&usbotg2 {
+	extcon = "tcpc";
+	phys = <&usbphynop2>;
+};
+
+&usbphynop2 {
+	compatible = "nop-phy";
+	#phy-cells = <0>;
+};
diff --git a/board/freescale/imx8mm_evk/Kconfig b/board/freescale/imx8mm_evk/Kconfig
index 299691a619..cbd9d4e8f2 100644
--- a/board/freescale/imx8mm_evk/Kconfig
+++ b/board/freescale/imx8mm_evk/Kconfig
@@ -9,4 +9,5 @@ config SYS_VENDOR
 config SYS_CONFIG_NAME
 	default "imx8mm_evk"
 
+source "board/freescale/common/Kconfig"
 endif
diff --git a/board/freescale/imx8mm_evk/imx8mm_evk.c b/board/freescale/imx8mm_evk/imx8mm_evk.c
index 6af7100696..187ea19b91 100644
--- a/board/freescale/imx8mm_evk/imx8mm_evk.c
+++ b/board/freescale/imx8mm_evk/imx8mm_evk.c
@@ -6,11 +6,14 @@
 #include <common.h>
 #include <env.h>
 #include <init.h>
+#include <i2c.h>
 #include <miiphy.h>
 #include <netdev.h>
+#include <usb.h>
 
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
+#include "../common/tcpc.h"
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -44,8 +47,186 @@ int board_phy_config(struct phy_device *phydev)
 }
 #endif
 
+#if IS_ENABLED(CONFIG_USB_TCPC)
+struct tcpc_port port1;
+struct tcpc_port port2;
+
+static int setup_pd_switch(uint8_t i2c_bus, uint8_t addr)
+{
+	struct udevice *bus;
+	struct udevice *i2c_dev = NULL;
+	int ret;
+	uint8_t valb;
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		printf("%s: Can't find bus\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = dm_i2c_probe(bus, addr, 0, &i2c_dev);
+	if (ret) {
+		printf("%s: Can't find device id=0x%x\n",
+			__func__, addr);
+		return -ENODEV;
+	}
+
+	ret = dm_i2c_read(i2c_dev, 0xB, &valb, 1);
+	if (ret) {
+		printf("%s dm_i2c_read failed, err %d\n", __func__, ret);
+		return -EIO;
+	}
+	valb |= 0x4; /* Set DB_EXIT to exit dead battery mode */
+	ret = dm_i2c_write(i2c_dev, 0xB, (const uint8_t *)&valb, 1);
+	if (ret) {
+		printf("%s dm_i2c_write failed, err %d\n", __func__, ret);
+		return -EIO;
+	}
+
+	/* Set OVP threshold to 23V */
+	valb = 0x6;
+	ret = dm_i2c_write(i2c_dev, 0x8, (const uint8_t *)&valb, 1);
+	if (ret) {
+		printf("%s dm_i2c_write failed, err %d\n", __func__, ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int pd_switch_snk_enable(struct tcpc_port *port)
+{
+	if (port == &port1) {
+		debug("Setup pd switch on port 1\n");
+		return setup_pd_switch(1, 0x72);
+	} else if (port == &port2) {
+		debug("Setup pd switch on port 2\n");
+		return setup_pd_switch(1, 0x73);
+	} else
+		return -EINVAL;
+}
+
+struct tcpc_port_config port1_config = {
+	.i2c_bus = 1, /*i2c2*/
+	.addr = 0x50,
+	.port_type = TYPEC_PORT_UFP,
+	.max_snk_mv = 5000,
+	.max_snk_ma = 3000,
+	.max_snk_mw = 40000,
+	.op_snk_mv = 9000,
+	.switch_setup_func = &pd_switch_snk_enable,
+};
+
+struct tcpc_port_config port2_config = {
+	.i2c_bus = 1, /*i2c2*/
+	.addr = 0x52,
+	.port_type = TYPEC_PORT_UFP,
+	.max_snk_mv = 9000,
+	.max_snk_ma = 3000,
+	.max_snk_mw = 40000,
+	.op_snk_mv = 9000,
+	.switch_setup_func = &pd_switch_snk_enable,
+};
+
+static int setup_typec(void)
+{
+	int ret;
+
+	debug("tcpc_init port 2\n");
+	ret = tcpc_init(&port2, port2_config, NULL);
+	if (ret) {
+		printf("%s: tcpc port2 init failed, err=%d\n",
+		       __func__, ret);
+	} else if (tcpc_pd_sink_check_charging(&port2)) {
+		/* Disable PD for USB1, since USB2 has priority */
+		port1_config.disable_pd = true;
+		printf("Power supply on USB2\n");
+	}
+
+	debug("tcpc_init port 1\n");
+	ret = tcpc_init(&port1, port1_config, NULL);
+	if (ret) {
+		printf("%s: tcpc port1 init failed, err=%d\n",
+		       __func__, ret);
+	} else {
+		if (!port1_config.disable_pd)
+			printf("Power supply on USB1\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	int ret = 0;
+	struct tcpc_port *port_ptr;
+
+	debug("board_usb_init %d, type %d\n", index, init);
+
+	if (index == 0)
+		port_ptr = &port1;
+	else
+		port_ptr = &port2;
+
+	imx8m_usb_power(index, true);
+
+	if (init == USB_INIT_HOST)
+		tcpc_setup_dfp_mode(port_ptr);
+	else
+		tcpc_setup_ufp_mode(port_ptr);
+
+	return ret;
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	int ret = 0;
+
+	debug("board_usb_cleanup %d, type %d\n", index, init);
+
+	if (init == USB_INIT_HOST) {
+		if (index == 0)
+			ret = tcpc_disable_src_vbus(&port1);
+		else
+			ret = tcpc_disable_src_vbus(&port2);
+	}
+
+	imx8m_usb_power(index, false);
+	return ret;
+}
+
+int board_ehci_usb_phy_mode(struct udevice *dev)
+{
+	int ret = 0;
+	enum typec_cc_polarity pol;
+	enum typec_cc_state state;
+	struct tcpc_port *port_ptr;
+
+	if (dev->req_seq == 0)
+		port_ptr = &port1;
+	else
+		port_ptr = &port2;
+
+	tcpc_setup_ufp_mode(port_ptr);
+
+	ret = tcpc_get_cc_status(port_ptr, &pol, &state);
+	if (!ret) {
+		if (state == TYPEC_STATE_SRC_RD_RA || state == TYPEC_STATE_SRC_RD)
+			return USB_INIT_HOST;
+	}
+
+	return USB_INIT_DEVICE;
+}
+
+#endif
+
+
 int board_init(void)
 {
+	if (IS_ENABLED(CONFIG_USB_TCPC))
+		setup_typec();
+
 	if (IS_ENABLED(CONFIG_FEC_MXC))
 		setup_fec();
 
diff --git a/configs/imx8mm_evk_defconfig b/configs/imx8mm_evk_defconfig
index 91d3bc3ac9..10e95d8d5c 100644
--- a/configs/imx8mm_evk_defconfig
+++ b/configs/imx8mm_evk_defconfig
@@ -12,12 +12,14 @@ CONFIG_SYS_I2C_MXC_I2C2=y
 CONFIG_SYS_I2C_MXC_I2C3=y
 CONFIG_DM_GPIO=y
 CONFIG_SPL_TEXT_BASE=0x7E1000
+CONFIG_USB_TCPC=y
 CONFIG_TARGET_IMX8MM_EVK=y
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
 CONFIG_SPL=y
 CONFIG_DEFAULT_DEVICE_TREE="imx8mm-evk"
+CONFIG_ANDROID_BOOT_IMAGE=y
 CONFIG_FIT=y
 CONFIG_FIT_EXTERNAL_OFFSET=0x3000
 CONFIG_SPL_LOAD_FIT=y
@@ -40,6 +42,7 @@ CONFIG_CMD_FUSE=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
@@ -73,6 +76,8 @@ CONFIG_DM_ETH=y
 CONFIG_PHY_GIGE=y
 CONFIG_FEC_MXC=y
 CONFIG_MII=y
+CONFIG_PHY=y
+CONFIG_NOP_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
 CONFIG_PINCTRL_IMX8M=y
@@ -87,4 +92,11 @@ CONFIG_SPL_SYSRESET=y
 CONFIG_SYSRESET_PSCI=y
 CONFIG_SYSRESET_WATCHDOG=y
 CONFIG_DM_THERMAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+# CONFIG_SPL_DM_USB is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_MX7 is not set
+CONFIG_USB_EHCI_IMX=y
+CONFIG_USB_STORAGE=y
 CONFIG_IMX_WATCHDOG=y
diff --git a/include/configs/imx8mm_evk.h b/include/configs/imx8mm_evk.h
index 83521ad401..5e865f0bef 100644
--- a/include/configs/imx8mm_evk.h
+++ b/include/configs/imx8mm_evk.h
@@ -145,4 +145,7 @@
 
 #define IMX_FEC_BASE			0x30BE0000
 
+#define CONFIG_MXC_USB_PORTSC  (PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         2
+
 #endif
-- 
2.28.0



More information about the U-Boot mailing list