All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] i.MX8MM: add host/gadget support
@ 2020-10-12  6:23 Peng Fan
  2020-10-12  6:23 ` [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC) Peng Fan
                   ` (7 more replies)
  0 siblings, 8 replies; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

This patchset is based on
https://patchwork.ozlabs.org/project/uboot/list/?series=202112
https://patchwork.ozlabs.org/project/uboot/list/?series=202117

In this patchset, A new pure DM USB driver was added to driver/use/imx
which will be used to hold i.MX DM USB stuff, the ehci-mx6.c will retire
step by step after more code moved.

It also includes the DM GADGET part of ci udc, my future idea is to
add gadget support in driver/usb/imx/ and use one driver to handle
host and gadget support.

The i.MX8MM EVK board has a typec devices, so need to setup the typec,
this piece code was added in board/freescale/common.

Stefano:
  This might not be good to merge the patches into one patchset,
but to make people could easy to setup test, so send in a whole.

 Marek:
  Please see whether you are fine moving the code to drivers/usb/imx/

Peng Fan (6):
  power: regulator: add dummy helper
  phy: nop-phy: add optional clk
  usb: imx: add i.MX usb ehci driver
  imx8m: enable usb power domain
  imx8mm_evk: add usbotg1 host support
  imx8mm_evk: add fastboot support

Sherry Sun (1):
  usb: ci_udc: Convert driver to DM_USB_GADGET

Ye Li (1):
  tcpc: Add driver for USB typec port controller (TCPC)

 Makefile                                    |    1 +
 arch/arm/dts/imx8mm-evk-u-boot.dtsi         |   43 +
 arch/arm/include/asm/arch-imx8m/sys_proto.h |    1 +
 arch/arm/include/asm/mach-imx/regs-usbphy.h |    5 +
 arch/arm/include/asm/mach-imx/sys_proto.h   |    2 +
 arch/arm/mach-imx/imx8m/soc.c               |   55 +
 board/freescale/common/Kconfig              |    6 +
 board/freescale/common/Makefile             |    4 +
 board/freescale/common/tcpc.c               | 1018 +++++++++++++++++++
 board/freescale/common/tcpc.h               |  469 +++++++++
 board/freescale/imx8mm_evk/Kconfig          |    1 +
 board/freescale/imx8mm_evk/imx8mm_evk.c     |  181 ++++
 configs/imx8mm_evk_defconfig                |   23 +
 drivers/Makefile                            |    1 +
 drivers/phy/nop-phy.c                       |   34 +
 drivers/usb/Kconfig                         |    2 +
 drivers/usb/gadget/ci_udc.c                 |  305 +++++-
 drivers/usb/host/ehci-mx6.c                 |   15 +-
 drivers/usb/imx/Kconfig                     |   10 +
 drivers/usb/imx/Makefile                    |    5 +
 drivers/usb/imx/ehci-imx.c                  |  406 ++++++++
 drivers/usb/imx/imx-usb-misc.c              |   47 +
 include/configs/imx8mm_evk.h                |   17 +
 include/power/regulator.h                   |  114 +++
 include/usb/ci_udc.h                        |    3 +
 25 files changed, 2750 insertions(+), 18 deletions(-)
 create mode 100644 board/freescale/common/tcpc.c
 create mode 100644 board/freescale/common/tcpc.h
 create mode 100644 drivers/usb/imx/Kconfig
 create mode 100644 drivers/usb/imx/Makefile
 create mode 100644 drivers/usb/imx/ehci-imx.c
 create mode 100644 drivers/usb/imx/imx-usb-misc.c

-- 
2.28.0

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-12  8:50   ` Marek Vasut
  2020-10-12  6:23 ` [PATCH 2/8] power: regulator: add dummy helper Peng Fan
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

The functionalities in this driver include:
1. USB power delivery support at dead battery
2. Support configure to UFP or DFP mode
3. Support callback to setup external PD switch. When PD process is enabled,
   we call this function only when SINK_VBUS is enabled to avoid system power
   shut down.

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 board/freescale/common/Kconfig  |    6 +
 board/freescale/common/Makefile |    4 +
 board/freescale/common/tcpc.c   | 1018 +++++++++++++++++++++++++++++++
 board/freescale/common/tcpc.h   |  469 ++++++++++++++
 4 files changed, 1497 insertions(+)
 create mode 100644 board/freescale/common/tcpc.c
 create mode 100644 board/freescale/common/tcpc.h

diff --git a/board/freescale/common/Kconfig b/board/freescale/common/Kconfig
index 1b1fd69cb2..eccfc12bfc 100644
--- a/board/freescale/common/Kconfig
+++ b/board/freescale/common/Kconfig
@@ -36,3 +36,9 @@ config VOL_MONITOR_LTC3882_SET
 	help
 	 This option enables LTC3882 voltage monitor set
 	 functionality. It is used by common VID driver.
+
+config USB_TCPC
+	bool "USB Typec port controller simple driver"
+	default n
+	help
+	  Enable USB type-c port controller (TCPC) driver
diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile
index 04e04a6358..8f1ce67f66 100644
--- a/board/freescale/common/Makefile
+++ b/board/freescale/common/Makefile
@@ -79,4 +79,8 @@ obj-$(CONFIG_CMD_ESBC_VALIDATE) += fsl_validate.o cmd_esbc_validate.o
 endif
 obj-$(CONFIG_CHAIN_OF_TRUST) += fsl_chain_of_trust.o
 
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_USB_TCPC) += tcpc.o
+endif
+
 endif
diff --git a/board/freescale/common/tcpc.c b/board/freescale/common/tcpc.c
new file mode 100644
index 0000000000..fb532a3d87
--- /dev/null
+++ b/board/freescale/common/tcpc.c
@@ -0,0 +1,1018 @@
+/*
+ * Copyright 2017,2019 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <i2c.h>
+#include <time.h>
+#include <linux/delay.h>
+#include "tcpc.h"
+
+#ifdef DEBUG
+#define tcpc_debug_log(port, fmt, args...) tcpc_log(port, fmt, ##args)
+#else
+#define tcpc_debug_log(port, fmt, args...)
+#endif
+
+static int tcpc_log(struct tcpc_port *port, const char *fmt, ...)
+{
+	va_list args;
+	int i;
+
+	va_start(args, fmt);
+	i = vscnprintf(port->log_p, port->log_size, fmt, args);
+	va_end(args);
+
+	port->log_size -= i;
+	port->log_p += i;
+
+	return i;
+}
+
+int tcpc_set_cc_to_source(struct tcpc_port *port)
+{
+	uint8_t valb;
+	int err;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	valb = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) |
+			(TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) |
+			(TCPC_ROLE_CTRL_RP_VAL_DEF <<
+			 TCPC_ROLE_CTRL_RP_VAL_SHIFT) | TCPC_ROLE_CTRL_DRP;
+
+	err = dm_i2c_write(port->i2c_dev, TCPC_ROLE_CTRL, &valb, 1);
+	if (err)
+		tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err);
+	return err;
+}
+
+int tcpc_set_cc_to_sink(struct tcpc_port *port)
+{
+	uint8_t valb;
+	int err;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	valb = (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) |
+			(TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT) | TCPC_ROLE_CTRL_DRP;
+
+	err = dm_i2c_write(port->i2c_dev, TCPC_ROLE_CTRL, &valb, 1);
+	if (err)
+		tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err);
+	return err;
+}
+
+
+int tcpc_set_plug_orientation(struct tcpc_port *port, enum typec_cc_polarity polarity)
+{
+	uint8_t valb;
+	int err;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	err = dm_i2c_read(port->i2c_dev, TCPC_TCPC_CTRL, &valb, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	if (polarity == TYPEC_POLARITY_CC2)
+		valb |= TCPC_TCPC_CTRL_ORIENTATION;
+	else
+		valb &= ~TCPC_TCPC_CTRL_ORIENTATION;
+
+	err = dm_i2c_write(port->i2c_dev, TCPC_TCPC_CTRL, &valb, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int tcpc_get_cc_status(struct tcpc_port *port, enum typec_cc_polarity *polarity, enum typec_cc_state *state)
+{
+
+	uint8_t valb_cc, cc2, cc1;
+	int err;
+
+	if (port == NULL || polarity == NULL || state == NULL)
+		return -EINVAL;
+
+	err = dm_i2c_read(port->i2c_dev, TCPC_CC_STATUS, (uint8_t *)&valb_cc, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	tcpc_debug_log(port, "cc status 0x%x\n", valb_cc);
+
+	cc2 = (valb_cc >> TCPC_CC_STATUS_CC2_SHIFT) & TCPC_CC_STATUS_CC2_MASK;
+	cc1 = (valb_cc >> TCPC_CC_STATUS_CC1_SHIFT) & TCPC_CC_STATUS_CC1_MASK;
+
+	if (valb_cc & TCPC_CC_STATUS_LOOK4CONN)
+		return -EFAULT;
+
+	*state = TYPEC_STATE_OPEN;
+
+	if (valb_cc & TCPC_CC_STATUS_TERM) {
+		if (cc2) {
+			*polarity = TYPEC_POLARITY_CC2;
+
+			switch (cc2) {
+			case 0x1:
+				*state = TYPEC_STATE_SNK_DEFAULT;
+				tcpc_log(port, "SNK.Default on CC2\n");
+				break;
+			case 0x2:
+				*state = TYPEC_STATE_SNK_POWER15;
+				tcpc_log(port, "SNK.Power1.5 on CC2\n");
+				break;
+			case 0x3:
+				*state = TYPEC_STATE_SNK_POWER30;
+				tcpc_log(port, "SNK.Power3.0 on CC2\n");
+				break;
+			}
+		} else if (cc1) {
+			*polarity = TYPEC_POLARITY_CC1;
+
+			switch (cc1) {
+			case 0x1:
+				*state = TYPEC_STATE_SNK_DEFAULT;
+				tcpc_log(port, "SNK.Default on CC1\n");
+				break;
+			case 0x2:
+				*state = TYPEC_STATE_SNK_POWER15;
+				tcpc_log(port, "SNK.Power1.5 on CC1\n");
+				break;
+			case 0x3:
+				*state = TYPEC_STATE_SNK_POWER30;
+				tcpc_log(port, "SNK.Power3.0 on CC1\n");
+				break;
+			}
+		} else {
+			*state = TYPEC_STATE_OPEN;
+			return -EPERM;
+		}
+
+	} else {
+		if (cc2) {
+			*polarity = TYPEC_POLARITY_CC2;
+
+			switch (cc2) {
+			case 0x1:
+				if (cc1 == 0x1) {
+					*state = TYPEC_STATE_SRC_BOTH_RA;
+					tcpc_log(port, "SRC.Ra on both CC1 and CC2\n");
+				} else if (cc1 == 0x2) {
+					*state = TYPEC_STATE_SRC_RD_RA;
+					tcpc_log(port, "SRC.Ra on CC2, SRC.Rd on CC1\n");
+				} else if (cc1 == 0x0) {
+					tcpc_log(port, "SRC.Ra only on CC2\n");
+					return -EFAULT;
+				} else
+					return -EFAULT;
+				break;
+			case 0x2:
+				if (cc1 == 0x1) {
+					*state = TYPEC_STATE_SRC_RD_RA;
+					tcpc_log(port, "SRC.Ra on CC1, SRC.Rd on CC2\n");
+				} else if (cc1 == 0x0) {
+					*state = TYPEC_STATE_SRC_RD;
+					tcpc_log(port, "SRC.Rd on CC2\n");
+				} else
+					return -EFAULT;
+				break;
+			case 0x3:
+				*state = TYPEC_STATE_SRC_RESERVED;
+				return -EFAULT;
+			}
+		} else if (cc1) {
+			*polarity = TYPEC_POLARITY_CC1;
+
+			switch (cc1) {
+			case 0x1:
+				tcpc_log(port, "SRC.Ra only on CC1\n");
+				return -EFAULT;
+			case 0x2:
+				*state = TYPEC_STATE_SRC_RD;
+				tcpc_log(port, "SRC.Rd on CC1\n");
+				break;
+			case 0x3:
+				*state = TYPEC_STATE_SRC_RESERVED;
+				return -EFAULT;
+			}
+		} else {
+			*state = TYPEC_STATE_OPEN;
+			return -EPERM;
+		}
+	}
+
+	return 0;
+}
+
+int tcpc_clear_alert(struct tcpc_port *port, uint16_t clear_mask)
+{
+	int err;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	err = dm_i2c_write(port->i2c_dev, TCPC_ALERT, (const uint8_t *)&clear_mask, 2);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int tcpc_send_command(struct tcpc_port *port, uint8_t command)
+{
+	int err;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	err = dm_i2c_write(port->i2c_dev, TCPC_COMMAND, (const uint8_t *)&command, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int tcpc_polling_reg(struct tcpc_port *port, uint8_t reg,
+	uint8_t reg_width, uint16_t mask, uint16_t value, ulong timeout_ms)
+{
+	uint16_t val = 0;
+	int err;
+	ulong start;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	tcpc_debug_log(port, "%s reg 0x%x, mask 0x%x, value 0x%x\n", __func__, reg, mask, value);
+
+	/* TCPC registers is 8 bits or 16 bits */
+	if (reg_width != 1 && reg_width != 2)
+		return -EINVAL;
+
+	start = get_timer(0);	/* Get current timestamp */
+	do {
+		err = dm_i2c_read(port->i2c_dev, reg, (uint8_t *)&val, reg_width);
+		if (err)
+			return -EIO;
+
+		if ((val & mask) == value)
+			return 0;
+	} while (get_timer(0) < (start + timeout_ms));
+
+	return -ETIME;
+}
+
+void tcpc_print_log(struct tcpc_port *port)
+{
+	if (port == NULL)
+		return;
+
+	if (port->log_print == port->log_p) /*nothing to output*/
+		return;
+
+	printf("%s", port->log_print);
+
+	port->log_print = port->log_p;
+}
+
+int tcpc_setup_dfp_mode(struct tcpc_port *port)
+{
+	enum typec_cc_polarity pol;
+	enum typec_cc_state state;
+	int ret;
+
+	if ((port == NULL) || (port->i2c_dev == NULL))
+		return -EINVAL;
+
+	if (tcpc_pd_sink_check_charging(port)) {
+		tcpc_log(port, "%s: Can't apply DFP mode when PD is charging\n",
+			__func__);
+		return -EPERM;
+	}
+
+	tcpc_set_cc_to_source(port);
+
+	ret = tcpc_send_command(port, TCPC_CMD_LOOK4CONNECTION);
+	if (ret)
+		return ret;
+
+	/* At least wait tCcStatusDelay + tTCPCFilter + tCcTCPCSampleRate (max) = 200us + 500us + ?ms
+	 * PTN5110 datasheet does not contain the sample rate value, according other productions,
+	 * the sample rate is at ms level, about 2 ms -10ms. So wait 100ms should be enough.
+	 */
+	mdelay(100);
+
+	ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_CC_STATUS, TCPC_ALERT_CC_STATUS, 100);
+	if (ret) {
+		tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_CC_STATUS bit failed, ret = %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = tcpc_get_cc_status(port, &pol, &state);
+	tcpc_clear_alert(port, TCPC_ALERT_CC_STATUS);
+
+	if (!ret) {
+		/* If presenting as Rd/audio mode/open, return */
+		if (state != TYPEC_STATE_SRC_RD_RA && state != TYPEC_STATE_SRC_RD)
+			return -EPERM;
+
+		if (pol == TYPEC_POLARITY_CC1)
+			tcpc_debug_log(port, "polarity cc1\n");
+		else
+			tcpc_debug_log(port, "polarity cc2\n");
+
+		if (port->ss_sel_func)
+			port->ss_sel_func(pol);
+
+		ret = tcpc_set_plug_orientation(port, pol);
+		if (ret)
+			return ret;
+
+		/* Enable source vbus default voltage */
+		ret = tcpc_send_command(port, TCPC_CMD_SRC_VBUS_DEFAULT);
+		if (ret)
+			return ret;
+
+		/* The max vbus on time is 200ms, we add margin 100ms */
+		mdelay(300);
+
+	}
+
+	return 0;
+}
+
+int tcpc_setup_ufp_mode(struct tcpc_port *port)
+{
+	enum typec_cc_polarity pol;
+	enum typec_cc_state state;
+	int ret;
+
+	if ((port == NULL) || (port->i2c_dev == NULL))
+		return -EINVAL;
+
+	/* Check if the PD charge is working. If not, need to configure CC role for UFP */
+	if (!tcpc_pd_sink_check_charging(port)) {
+
+		/* Disable the source vbus once it is enabled by DFP mode */
+		tcpc_disable_src_vbus(port);
+
+		tcpc_set_cc_to_sink(port);
+
+		ret = tcpc_send_command(port, TCPC_CMD_LOOK4CONNECTION);
+		if (ret)
+			return ret;
+
+		/* At least wait tCcStatusDelay + tTCPCFilter + tCcTCPCSampleRate (max) = 200us + 500us + ?ms
+		 * PTN5110 datasheet does not contain the sample rate value, according other productions,
+		 * the sample rate is at ms level, about 2 ms -10ms. So wait 100ms should be enough.
+		 */
+		mdelay(100);
+
+		ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_CC_STATUS, TCPC_ALERT_CC_STATUS, 100);
+		if (ret) {
+			tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_CC_STATUS bit failed, ret = %d\n",
+				__func__, ret);
+			return ret;
+		}
+
+		ret = tcpc_get_cc_status(port, &pol, &state);
+		tcpc_clear_alert(port, TCPC_ALERT_CC_STATUS);
+
+	} else {
+		ret = tcpc_get_cc_status(port, &pol, &state);
+	}
+
+	if (!ret) {
+		/* If presenting not as sink, then return */
+		if (state != TYPEC_STATE_SNK_DEFAULT && state != TYPEC_STATE_SNK_POWER15 &&
+			state != TYPEC_STATE_SNK_POWER30)
+			return -EPERM;
+
+		if (pol == TYPEC_POLARITY_CC1)
+			tcpc_debug_log(port, "polarity cc1\n");
+		else
+			tcpc_debug_log(port, "polarity cc2\n");
+
+		if (port->ss_sel_func)
+			port->ss_sel_func(pol);
+
+		ret = tcpc_set_plug_orientation(port, pol);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int tcpc_disable_src_vbus(struct tcpc_port *port)
+{
+	int ret;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	/* Disable VBUS*/
+	ret = tcpc_send_command(port, TCPC_CMD_DISABLE_SRC_VBUS);
+	if (ret)
+		return ret;
+
+	/* The max vbus off time is 0.5ms, we add margin 0.5 ms */
+	mdelay(1);
+
+	return 0;
+}
+
+int tcpc_disable_sink_vbus(struct tcpc_port *port)
+{
+	int ret;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	/* Disable SINK VBUS*/
+	ret = tcpc_send_command(port, TCPC_CMD_DISABLE_SINK_VBUS);
+	if (ret)
+		return ret;
+
+	/* The max vbus off time is 0.5ms, we add margin 0.5 ms */
+	mdelay(1);
+
+	return 0;
+}
+
+
+static int tcpc_pd_receive_message(struct tcpc_port *port, struct pd_message *msg)
+{
+	int ret;
+	uint8_t cnt;
+	uint16_t val;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	/* Generally the max tSenderResponse is 30ms, max tTypeCSendSourceCap is 200ms, we set the timeout to 500ms */
+	ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_RX_STATUS, TCPC_ALERT_RX_STATUS, 500);
+	if (ret) {
+		tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_RX_STATUS bit failed, ret = %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	cnt = 0;
+	ret = dm_i2c_read(port->i2c_dev, TCPC_RX_BYTE_CNT, (uint8_t *)&cnt, 1);
+	if (ret)
+		return -EIO;
+
+	if (cnt > 0) {
+		ret = dm_i2c_read(port->i2c_dev, TCPC_RX_BUF_FRAME_TYPE, (uint8_t *)msg, cnt);
+		if (ret)
+			return -EIO;
+
+		/* Clear RX status alert bit */
+		val = TCPC_ALERT_RX_STATUS;
+		ret = dm_i2c_write(port->i2c_dev, TCPC_ALERT, (const uint8_t *)&val, 2);
+		if (ret)
+			return -EIO;
+	}
+
+	return cnt;
+}
+
+static int tcpc_pd_transmit_message(struct tcpc_port *port, struct pd_message *msg_p, uint8_t bytes)
+{
+	int ret;
+	uint8_t valb;
+	uint16_t val;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	if (msg_p == NULL || bytes <= 0)
+		return -EINVAL;
+
+	ret = dm_i2c_write(port->i2c_dev, TCPC_TX_BYTE_CNT, (const uint8_t *)&bytes, 1);
+	if (ret)
+		return -EIO;
+
+	ret = dm_i2c_write(port->i2c_dev, TCPC_TX_HDR, (const uint8_t *)&(msg_p->header), bytes);
+	if (ret)
+		return -EIO;
+
+	valb = (3 << TCPC_TRANSMIT_RETRY_SHIFT) | (TCPC_TX_SOP << TCPC_TRANSMIT_TYPE_SHIFT);
+	ret = dm_i2c_write(port->i2c_dev, TCPC_TRANSMIT, (const uint8_t *)&valb, 1);
+	if (ret)
+		return -EIO;
+
+	/* Max tReceive is 1.1ms, we set to 5ms timeout */
+	ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_TX_SUCCESS, TCPC_ALERT_TX_SUCCESS, 5);
+	if (ret) {
+		if (ret == -ETIME) {
+			ret = dm_i2c_read(port->i2c_dev, TCPC_ALERT, (uint8_t *)&val, 2);
+			if (ret)
+				return -EIO;
+
+			if (val & TCPC_ALERT_TX_FAILED)
+				tcpc_log(port, "%s: PD TX FAILED, ALERT = 0x%x\n", __func__, val);
+
+			if (val & TCPC_ALERT_TX_DISCARDED)
+				tcpc_log(port, "%s: PD TX DISCARDED, ALERT = 0x%x\n", __func__, val);
+
+		} else {
+			tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_TX_SUCCESS bit failed, ret = %d\n",
+				__func__, ret);
+		}
+	} else {
+		port->tx_msg_id = (port->tx_msg_id + 1) & PD_HEADER_ID_MASK;
+	}
+
+	/* Clear ALERT status */
+	val &= (TCPC_ALERT_TX_FAILED | TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_TX_SUCCESS);
+	ret = dm_i2c_write(port->i2c_dev, TCPC_ALERT, (const uint8_t *)&val, 2);
+	if (ret)
+		return -EIO;
+
+	return ret;
+}
+
+static void tcpc_log_source_caps(struct tcpc_port *port, struct pd_message *msg, unsigned int capcount)
+{
+	int i;
+
+	for (i = 0; i < capcount; i++) {
+		u32 pdo = msg->payload[i];
+		enum pd_pdo_type type = pdo_type(pdo);
+
+		tcpc_log(port, "PDO %d: type %d, ",
+			 i, type);
+
+		switch (type) {
+		case PDO_TYPE_FIXED:
+			tcpc_log(port, "%u mV, %u mA [%s%s%s%s%s%s]\n",
+				  pdo_fixed_voltage(pdo),
+				  pdo_max_current(pdo),
+				  (pdo & PDO_FIXED_DUAL_ROLE) ?
+							"R" : "",
+				  (pdo & PDO_FIXED_SUSPEND) ?
+							"S" : "",
+				  (pdo & PDO_FIXED_HIGHER_CAP) ?
+							"H" : "",
+				  (pdo & PDO_FIXED_USB_COMM) ?
+							"U" : "",
+				  (pdo & PDO_FIXED_DATA_SWAP) ?
+							"D" : "",
+				  (pdo & PDO_FIXED_EXTPOWER) ?
+							"E" : "");
+			break;
+		case PDO_TYPE_VAR:
+			tcpc_log(port, "%u-%u mV, %u mA\n",
+				  pdo_min_voltage(pdo),
+				  pdo_max_voltage(pdo),
+				  pdo_max_current(pdo));
+			break;
+		case PDO_TYPE_BATT:
+			tcpc_log(port, "%u-%u mV, %u mW\n",
+				  pdo_min_voltage(pdo),
+				  pdo_max_voltage(pdo),
+				  pdo_max_power(pdo));
+			break;
+		default:
+			tcpc_log(port, "undefined\n");
+			break;
+		}
+	}
+}
+
+static int tcpc_pd_select_pdo(struct pd_message *msg, uint32_t capcount, uint32_t max_snk_mv, uint32_t max_snk_ma)
+{
+	unsigned int i, max_mw = 0, max_mv = 0;
+	int ret = -EINVAL;
+
+	/*
+	 * Select the source PDO providing the most power while staying within
+	 * the board's voltage limits. Prefer PDO providing exp
+	 */
+	for (i = 0; i < capcount; i++) {
+		u32 pdo = msg->payload[i];
+		enum pd_pdo_type type = pdo_type(pdo);
+		unsigned int mv, ma, mw;
+
+		if (type == PDO_TYPE_FIXED)
+			mv = pdo_fixed_voltage(pdo);
+		else
+			mv = pdo_min_voltage(pdo);
+
+		if (type == PDO_TYPE_BATT) {
+			mw = pdo_max_power(pdo);
+		} else {
+			ma = min(pdo_max_current(pdo),
+				 max_snk_ma);
+			mw = ma * mv / 1000;
+		}
+
+		/* Perfer higher voltages if available */
+		if ((mw > max_mw || (mw == max_mw && mv > max_mv)) &&
+		    mv <= max_snk_mv) {
+			ret = i;
+			max_mw = mw;
+			max_mv = mv;
+		}
+	}
+
+	return ret;
+}
+
+static int tcpc_pd_build_request(struct tcpc_port *port,
+										struct pd_message *msg,
+										uint32_t capcount,
+										uint32_t max_snk_mv,
+										uint32_t max_snk_ma,
+										uint32_t max_snk_mw,
+										uint32_t operating_snk_mw,
+										uint32_t *rdo)
+{
+	unsigned int mv, ma, mw, flags;
+	unsigned int max_ma, max_mw;
+	enum pd_pdo_type type;
+	int index;
+	u32 pdo;
+
+	index = tcpc_pd_select_pdo(msg, capcount, max_snk_mv, max_snk_ma);
+	if (index < 0)
+		return -EINVAL;
+
+	pdo = msg->payload[index];
+	type = pdo_type(pdo);
+
+	if (type == PDO_TYPE_FIXED)
+		mv = pdo_fixed_voltage(pdo);
+	else
+		mv = pdo_min_voltage(pdo);
+
+	/* Select maximum available current within the board's power limit */
+	if (type == PDO_TYPE_BATT) {
+		mw = pdo_max_power(pdo);
+		ma = 1000 * min(mw, max_snk_mw) / mv;
+	} else {
+		ma = min(pdo_max_current(pdo),
+			 1000 * max_snk_mw / mv);
+	}
+	ma = min(ma, max_snk_ma);
+
+	/* XXX: Any other flags need to be set? */
+	flags = 0;
+
+	/* Set mismatch bit if offered power is less than operating power */
+	mw = ma * mv / 1000;
+	max_ma = ma;
+	max_mw = mw;
+	if (mw < operating_snk_mw) {
+		flags |= RDO_CAP_MISMATCH;
+		max_mw = operating_snk_mw;
+		max_ma = max_mw * 1000 / mv;
+	}
+
+	if (type == PDO_TYPE_BATT) {
+		*rdo = RDO_BATT(index + 1, mw, max_mw, flags);
+
+		tcpc_log(port, "Requesting PDO %d: %u mV, %u mW%s\n",
+			 index, mv, mw,
+			 flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");
+	} else {
+		*rdo = RDO_FIXED(index + 1, ma, max_ma, flags);
+
+		tcpc_log(port, "Requesting PDO %d: %u mV, %u mA%s\n",
+			 index, mv, ma,
+			 flags & RDO_CAP_MISMATCH ? " [mismatch]" : "");
+	}
+
+	return 0;
+}
+
+static void tcpc_pd_sink_process(struct tcpc_port *port)
+{
+	int ret;
+	uint8_t msgtype;
+	uint32_t objcnt;
+	struct pd_message msg;
+	enum pd_sink_state pd_state = WAIT_SOURCE_CAP;
+
+	while (tcpc_pd_receive_message(port, &msg) > 0) {
+
+		msgtype = pd_header_type(msg.header);
+		objcnt = pd_header_cnt_le(msg.header);
+
+		tcpc_debug_log(port, "get msg, type %d, cnt %d\n", msgtype, objcnt);
+
+		switch (pd_state) {
+		case WAIT_SOURCE_CAP:
+		case SINK_READY:
+			if (msgtype != PD_DATA_SOURCE_CAP)
+				continue;
+
+			uint32_t rdo = 0;
+
+			tcpc_log_source_caps(port, &msg, objcnt);
+
+			tcpc_pd_build_request(port, &msg, objcnt,
+				port->cfg.max_snk_mv, port->cfg.max_snk_ma,
+				port->cfg.max_snk_mw, port->cfg.op_snk_mv,
+				&rdo);
+
+			memset(&msg, 0, sizeof(msg));
+			msg.header = PD_HEADER(PD_DATA_REQUEST, 0, 0, port->tx_msg_id, 1);  /* power sink, data device, id 0, len 1 */
+			msg.payload[0] = rdo;
+
+			ret = tcpc_pd_transmit_message(port, &msg, 6);
+			if (ret)
+				tcpc_log(port, "send request failed\n");
+			else
+				pd_state = WAIT_SOURCE_ACCEPT;
+
+			break;
+		case WAIT_SOURCE_ACCEPT:
+			if (objcnt > 0) /* Should be ctrl message */
+				continue;
+
+			if (msgtype == PD_CTRL_ACCEPT) {
+				pd_state = WAIT_SOURCE_READY;
+				tcpc_log(port, "Source accept request\n");
+			} else if (msgtype == PD_CTRL_REJECT) {
+				tcpc_log(port, "Source reject request\n");
+				return;
+			}
+
+			break;
+		case WAIT_SOURCE_READY:
+			if (objcnt > 0) /* Should be ctrl message */
+				continue;
+
+			if (msgtype == PD_CTRL_PS_RDY) {
+				tcpc_log(port, "PD source ready!\n");
+				pd_state = SINK_READY;
+			}
+
+			break;
+		default:
+			tcpc_log(port, "unexpect status: %u\n", pd_state);
+			break;
+		}
+	}
+}
+
+bool tcpc_pd_sink_check_charging(struct tcpc_port *port)
+{
+	uint8_t valb;
+	int err;
+	enum typec_cc_polarity pol;
+	enum typec_cc_state state;
+
+	if (port == NULL)
+		return false;
+
+	/* Check the CC status, must be sink */
+	err = tcpc_get_cc_status(port, &pol, &state);
+	if (err || (state != TYPEC_STATE_SNK_POWER15
+		&& state != TYPEC_STATE_SNK_POWER30
+		&& state != TYPEC_STATE_SNK_DEFAULT)) {
+		tcpc_debug_log(port, "TCPC wrong state for PD charging, err = %d, CC = 0x%x\n",
+			err, state);
+		return false;
+	}
+
+	/* Check the VBUS PRES and SINK VBUS for dead battery */
+	err = dm_i2c_read(port->i2c_dev, TCPC_POWER_STATUS, &valb, 1);
+	if (err) {
+		tcpc_debug_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return false;
+	}
+
+	if (!(valb & TCPC_POWER_STATUS_VBUS_PRES)) {
+		tcpc_debug_log(port, "VBUS NOT PRES \n");
+		return false;
+	}
+
+	if (!(valb & TCPC_POWER_STATUS_SINKING_VBUS)) {
+		tcpc_debug_log(port, "SINK VBUS is not enabled for dead battery\n");
+		return false;
+	}
+
+	return true;
+}
+
+static int tcpc_pd_sink_disable(struct tcpc_port *port)
+{
+	uint8_t valb;
+	int err;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	port->pd_state = UNATTACH;
+
+	/* Check the VBUS PRES and SINK VBUS for dead battery */
+	err = dm_i2c_read(port->i2c_dev, TCPC_POWER_STATUS, &valb, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	if ((valb & TCPC_POWER_STATUS_VBUS_PRES) && (valb & TCPC_POWER_STATUS_SINKING_VBUS)) {
+		dm_i2c_read(port->i2c_dev, TCPC_POWER_CTRL, (uint8_t *)&valb, 1);
+		valb &= ~TCPC_POWER_CTRL_AUTO_DISCH_DISCO; /* disable AutoDischargeDisconnect */
+		dm_i2c_write(port->i2c_dev, TCPC_POWER_CTRL, (const uint8_t *)&valb, 1);
+
+		tcpc_disable_sink_vbus(port);
+	}
+
+	if (port->cfg.switch_setup_func)
+		port->cfg.switch_setup_func(port);
+
+	return 0;
+}
+
+static int tcpc_pd_sink_init(struct tcpc_port *port)
+{
+	uint8_t valb;
+	uint16_t val;
+	int err;
+	enum typec_cc_polarity pol;
+	enum typec_cc_state state;
+
+	if (port == NULL)
+		return -EINVAL;
+
+	port->pd_state = UNATTACH;
+
+	/* Check the VBUS PRES and SINK VBUS for dead battery */
+	err = dm_i2c_read(port->i2c_dev, TCPC_POWER_STATUS, &valb, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	if (!(valb & TCPC_POWER_STATUS_VBUS_PRES)) {
+		tcpc_debug_log(port, "VBUS NOT PRES \n");
+		return -EPERM;
+	}
+
+	if (!(valb & TCPC_POWER_STATUS_SINKING_VBUS)) {
+		tcpc_debug_log(port, "SINK VBUS is not enabled for dead battery\n");
+		return -EPERM;
+	}
+
+	err = dm_i2c_read(port->i2c_dev, TCPC_ALERT, (uint8_t *)&val, 2);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	if (!(val & TCPC_ALERT_CC_STATUS)) {
+		tcpc_debug_log(port, "CC STATUS not detected for dead battery\n");
+		return -EPERM;
+	}
+
+	err = tcpc_get_cc_status(port, &pol, &state);
+	if (err || (state != TYPEC_STATE_SNK_POWER15
+		&& state != TYPEC_STATE_SNK_POWER30
+		&& state != TYPEC_STATE_SNK_DEFAULT)) {
+		tcpc_log(port, "TCPC wrong state for dead battery, err = %d, CC = 0x%x\n",
+			err, state);
+		return -EPERM;
+	} else {
+		err = tcpc_set_plug_orientation(port, pol);
+		if (err) {
+			tcpc_log(port, "TCPC set plug orientation failed, err = %d\n", err);
+			return err;
+		}
+		port->pd_state = ATTACHED;
+	}
+
+	dm_i2c_read(port->i2c_dev, TCPC_POWER_CTRL, (uint8_t *)&valb, 1);
+	valb &= ~TCPC_POWER_CTRL_AUTO_DISCH_DISCO; /* disable AutoDischargeDisconnect */
+	dm_i2c_write(port->i2c_dev, TCPC_POWER_CTRL, (const uint8_t *)&valb, 1);
+
+	if (port->cfg.switch_setup_func)
+		port->cfg.switch_setup_func(port);
+
+	/* As sink role */
+	valb = 0x00;
+	err = dm_i2c_write(port->i2c_dev, TCPC_MSG_HDR_INFO, (const uint8_t *)&valb, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	/* Enable rx */
+	valb = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET;
+	err = dm_i2c_write(port->i2c_dev, TCPC_RX_DETECT, (const uint8_t *)&valb, 1);
+	if (err) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err);
+		return -EIO;
+	}
+
+	tcpc_pd_sink_process(port);
+
+	return 0;
+}
+
+int tcpc_init(struct tcpc_port *port, struct tcpc_port_config config, ss_mux_sel ss_sel_func)
+{
+	int ret;
+	uint8_t valb;
+	uint16_t vid, pid;
+	struct udevice *bus;
+	struct udevice *i2c_dev = NULL;
+
+	memset(port, 0, sizeof(struct tcpc_port));
+
+	if (port == NULL)
+		return -EINVAL;
+
+	port->cfg = config;
+	port->tx_msg_id = 0;
+	port->ss_sel_func = ss_sel_func;
+	port->log_p = (char *)&(port->logbuffer);
+	port->log_size = TCPC_LOG_BUFFER_SIZE;
+	port->log_print = port->log_p;
+	memset(&(port->logbuffer), 0, TCPC_LOG_BUFFER_SIZE);
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, port->cfg.i2c_bus, &bus);
+	if (ret) {
+		printf("%s: Can't find bus\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = dm_i2c_probe(bus, port->cfg.addr, 0, &i2c_dev);
+	if (ret) {
+		printf("%s: Can't find device id=0x%x\n",
+			__func__, config.addr);
+		return -ENODEV;
+	}
+
+	port->i2c_dev = i2c_dev;
+
+	/* Check the Initialization Status bit in 1s */
+	ret = tcpc_polling_reg(port, TCPC_POWER_STATUS, 1, TCPC_POWER_STATUS_UNINIT, 0, 1000);
+	if (ret) {
+		tcpc_log(port, "%s: Polling TCPC POWER STATUS Initialization Status bit failed, ret = %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	dm_i2c_read(port->i2c_dev, TCPC_POWER_STATUS, &valb, 1);
+	tcpc_debug_log(port, "POWER STATUS: 0x%x\n", valb);
+
+	/* Clear AllRegistersResetToDefault */
+	valb = 0x80;
+	ret = dm_i2c_write(port->i2c_dev, TCPC_FAULT_STATUS, (const uint8_t *)&valb, 1);
+	if (ret) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, ret);
+		return -EIO;
+	}
+
+	/* Read Vendor ID and Product ID */
+	ret = dm_i2c_read(port->i2c_dev, TCPC_VENDOR_ID, (uint8_t *)&vid, 2);
+	if (ret) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, ret);
+		return -EIO;
+	}
+
+	ret = dm_i2c_read(port->i2c_dev, TCPC_PRODUCT_ID, (uint8_t *)&pid, 2);
+	if (ret) {
+		tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, ret);
+		return -EIO;
+	}
+
+	tcpc_log(port, "TCPC:  Vendor ID [0x%x], Product ID [0x%x], Addr [I2C%u 0x%x]\n",
+		vid, pid, port->cfg.i2c_bus, port->cfg.addr);
+
+	if (!port->cfg.disable_pd) {
+		if  (port->cfg.port_type == TYPEC_PORT_UFP
+			|| port->cfg.port_type == TYPEC_PORT_DRP)
+			tcpc_pd_sink_init(port);
+	} else {
+		tcpc_pd_sink_disable(port);
+	}
+
+	tcpc_clear_alert(port, 0xffff);
+
+	tcpc_print_log(port);
+
+	return 0;
+}
diff --git a/board/freescale/common/tcpc.h b/board/freescale/common/tcpc.h
new file mode 100644
index 0000000000..ff749518a8
--- /dev/null
+++ b/board/freescale/common/tcpc.h
@@ -0,0 +1,469 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __TCPCI_H
+#define __TCPCI_H
+
+#include <dm.h>
+
+#define TCPC_VENDOR_ID			0x0
+#define TCPC_PRODUCT_ID			0x2
+
+#define TCPC_ALERT					0x10
+#define TCPC_ALERT_VBUS_DISCNCT		BIT(11)
+#define TCPC_ALERT_RX_BUF_OVF		BIT(10)
+#define TCPC_ALERT_FAULT			BIT(9)
+#define TCPC_ALERT_V_ALARM_LO		BIT(8)
+#define TCPC_ALERT_V_ALARM_HI		BIT(7)
+#define TCPC_ALERT_TX_SUCCESS		BIT(6)
+#define TCPC_ALERT_TX_DISCARDED		BIT(5)
+#define TCPC_ALERT_TX_FAILED		BIT(4)
+#define TCPC_ALERT_RX_HARD_RST		BIT(3)
+#define TCPC_ALERT_RX_STATUS		BIT(2)
+#define TCPC_ALERT_POWER_STATUS		BIT(1)
+#define TCPC_ALERT_CC_STATUS		BIT(0)
+
+#define TCPC_TCPC_CTRL				0x19
+#define TCPC_TCPC_CTRL_BIST_MODE	BIT(1)
+#define TCPC_TCPC_CTRL_ORIENTATION	BIT(0)
+
+#define TCPC_ROLE_CTRL				0x1a
+#define TCPC_ROLE_CTRL_DRP			BIT(6)
+#define TCPC_ROLE_CTRL_RP_VAL_SHIFT	4
+#define TCPC_ROLE_CTRL_RP_VAL_MASK	0x3
+#define TCPC_ROLE_CTRL_RP_VAL_DEF	0x0
+#define TCPC_ROLE_CTRL_RP_VAL_1_5	0x1
+#define TCPC_ROLE_CTRL_RP_VAL_3_0	0x2
+#define TCPC_ROLE_CTRL_CC2_SHIFT	2
+#define TCPC_ROLE_CTRL_CC2_MASK		0x3
+#define TCPC_ROLE_CTRL_CC1_SHIFT	0
+#define TCPC_ROLE_CTRL_CC1_MASK		0x3
+#define TCPC_ROLE_CTRL_CC_RA		0x0
+#define TCPC_ROLE_CTRL_CC_RP		0x1
+#define TCPC_ROLE_CTRL_CC_RD		0x2
+#define TCPC_ROLE_CTRL_CC_OPEN		0x3
+
+#define TCPC_POWER_CTRL						0x1c
+#define TCPC_POWER_CTRL_EN_VCONN			BIT(0)
+#define TCPC_POWER_CTRL_VCONN_POWER			BIT(1)
+#define TCPC_POWER_CTRL_FORCE_DISCH			BIT(2)
+#define TCPC_POWER_CTRL_EN_BLEED_CH			BIT(3)
+#define TCPC_POWER_CTRL_AUTO_DISCH_DISCO	BIT(4)
+#define TCPC_POWER_CTRL_DIS_V_ALARMS		BIT(5)
+#define TCPC_POWER_CTRL_VBUS_V_MONITOR		BIT(6)
+
+#define TCPC_CC_STATUS					0x1d
+#define TCPC_CC_STATUS_LOOK4CONN		BIT(5)
+#define TCPC_CC_STATUS_TERM				BIT(4)
+#define TCPC_CC_STATUS_CC2_SHIFT		2
+#define TCPC_CC_STATUS_CC2_MASK			0x3
+#define TCPC_CC_STATUS_CC1_SHIFT		0
+#define TCPC_CC_STATUS_CC1_MASK			0x3
+
+#define TCPC_POWER_STATUS				0x1e
+#define TCPC_POWER_STATUS_UNINIT		BIT(6)
+#define TCPC_POWER_STATUS_VBUS_DET		BIT(3)
+#define TCPC_POWER_STATUS_VBUS_PRES		BIT(2)
+#define TCPC_POWER_STATUS_SINKING_VBUS	BIT(0)
+
+#define TCPC_FAULT_STATUS               0x1f
+
+#define TCPC_COMMAND					0x23
+#define TCPC_CMD_WAKE_I2C				0x11
+#define TCPC_CMD_DISABLE_VBUS_DETECT	0x22
+#define TCPC_CMD_ENABLE_VBUS_DETECT		0x33
+#define TCPC_CMD_DISABLE_SINK_VBUS		0x44
+#define TCPC_CMD_SINK_VBUS				0x55
+#define TCPC_CMD_DISABLE_SRC_VBUS		0x66
+#define TCPC_CMD_SRC_VBUS_DEFAULT		0x77
+#define TCPC_CMD_SRC_VBUS_HIGH			0x88
+#define TCPC_CMD_LOOK4CONNECTION		0x99
+#define TCPC_CMD_RXONEMORE				0xAA
+#define TCPC_CMD_I2C_IDLE				0xFF
+
+#define TCPC_DEV_CAP_1					0x24
+#define TCPC_DEV_CAP_2					0x26
+#define TCPC_STD_INPUT_CAP				0x28
+#define TCPC_STD_OUTPUT_CAP				0x29
+
+#define TCPC_MSG_HDR_INFO				0x2e
+#define TCPC_MSG_HDR_INFO_DATA_ROLE		BIT(3)
+#define TCPC_MSG_HDR_INFO_PWR_ROLE		BIT(0)
+#define TCPC_MSG_HDR_INFO_REV_SHIFT		1
+#define TCPC_MSG_HDR_INFO_REV_MASK		0x3
+
+#define TCPC_RX_DETECT					0x2f
+#define TCPC_RX_DETECT_HARD_RESET		BIT(5)
+#define TCPC_RX_DETECT_SOP				BIT(0)
+
+#define TCPC_RX_BYTE_CNT				0x30
+#define TCPC_RX_BUF_FRAME_TYPE			0x31
+#define TCPC_RX_HDR						0x32
+#define TCPC_RX_DATA					0x34 /* through 0x4f */
+
+#define TCPC_TRANSMIT					0x50
+#define TCPC_TRANSMIT_RETRY_SHIFT		4
+#define TCPC_TRANSMIT_RETRY_MASK		0x3
+#define TCPC_TRANSMIT_TYPE_SHIFT		0
+#define TCPC_TRANSMIT_TYPE_MASK			0x7
+
+#define TCPC_TX_BYTE_CNT				0x51
+#define TCPC_TX_HDR						0x52
+#define TCPC_TX_DATA					0x54 /* through 0x6f */
+
+#define TCPC_VBUS_VOLTAGE					0x70
+#define TCPC_VBUS_VOL_MASK					0x3ff
+#define TCPC_VBUS_VOL_SCALE_FACTOR_MASK		0xc00
+#define TCPC_VBUS_VOL_SCALE_FACTOR_SHIFT	10
+#define TCPC_VBUS_VOL_MV_UNIT				25
+
+#define TCPC_VBUS_SINK_DISCONNECT_THRESH	0x72
+#define TCPC_VBUS_STOP_DISCHARGE_THRESH		0x74
+#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG		0x76
+#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG		0x78
+
+enum typec_role {
+	TYPEC_SINK,
+	TYPEC_SOURCE,
+	TYPEC_ROLE_UNKNOWN,
+};
+
+enum typec_data_role {
+	TYPEC_DEVICE,
+	TYPEC_HOST,
+};
+
+enum typec_cc_polarity {
+	TYPEC_POLARITY_CC1,
+	TYPEC_POLARITY_CC2,
+};
+
+enum typec_cc_state {
+	TYPEC_STATE_OPEN,
+	TYPEC_STATE_SRC_BOTH_RA,
+	TYPEC_STATE_SRC_RD_RA,
+	TYPEC_STATE_SRC_RD,
+	TYPEC_STATE_SRC_RESERVED,
+	TYPEC_STATE_SNK_DEFAULT,
+	TYPEC_STATE_SNK_POWER15,
+	TYPEC_STATE_SNK_POWER30,
+};
+
+
+/* USB PD Messages */
+enum pd_ctrl_msg_type {
+	/* 0 Reserved */
+	PD_CTRL_GOOD_CRC = 1,
+	PD_CTRL_GOTO_MIN = 2,
+	PD_CTRL_ACCEPT = 3,
+	PD_CTRL_REJECT = 4,
+	PD_CTRL_PING = 5,
+	PD_CTRL_PS_RDY = 6,
+	PD_CTRL_GET_SOURCE_CAP = 7,
+	PD_CTRL_GET_SINK_CAP = 8,
+	PD_CTRL_DR_SWAP = 9,
+	PD_CTRL_PR_SWAP = 10,
+	PD_CTRL_VCONN_SWAP = 11,
+	PD_CTRL_WAIT = 12,
+	PD_CTRL_SOFT_RESET = 13,
+	/* 14-15 Reserved */
+};
+
+enum pd_data_msg_type {
+	/* 0 Reserved */
+	PD_DATA_SOURCE_CAP = 1,
+	PD_DATA_REQUEST = 2,
+	PD_DATA_BIST = 3,
+	PD_DATA_SINK_CAP = 4,
+	/* 5-14 Reserved */
+	PD_DATA_VENDOR_DEF = 15,
+};
+
+enum tcpc_transmit_type {
+	TCPC_TX_SOP = 0,
+	TCPC_TX_SOP_PRIME = 1,
+	TCPC_TX_SOP_PRIME_PRIME = 2,
+	TCPC_TX_SOP_DEBUG_PRIME = 3,
+	TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4,
+	TCPC_TX_HARD_RESET = 5,
+	TCPC_TX_CABLE_RESET = 6,
+	TCPC_TX_BIST_MODE_2 = 7
+};
+
+enum pd_sink_state{
+	UNATTACH = 0,
+	ATTACHED,
+	WAIT_SOURCE_CAP,
+	WAIT_SOURCE_ACCEPT,
+	WAIT_SOURCE_READY,
+	SINK_READY,
+};
+
+
+#define PD_REV10        0x0
+#define PD_REV20        0x1
+
+#define PD_HEADER_CNT_SHIFT     12
+#define PD_HEADER_CNT_MASK      0x7
+#define PD_HEADER_ID_SHIFT      9
+#define PD_HEADER_ID_MASK       0x7
+#define PD_HEADER_PWR_ROLE      BIT(8)
+#define PD_HEADER_REV_SHIFT     6
+#define PD_HEADER_REV_MASK      0x3
+#define PD_HEADER_DATA_ROLE     BIT(5)
+#define PD_HEADER_TYPE_SHIFT    0
+#define PD_HEADER_TYPE_MASK     0xf
+
+#define PD_HEADER(type, pwr, data, id, cnt)                             \
+	((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) |     \
+	 ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) |             \
+	 ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) |             \
+	 (PD_REV20 << PD_HEADER_REV_SHIFT) |                            \
+	 (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) |           \
+	 (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT))
+
+
+static inline unsigned int pd_header_cnt(uint16_t header)
+{
+	return (header >> PD_HEADER_CNT_SHIFT) & PD_HEADER_CNT_MASK;
+}
+
+static inline unsigned int pd_header_cnt_le(__le16 header)
+{
+	return pd_header_cnt(le16_to_cpu(header));
+}
+
+static inline unsigned int pd_header_type(uint16_t header)
+{
+	return (header >> PD_HEADER_TYPE_SHIFT) & PD_HEADER_TYPE_MASK;
+}
+
+static inline unsigned int pd_header_type_le(__le16 header)
+{
+	return pd_header_type(le16_to_cpu(header));
+}
+
+#define PD_MAX_PAYLOAD          7
+
+struct pd_message {
+	uint8_t   frametype;
+	uint16_t  header;
+	uint32_t  payload[PD_MAX_PAYLOAD];
+} __packed;
+
+enum pd_pdo_type {
+	PDO_TYPE_FIXED = 0,
+	PDO_TYPE_BATT = 1,
+	PDO_TYPE_VAR = 2,
+};
+
+
+#define PDO_TYPE_SHIFT          30
+#define PDO_TYPE_MASK           0x3
+
+#define PDO_TYPE(t)     ((t) << PDO_TYPE_SHIFT)
+
+#define PDO_VOLT_MASK           0x3ff
+#define PDO_CURR_MASK           0x3ff
+#define PDO_PWR_MASK            0x3ff
+
+#define PDO_FIXED_DUAL_ROLE     BIT(29) /* Power role swap supported */
+#define PDO_FIXED_SUSPEND       BIT(28) /* USB Suspend supported (Source) */
+#define PDO_FIXED_HIGHER_CAP    BIT(28) /* Requires more than vSafe5V (Sink) */
+#define PDO_FIXED_EXTPOWER      BIT(27) /* Externally powered */
+#define PDO_FIXED_USB_COMM      BIT(26) /* USB communications capable */
+#define PDO_FIXED_DATA_SWAP     BIT(25) /* Data role swap supported */
+#define PDO_FIXED_VOLT_SHIFT    10      /* 50mV units */
+#define PDO_FIXED_CURR_SHIFT    0       /* 10mA units */
+
+#define PDO_FIXED_VOLT(mv)      ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT)
+#define PDO_FIXED_CURR(ma)      ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT)
+
+#define PDO_FIXED(mv, ma, flags)                        \
+	(PDO_TYPE(PDO_TYPE_FIXED) | (flags) |           \
+	 PDO_FIXED_VOLT(mv) | PDO_FIXED_CURR(ma))
+
+#define PDO_BATT_MAX_VOLT_SHIFT 20      /* 50mV units */
+#define PDO_BATT_MIN_VOLT_SHIFT 10      /* 50mV units */
+#define PDO_BATT_MAX_PWR_SHIFT  0       /* 250mW units */
+
+#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MIN_VOLT_SHIFT)
+#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MAX_VOLT_SHIFT)
+#define PDO_BATT_MAX_POWER(mw) ((((mw) / 250) & PDO_PWR_MASK) << PDO_BATT_MAX_PWR_SHIFT)
+
+#define PDO_BATT(min_mv, max_mv, max_mw)                        \
+	(PDO_TYPE(PDO_TYPE_BATT) | PDO_BATT_MIN_VOLT(min_mv) |  \
+	 PDO_BATT_MAX_VOLT(max_mv) | PDO_BATT_MAX_POWER(max_mw))
+
+#define PDO_VAR_MAX_VOLT_SHIFT  20      /* 50mV units */
+#define PDO_VAR_MIN_VOLT_SHIFT  10      /* 50mV units */
+#define PDO_VAR_MAX_CURR_SHIFT  0       /* 10mA units */
+
+#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MIN_VOLT_SHIFT)
+#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MAX_VOLT_SHIFT)
+#define PDO_VAR_MAX_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_VAR_MAX_CURR_SHIFT)
+
+#define PDO_VAR(min_mv, max_mv, max_ma)                         \
+	(PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) |    \
+	 PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma))
+
+static inline enum pd_pdo_type pdo_type(uint32_t pdo)
+{
+	return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK;
+}
+
+static inline unsigned int pdo_fixed_voltage(uint32_t pdo)
+{
+	return ((pdo >> PDO_FIXED_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
+}
+
+static inline unsigned int pdo_min_voltage(uint32_t pdo)
+{
+	return ((pdo >> PDO_VAR_MIN_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
+}
+
+static inline unsigned int pdo_max_voltage(uint32_t pdo)
+{
+	return ((pdo >> PDO_VAR_MAX_VOLT_SHIFT) & PDO_VOLT_MASK) * 50;
+}
+
+static inline unsigned int pdo_max_current(uint32_t pdo)
+{
+	return ((pdo >> PDO_VAR_MAX_CURR_SHIFT) & PDO_CURR_MASK) * 10;
+}
+
+static inline unsigned int pdo_max_power(uint32_t pdo)
+{
+	return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250;
+}
+
+/* RDO: Request Data Object */
+#define RDO_OBJ_POS_SHIFT       28
+#define RDO_OBJ_POS_MASK        0x7
+#define RDO_GIVE_BACK           BIT(27) /* Supports reduced operating current */
+#define RDO_CAP_MISMATCH        BIT(26) /* Not satisfied by source caps */
+#define RDO_USB_COMM            BIT(25) /* USB communications capable */
+#define RDO_NO_SUSPEND          BIT(24) /* USB Suspend not supported */
+
+#define RDO_PWR_MASK                    0x3ff
+#define RDO_CURR_MASK                   0x3ff
+
+#define RDO_FIXED_OP_CURR_SHIFT         10
+#define RDO_FIXED_MAX_CURR_SHIFT        0
+
+#define RDO_OBJ(idx) (((idx) & RDO_OBJ_POS_MASK) << RDO_OBJ_POS_SHIFT)
+
+#define PDO_FIXED_OP_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_OP_CURR_SHIFT)
+#define PDO_FIXED_MAX_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_MAX_CURR_SHIFT)
+
+#define RDO_FIXED(idx, op_ma, max_ma, flags)                    \
+	(RDO_OBJ(idx) | (flags) |                               \
+	 PDO_FIXED_OP_CURR(op_ma) | PDO_FIXED_MAX_CURR(max_ma))
+
+#define RDO_BATT_OP_PWR_SHIFT           10      /* 250mW units */
+#define RDO_BATT_MAX_PWR_SHIFT          0       /* 250mW units */
+
+#define RDO_BATT_OP_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_OP_PWR_SHIFT)
+#define RDO_BATT_MAX_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_MAX_PWR_SHIFT)
+
+#define RDO_BATT(idx, op_mw, max_mw, flags)                     \
+	(RDO_OBJ(idx) | (flags) |                               \
+	 RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw))
+
+static inline unsigned int rdo_index(u32 rdo)
+{
+	return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK;
+}
+
+static inline unsigned int rdo_op_current(u32 rdo)
+{
+	return ((rdo >> RDO_FIXED_OP_CURR_SHIFT) & RDO_CURR_MASK) * 10;
+}
+
+static inline unsigned int rdo_max_current(u32 rdo)
+{
+	return ((rdo >> RDO_FIXED_MAX_CURR_SHIFT) &
+			RDO_CURR_MASK) * 10;
+}
+
+static inline unsigned int rdo_op_power(u32 rdo)
+{
+	return ((rdo >> RDO_BATT_OP_PWR_SHIFT) & RDO_PWR_MASK) * 250;
+}
+
+static inline unsigned int rdo_max_power(u32 rdo)
+{
+	return ((rdo >> RDO_BATT_MAX_PWR_SHIFT) & RDO_PWR_MASK) * 250;
+}
+
+#define TCPC_LOG_BUFFER_SIZE 1024
+
+struct tcpc_port;
+
+typedef void (*ss_mux_sel)(enum typec_cc_polarity pol);
+typedef int (*ext_pd_switch_setup)(struct tcpc_port *port_p);
+
+enum tcpc_port_type {
+	TYPEC_PORT_DFP,
+	TYPEC_PORT_UFP,
+	TYPEC_PORT_DRP,
+};
+
+struct tcpc_port_config {
+	uint8_t i2c_bus;
+	uint8_t addr;
+	enum tcpc_port_type port_type;
+	uint32_t max_snk_mv;
+	uint32_t max_snk_ma;
+	uint32_t max_snk_mw;
+	uint32_t op_snk_mv;
+	bool disable_pd;
+	ext_pd_switch_setup switch_setup_func;
+};
+
+struct tcpc_port {
+	struct tcpc_port_config cfg;
+	struct udevice *i2c_dev;
+	ss_mux_sel ss_sel_func;
+	enum pd_sink_state pd_state;
+	uint32_t tx_msg_id;
+	uint32_t log_size;
+	char logbuffer[TCPC_LOG_BUFFER_SIZE];
+	char *log_p;
+	char *log_print;
+};
+
+int tcpc_set_cc_to_source(struct tcpc_port *port);
+int tcpc_set_cc_to_sink(struct tcpc_port *port);
+int tcpc_set_plug_orientation(struct tcpc_port *port, enum typec_cc_polarity polarity);
+int tcpc_get_cc_status(struct tcpc_port *port, enum typec_cc_polarity *polarity, enum typec_cc_state *state);
+int tcpc_clear_alert(struct tcpc_port *port, uint16_t clear_mask);
+int tcpc_send_command(struct tcpc_port *port, uint8_t command);
+int tcpc_polling_reg(struct tcpc_port *port, uint8_t reg,
+	uint8_t reg_width, uint16_t mask, uint16_t value, ulong timeout_ms);
+int tcpc_setup_dfp_mode(struct tcpc_port *port);
+int tcpc_setup_ufp_mode(struct tcpc_port *port);
+int tcpc_disable_src_vbus(struct tcpc_port *port);
+int tcpc_init(struct tcpc_port *port, struct tcpc_port_config config, ss_mux_sel ss_sel_func);
+bool tcpc_pd_sink_check_charging(struct tcpc_port *port);
+void tcpc_print_log(struct tcpc_port *port);
+
+#ifdef CONFIG_SPL_BUILD
+int tcpc_setup_ufp_mode(struct tcpc_port *port)
+{
+	return 0;
+}
+int tcpc_setup_dfp_mode(struct tcpc_port *port)
+{
+	return 0;
+}
+
+int tcpc_disable_src_vbus(struct tcpc_port *port)
+{
+	return 0;
+}
+#endif
+#endif /* __TCPCI_H */
-- 
2.28.0

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

* [PATCH 2/8] power: regulator: add dummy helper
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
  2020-10-12  6:23 ` [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC) Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-12  6:23 ` [PATCH 3/8] phy: nop-phy: add optional clk Peng Fan
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

Add dummy helper to enabling the header could be included when
DM REGULATOR not enabled.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 include/power/regulator.h | 114 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/include/power/regulator.h b/include/power/regulator.h
index 74938dd61e..7f278e8c7d 100644
--- a/include/power/regulator.h
+++ b/include/power/regulator.h
@@ -264,6 +264,7 @@ struct dm_regulator_ops {
 	int (*set_mode)(struct udevice *dev, int mode_id);
 };
 
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
 /**
  * regulator_mode: returns a pointer to the array of regulator mode info
  *
@@ -524,5 +525,118 @@ int regulator_get_by_platname(const char *platname, struct udevice **devp);
  */
 int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
 				struct udevice **devp);
+#else
+static inline int regulator_mode(struct udevice *dev, struct dm_regulator_mode **modep)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_value(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_value(struct udevice *dev, int uV)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_suspend_value(struct udevice *dev, int uV)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_suspend_value(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_value_force(struct udevice *dev, int uV)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_current(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_current(struct udevice *dev, int uA)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_enable(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_enable(struct udevice *dev, bool enable)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_suspend_enable(struct udevice *dev, bool enable)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_suspend_enable(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_mode(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_set_mode(struct udevice *dev, int mode_id)
+{
+	return -ENOSYS;
+}
+
+static inline int regulators_enable_boot_on(bool verbose)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_autoset(struct udevice *dev)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_autoset_by_name(const char *platname, struct udevice **devp)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_list_autoset(const char *list_platname[], struct udevice *list_devp[],
+					 bool verbose)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_by_devname(const char *devname, struct udevice **devp)
+{
+	return -ENOSYS;
+}
+
+static inline int regulator_get_by_platname(const char *platname, struct udevice **devp)
+{
+	return -ENOSYS;
+}
+
+static inline int device_get_supply_regulator(struct udevice *dev, const char *supply_name,
+					       struct udevice **devp)
+{
+	return -ENOSYS;
+}
+#endif
 
 #endif /* _INCLUDE_REGULATOR_H_ */
-- 
2.28.0

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

* [PATCH 3/8] phy: nop-phy: add optional clk
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
  2020-10-12  6:23 ` [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC) Peng Fan
  2020-10-12  6:23 ` [PATCH 2/8] power: regulator: add dummy helper Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-12  8:52   ` Marek Vasut
  2020-10-12  6:23 ` [PATCH 4/8] usb: imx: add i.MX usb ehci driver Peng Fan
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

Add optional clk for nop phy

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/phy/nop-phy.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/phy/nop-phy.c b/drivers/phy/nop-phy.c
index a5eed20f3f..a1afdef736 100644
--- a/drivers/phy/nop-phy.c
+++ b/drivers/phy/nop-phy.c
@@ -4,17 +4,49 @@
  * Written by Jean-Jacques Hiblot  <jjhiblot@ti.com>
  */
 
+#include <clk.h>
 #include <common.h>
 #include <dm.h>
 #include <dm/device.h>
 #include <generic-phy.h>
 
+struct nop_phy_priv {
+	struct clk nop_clk;
+};
+
+static int nop_phy_init(struct phy *phy)
+{
+	struct nop_phy_priv *priv = dev_get_priv(phy->dev);
+
+	if (!clk_valid(&priv->nop_clk))
+		return 0;
+
+	return clk_enable(&priv->nop_clk);
+}
+
+static int nop_phy_probe(struct udevice *dev)
+{
+	struct nop_phy_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	if (CONFIG_IS_ENABLED(CLK)) {
+		ret = clk_get_by_name(dev, "main_clk", &priv->nop_clk);
+		if (ret < 0 && ret != -ENODATA) {
+			dev_err(dev, "Failed to get main_clk: %d\n", ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static const struct udevice_id nop_phy_ids[] = {
 	{ .compatible = "nop-phy" },
 	{ }
 };
 
 static struct phy_ops nop_phy_ops = {
+	.init = nop_phy_init,
 };
 
 U_BOOT_DRIVER(nop_phy) = {
@@ -22,4 +54,6 @@ U_BOOT_DRIVER(nop_phy) = {
 	.id	= UCLASS_PHY,
 	.of_match = nop_phy_ids,
 	.ops = &nop_phy_ops,
+	.probe = nop_phy_probe,
+	.priv_auto_alloc_size = sizeof(struct nop_phy_priv),
 };
-- 
2.28.0

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

* [PATCH 4/8] usb: imx: add i.MX usb ehci driver
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
                   ` (2 preceding siblings ...)
  2020-10-12  6:23 ` [PATCH 3/8] phy: nop-phy: add optional clk Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-12  8:55   ` Marek Vasut
  2020-10-12  6:23 ` [PATCH 5/8] imx8m: enable usb power domain Peng Fan
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

This driver is a modifed and cleaned-up version of drivers/usb/host/ehci-mx6.c,
it is to replace the original ehci-mx6.c driver.

It dropped the hardcoding code and only support driver model with
phy/clk/regulator/etc enabled.

The usbmisc code is handling "fsl,usbmisc" related driver code, similar
with Linux Kernel.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 Makefile                                    |   1 +
 arch/arm/include/asm/mach-imx/regs-usbphy.h |   5 +
 arch/arm/include/asm/mach-imx/sys_proto.h   |   2 +
 drivers/Makefile                            |   1 +
 drivers/usb/Kconfig                         |   2 +
 drivers/usb/imx/Kconfig                     |  10 +
 drivers/usb/imx/Makefile                    |   5 +
 drivers/usb/imx/ehci-imx.c                  | 406 ++++++++++++++++++++
 drivers/usb/imx/imx-usb-misc.c              |  47 +++
 9 files changed, 479 insertions(+)
 create mode 100644 drivers/usb/imx/Kconfig
 create mode 100644 drivers/usb/imx/Makefile
 create mode 100644 drivers/usb/imx/ehci-imx.c
 create mode 100644 drivers/usb/imx/imx-usb-misc.c

diff --git a/Makefile b/Makefile
index 1de1f384e5..d1e9b19f34 100644
--- a/Makefile
+++ b/Makefile
@@ -799,6 +799,7 @@ libs-y += drivers/usb/musb/
 libs-y += drivers/usb/musb-new/
 libs-y += drivers/usb/phy/
 libs-y += drivers/usb/ulpi/
+libs-y += drivers/usb/imx/
 libs-y += cmd/
 libs-y += common/
 libs-y += env/
diff --git a/arch/arm/include/asm/mach-imx/regs-usbphy.h b/arch/arm/include/asm/mach-imx/regs-usbphy.h
index 2b18ec20f3..c1f0a3264c 100644
--- a/arch/arm/include/asm/mach-imx/regs-usbphy.h
+++ b/arch/arm/include/asm/mach-imx/regs-usbphy.h
@@ -7,6 +7,8 @@
 #ifndef __REGS_USBPHY_H__
 #define __REGS_USBPHY_H__
 
+#include <linux/bitops.h>
+
 #define USBPHY_CTRL						0x00000030
 #define USBPHY_CTRL_SET					0x00000034
 #define USBPHY_CTRL_CLR					0x00000038
@@ -22,4 +24,7 @@
 #define USBPHY_CTRL_CLKGATE				(1 << 30)
 #define USBPHY_CTRL_SFTRST				(1 << 31)
 
+#define USBNC_PHY_STATUS_OFFSET			0x23C
+#define USBNC_PHYSTATUS_ID_DIG			BIT(4)
+
 #endif /* __REGS_USBPHY_H__ */
diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h
index 5f0c1ae218..c1e3cdcd88 100644
--- a/arch/arm/include/asm/mach-imx/sys_proto.h
+++ b/arch/arm/include/asm/mach-imx/sys_proto.h
@@ -212,4 +212,6 @@ unsigned long call_imx_sip_ret2(unsigned long id, unsigned long reg0,
 				unsigned long reg3);
 
 void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
+
+int usbmisc_init(void __iomem *addr, int index);
 #endif
diff --git a/drivers/Makefile b/drivers/Makefile
index 9eb51453e5..f566217399 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_SPL_USB_GADGET) += usb/common/
 obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/udc/
 obj-$(CONFIG_SPL_WATCHDOG_SUPPORT) += watchdog/
 obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/
+obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/imx/
 obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/
 obj-$(CONFIG_SPL_SATA_SUPPORT) += ata/ scsi/
 obj-$(CONFIG_HAVE_BLOCK_DEVICE) += block/
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 34881a12b8..18c266a900 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -68,6 +68,8 @@ config SPL_DM_USB_GADGET
 
 source "drivers/usb/host/Kconfig"
 
+source "drivers/usb/imx/Kconfig"
+
 source "drivers/usb/cdns3/Kconfig"
 
 source "drivers/usb/dwc3/Kconfig"
diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig
new file mode 100644
index 0000000000..5ccf5282fc
--- /dev/null
+++ b/drivers/usb/imx/Kconfig
@@ -0,0 +1,10 @@
+if USB_EHCI_HCD
+
+config USB_EHCI_IMX
+	bool "Support for i.MX on-chip EHCI USB controller"
+	depends on IMX8MM || IMX8MN
+	---help---
+	  Enables support for the on-chip EHCI controller on i.MX SoCs.
+	  This is to replace ehci-mx6.c
+
+endif
diff --git a/drivers/usb/imx/Makefile b/drivers/usb/imx/Makefile
new file mode 100644
index 0000000000..9e50882719
--- /dev/null
+++ b/drivers/usb/imx/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2020 NXP
+
+obj-$(CONFIG_USB_EHCI_IMX) += ehci-imx.o imx-usb-misc.o
diff --git a/drivers/usb/imx/ehci-imx.c b/drivers/usb/imx/ehci-imx.c
new file mode 100644
index 0000000000..66ea8a1ab4
--- /dev/null
+++ b/drivers/usb/imx/ehci-imx.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <usb.h>
+#include <errno.h>
+#include <wait_bit.h>
+#include <linux/compat.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <usb/ehci-ci.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#include <asm/mach-imx/regs-usbphy.h>
+#include <asm/mach-imx/sys_proto.h>
+#include <dm.h>
+#include <asm/mach-types.h>
+#include <power-domain.h>
+#include <power/regulator.h>
+#include <linux/iopoll.h>
+#include <linux/usb/otg.h>
+
+#include "../host/ehci.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void ehci_imx_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, uint32_t *reg)
+{
+	u32 result;
+	int ret;
+
+	mdelay(50);
+
+	ret = read_poll_timeout(ehci_readl, status_reg, result, !(result & EHCI_PS_PR), 5, 20000);
+	if (ret)
+		printf("%s timeout\n", __func__);
+
+	*reg = ehci_readl(status_reg);
+}
+
+/**
+ * board_ehci_hcd_init - set usb vbus voltage
+ * @port:      usb otg port
+ *
+ * Target board specific, setup iomux pad to setup supply vbus voltage
+ * for usb otg port. Machine board file overrides board_ehci_hcd_init
+ *
+ * Return: 0 Success
+ */
+int __weak board_ehci_hcd_init(int port)
+{
+	return 0;
+}
+
+#define  USB_INIT_UNKNOWN (USB_INIT_DEVICE + 1)
+
+struct ehci_imx_priv_data {
+	struct ehci_ctrl ctrl;
+	struct usb_ehci *ehci;
+	struct udevice *vbus_supply;
+	enum usb_init_type init_type;
+	void *__iomem phy_base;
+	int portnr;
+	int clock_count;
+	struct clk_bulk clks;
+	void *__iomem usbmisc_addr;
+	int usbmisc_index;
+	struct phy phy;
+};
+
+static int imx_init_after_reset(struct ehci_ctrl *dev)
+{
+	struct ehci_imx_priv_data *priv = dev->priv;
+	enum usb_init_type type = priv->init_type;
+	struct usb_ehci *ehci = priv->ehci;
+	int ret;
+
+	ret = board_usb_init(priv->portnr, priv->init_type);
+	if (ret) {
+		printf("Failed to initialize board for USB\n");
+		return ret;
+	}
+
+	/* Do board specific initialization */
+	ret = board_ehci_hcd_init(priv->portnr);
+	if (ret) {
+		dev_err(dev, "board_ehci_hcd_init failed %d\n", ret);
+		return ret;
+	}
+
+	ret = usbmisc_init(priv->usbmisc_addr, priv->usbmisc_index);
+	if (ret) {
+		dev_err(dev, "usbmisc_init %d\n", ret);
+		return ret;
+	}
+
+	if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->vbus_supply) {
+		ret = regulator_set_enable(priv->vbus_supply, (type == USB_INIT_DEVICE) ?
+					   false : true);
+		if (ret && ret != -ENOSYS) {
+			printf("Error enabling VBUS supply (ret=%i)\n", ret);
+			return ret;
+		}
+	}
+
+	if (type == USB_INIT_DEVICE)
+		return 0;
+
+	setbits_le32(&ehci->usbmode, CM_HOST);
+	writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+	setbits_le32(&ehci->portsc, USB_EN);
+
+	mdelay(10);
+
+	return 0;
+}
+
+static const struct ehci_ops imx_ehci_ops = {
+	.powerup_fixup		= ehci_imx_powerup_fixup,
+	.init_after_reset	= imx_init_after_reset
+};
+
+/**
+ * board_ehci_usb_phy_mode - override usb phy mode
+ * @port:	usb host/otg port
+ *
+ * Target board specific, override usb_phy_mode.
+ * When usb-otg is used as usb host port, iomux pad usb_otg_id can be
+ * left disconnected in this case usb_phy_mode will not be able to identify
+ * the phy mode that usb port is used.
+ * Machine file overrides board_usb_phy_mode.
+ * When the extcon property is set in DTB, machine must provide this function, otherwise
+ * it will default return HOST.
+ *
+ * Return: USB_INIT_DEVICE or USB_INIT_HOST
+ */
+int __weak board_ehci_usb_phy_mode(struct udevice *dev)
+{
+	return USB_INIT_HOST;
+}
+
+static int ehci_usb_phy_mode(struct udevice *dev)
+{
+	struct ehci_imx_priv_data *priv = dev_get_priv(dev);
+	void *__iomem phy_status;
+	u32 val;
+
+	if (is_imx8mm() || is_imx8mn()) {
+		phy_status = (void __iomem *)(priv->phy_base +
+					      USBNC_PHY_STATUS_OFFSET);
+		val = readl(phy_status);
+
+		if (val & USBNC_PHYSTATUS_ID_DIG)
+			priv->init_type = USB_INIT_DEVICE;
+		else
+			priv->init_type = USB_INIT_HOST;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ehci_get_usb_phy(struct udevice *dev)
+{
+	struct ehci_imx_priv_data *priv = dev_get_priv(dev);
+	void *__iomem addr = (void *__iomem)devfdt_get_addr(dev);
+
+	if (is_imx8mm() || is_imx8mn())
+		priv->phy_base = addr;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ehci_get_usbmisc(struct udevice *dev)
+{
+	struct ehci_imx_priv_data *priv = dev_get_priv(dev);
+	struct ofnode_phandle_args args;
+	int ret;
+
+	/*
+	 * About fsl,usbmisc, Refer to
+	 * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt.
+	 */
+	if (!ofnode_get_property(dev_ofnode(dev), "fsl,usbmisc", NULL))
+		return 0;
+
+	ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "fsl,usbmisc", "#index-cells",
+					     0, 0, &args);
+	if (ret) {
+		dev_err(dev, "failed ofnode_parse_phandle_with_args %d\n", ret);
+		return ret;
+	}
+
+	if (!ofnode_valid(args.node)) {
+		dev_err(dev, "%s: unable to find node\n", __func__);
+		return -ENOENT;
+	}
+
+	priv->usbmisc_addr = (void __iomem *)ofnode_get_addr(args.node);
+	if ((fdt_addr_t)priv->usbmisc_addr == FDT_ADDR_T_NONE) {
+		dev_err(dev, "failed ofnode_get_addr %d\n", ret);
+		return -EINVAL;
+	}
+
+	priv->usbmisc_index = args.args[0];
+
+	return 0;
+}
+
+static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+	struct usb_platdata *plat = dev_get_platdata(dev);
+	struct ehci_imx_priv_data *priv = dev_get_priv(dev);
+	enum usb_dr_mode dr_mode;
+	const void *extcon;
+
+	extcon = ofnode_get_property(dev->node, "extcon", NULL);
+	if (extcon) {
+		priv->init_type = board_ehci_usb_phy_mode(dev);
+		goto check_type;
+	}
+
+	dr_mode = usb_get_dr_mode(dev->node);
+
+	switch (dr_mode) {
+	case USB_DR_MODE_HOST:
+		priv->init_type = USB_INIT_HOST;
+		break;
+	case USB_DR_MODE_PERIPHERAL:
+		priv->init_type = USB_INIT_DEVICE;
+		break;
+	case USB_DR_MODE_OTG:
+	case USB_DR_MODE_UNKNOWN:
+		priv->init_type = USB_INIT_UNKNOWN;
+		break;
+	};
+
+check_type:
+	if (priv->init_type != USB_INIT_UNKNOWN && priv->init_type != plat->init_type) {
+		debug("Request USB type is %u, board forced type is %u\n",
+		      plat->init_type, priv->init_type);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int ehci_usb_probe(struct udevice *dev)
+{
+	struct usb_platdata *plat = dev_get_platdata(dev);
+	struct usb_ehci *ehci = dev_read_addr_ptr(dev);
+	struct ehci_imx_priv_data *priv = dev_get_priv(dev);
+	enum usb_init_type type = plat->init_type;
+	struct ehci_hccr *hccr;
+	struct ehci_hcor *hcor;
+	int ret, alias_id;
+	u32 portsc;
+
+	ret = dev_read_alias_seq(dev, &alias_id);
+	if (ret < 0) {
+		dev_err(dev, "%s: Could not get alias id: %d\n", __func__, ret);
+		return ret;
+	}
+
+	priv->ehci = ehci;
+	priv->portnr = dev->req_seq;
+
+	/* Init usb board level according to the requested init type */
+	ret = board_usb_init(priv->portnr, type);
+	if (ret) {
+		printf("Failed to initialize board for USB\n");
+		return ret;
+	}
+
+	if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
+		ret = device_get_supply_regulator(dev, "vbus-supply", &priv->vbus_supply);
+		if (ret)
+			debug("%s: No vbus supply\n", dev->name);
+	}
+
+	ret = ehci_get_usb_phy(dev);
+	if (ret) {
+		debug("%s: fail to get USB PHY base\n", dev->name);
+		return ret;
+	}
+
+	ret = ehci_get_usbmisc(dev);
+	if (ret) {
+		dev_err(dev, "fail to get USB misc, %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_get_bulk(dev, &priv->clks);
+	if (ret) {
+		dev_err(dev, "clk_get_bulk failed %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable_bulk(&priv->clks);
+	if (ret) {
+		dev_err(dev, "clk_enable_bulkj falied, %d\n", ret);
+		return ret;
+	}
+
+	mdelay(1);
+
+	portsc = readl(&ehci->portsc);
+	if (portsc & PORT_PTS_PHCD) {
+		debug("suspended: portsc %x, enabled it.\n", portsc);
+		clrbits_le32(&ehci->portsc, PORT_PTS_PHCD);
+	}
+
+	/* Do board specific initialization */
+	ret = board_ehci_hcd_init(priv->portnr);
+	if (ret) {
+		dev_err(dev, "board_ehci_hcd_init failed %d\n", ret);
+		goto release_clk;
+	}
+
+	ret = usbmisc_init(priv->usbmisc_addr, priv->usbmisc_index);
+	if (ret) {
+		dev_err(dev, "usbmisc_init %d\n", ret);
+		goto release_clk;
+	}
+
+	ret = ehci_setup_phy(dev, &priv->phy, 0);
+	if (ret < 0 && ret != -ENOSYS) {
+		dev_err(dev, "fail to setup USB PHY, %d\n", ret);
+		return ret;
+	}
+
+	/* If the init_type is unknown due to it is not forced in DTB, we use USB ID to detect */
+	if (priv->init_type == USB_INIT_UNKNOWN) {
+		ret = ehci_usb_phy_mode(dev);
+		if (ret)
+			return ret;
+		if (priv->init_type != type)
+			return -ENODEV;
+	}
+
+	if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->vbus_supply) {
+		ret = regulator_set_enable(priv->vbus_supply,
+					   (priv->init_type == USB_INIT_DEVICE) ?
+					   false : true);
+		if (ret && ret != -ENOSYS) {
+			printf("Error enabling VBUS supply (ret=%i)\n", ret);
+			return ret;
+		}
+	}
+
+	if (priv->init_type == USB_INIT_HOST) {
+		setbits_le32(&ehci->usbmode, CM_HOST);
+		writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
+		setbits_le32(&ehci->portsc, USB_EN);
+	}
+
+	mdelay(10);
+
+	hccr = (struct ehci_hccr *)((uintptr_t)&ehci->caplength);
+	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
+			HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
+
+	return ehci_register(dev, hccr, hcor, &imx_ehci_ops, 0, priv->init_type);
+
+release_clk:
+	clk_release_bulk(&priv->clks);
+
+	return ret;
+}
+
+int ehci_usb_remove(struct udevice *dev)
+{
+	struct ehci_imx_priv_data *priv = dev_get_priv(dev);
+	struct usb_platdata *plat = dev_get_platdata(dev);
+
+	ehci_deregister(dev);
+
+	plat->init_type = 0; /* Clean the requested usb type to host mode */
+
+	return board_usb_cleanup(dev->req_seq, priv->init_type);
+}
+
+static const struct udevice_id imx_usb_ids[] = {
+	{ .compatible = "fsl,imx8mm-usb" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_imx) = {
+	.name	= "ehci_imx",
+	.id	= UCLASS_USB,
+	.of_match = imx_usb_ids,
+	.ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
+	.probe	= ehci_usb_probe,
+	.remove = ehci_usb_remove,
+	.ops	= &ehci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
+	.priv_auto_alloc_size = sizeof(struct ehci_imx_priv_data),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c
new file mode 100644
index 0000000000..a9db71fdb1
--- /dev/null
+++ b/drivers/usb/imx/imx-usb-misc.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ *	Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/mach-imx/sys_proto.h>
+
+#define MX7D_USB_OTG_PHY_CFG2	0x34
+
+#define USBNC_PHYCFG2_ACAENB	(1 << 4) /* otg_id detection enable */
+#define UCTRL_PWR_POL		(1 << 9) /* OTG Polarity of Power Pin */
+#define UCTRL_OVER_CUR_POL	(1 << 8) /* OTG Polarity of Overcurrent */
+#define UCTRL_OVER_CUR_DIS	(1 << 7) /* Disable OTG Overcurrent Detection */
+
+int usbmisc_init(void __iomem *addr, int index)
+{
+	void __iomem *ctrl;
+
+	if (is_mx7() || is_imx8mm() || is_imx8mn())
+		clrbits_le32(addr + MX7D_USB_OTG_PHY_CFG2, USBNC_PHYCFG2_ACAENB);
+
+	if (is_mx6())
+		ctrl = addr + index * 4;
+	else
+		ctrl = addr;
+
+#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
+	/* mx6qarm2 seems to required a different setting*/
+	clrbits_le32(ctrl, UCTRL_OVER_CUR_POL);
+#else
+	setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
+#endif
+
+	setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
+
+	/* Set power polarity to high active */
+#ifdef CONFIG_MXC_USB_OTG_HACTIVE
+	setbits_le32(ctrl, UCTRL_PWR_POL);
+#else
+	clrbits_le32(ctrl, UCTRL_PWR_POL);
+#endif
+
+	return 0;
+}
-- 
2.28.0

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

* [PATCH 5/8] imx8m: enable usb power domain
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
                   ` (3 preceding siblings ...)
  2020-10-12  6:23 ` [PATCH 4/8] usb: imx: add i.MX usb ehci driver Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-12  9:00   ` Marek Vasut
  2020-10-12  6:23 ` [PATCH 6/8] imx8mm_evk: add usbotg1 host support Peng Fan
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

Enable usb power domain, we are not using a power domain driver now.
Currently NXP use a ARM SIP based power domain driver, but this has been
rejected by Linux Kernel, so we are thinking SCMI, however kernel stuff
still not settle down, to make uboot feature work, we directly use SIP
call for U-Boot and MMIO for SPL.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 arch/arm/include/asm/arch-imx8m/sys_proto.h |  1 +
 arch/arm/mach-imx/imx8m/soc.c               | 55 +++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/arch/arm/include/asm/arch-imx8m/sys_proto.h b/arch/arm/include/asm/arch-imx8m/sys_proto.h
index d328542ece..3e54f9b676 100644
--- a/arch/arm/include/asm/arch-imx8m/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8m/sys_proto.h
@@ -11,6 +11,7 @@
 void set_wdog_reset(struct wdog_regs *wdog);
 void enable_tzc380(void);
 void restore_boot_params(void);
+int imx8m_usb_power(int usb_id, bool on);
 extern unsigned long rom_pointer[];
 enum boot_device get_boot_device(void);
 bool is_usb_boot(void);
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index 9bca5bf972..830d1ac901 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -1112,3 +1112,58 @@ long long env_get_offset(long long defautl_offset)
 }
 #endif
 #endif
+
+#ifdef CONFIG_SPL_BUILD
+static uint32_t gpc_pu_m_core_offset[11] = {
+	0xc00, 0xc40, 0xc80, 0xcc0,
+	0xdc0, 0xe00, 0xe40, 0xe80,
+	0xec0, 0xf00, 0xf40,
+};
+
+#define PGC_PCR				0
+
+void imx_gpc_set_m_core_pgc(unsigned int offset, bool pdn)
+{
+	uint32_t val;
+	uintptr_t reg = GPC_BASE_ADDR + offset;
+
+	val = readl(reg);
+	val &= ~(0x1 << PGC_PCR);
+
+	if(pdn)
+		val |= 0x1 << PGC_PCR;
+	writel(val, reg);
+}
+
+void imx8m_usb_power_domain(uint32_t domain_id, bool on)
+{
+	uint32_t val;
+	uintptr_t reg;
+
+	imx_gpc_set_m_core_pgc(gpc_pu_m_core_offset[domain_id], true);
+
+	reg = GPC_BASE_ADDR + (on ? 0xf8 : 0x104);
+	val = 1 << (domain_id > 3 ? (domain_id + 3) : domain_id);
+	writel(val, reg);
+	while (readl(reg) & val)
+		;
+	imx_gpc_set_m_core_pgc(gpc_pu_m_core_offset[domain_id], false);
+}
+#endif
+
+int imx8m_usb_power(int usb_id, bool on)
+{
+	if (usb_id > 1)
+		return -EINVAL;
+
+#ifdef CONFIG_SPL_BUILD
+	imx8m_usb_power_domain(2 + usb_id, on);
+#else
+	struct arm_smccc_res res;
+
+	/* Get ARM Trusted Firmware commit id */
+	arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN, 2 + usb_id, on, 0, 0, 0, 0, &res);
+#endif
+
+	return 0;
+}
-- 
2.28.0

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

* [PATCH 6/8] imx8mm_evk: add usbotg1 host support
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
                   ` (4 preceding siblings ...)
  2020-10-12  6:23 ` [PATCH 5/8] imx8m: enable usb power domain Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-12  6:23 ` [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET Peng Fan
  2020-10-12  6:23 ` [PATCH 8/8] imx8mm_evk: add fastboot support Peng Fan
  7 siblings, 0 replies; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

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@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

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
                   ` (5 preceding siblings ...)
  2020-10-12  6:23 ` [PATCH 6/8] imx8mm_evk: add usbotg1 host support Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-27  7:45   ` Wolfgang Denk
  2020-10-12  6:23 ` [PATCH 8/8] imx8mm_evk: add fastboot support Peng Fan
  7 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

From: Sherry Sun <sherry.sun@nxp.com>

Convert the ci_udc driver to driver model by using the uclass
UCLASS_USB_GADGET_GENERIC. The clk and power of USB controller and USB
PHY both are initialized by parsing the device tree nodes.

If CONFIG_DM_USB_GADGET is defined, we use the ci_udc driver in DM way,
if it does not defined, we can use ci_udc driver in its original Non-DM
way.

Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
Reviewed-by: Ye Li <ye.li@nxp.com>
[Peng: need to extract common code from host and gadget driver(TODO)]
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/ci_udc.c | 305 +++++++++++++++++++++++++++++++++++-
 drivers/usb/host/ehci-mx6.c |  15 +-
 include/usb/ci_udc.h        |   3 +
 3 files changed, 305 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 226a9e6d67..6f2e38ffd8 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -13,16 +13,25 @@
 #include <cpu_func.h>
 #include <net.h>
 #include <malloc.h>
+#include <dm.h>
+#include <clk.h>
+#include <power-domain.h>
 #include <asm/byteorder.h>
 #include <asm/cache.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/unaligned.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/clock.h>
+#include <asm/mach-imx/regs-usbphy.h>
 #include <linux/types.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <dm/pinctrl.h>
 #include <usb/ci_udc.h>
+#include <usb/ehci-ci.h>
 #include "../host/ehci.h"
 #include "ci_udc.h"
 
@@ -93,9 +102,18 @@ static int ci_ep_dequeue(struct usb_ep *ep, struct usb_request *req);
 static struct usb_request *
 ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags);
 static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req);
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+static int ci_udc_gadget_start(struct usb_gadget *g,
+			       struct usb_gadget_driver *driver);
+static int ci_udc_gadget_stop(struct usb_gadget *g);
+#endif
 
 static struct usb_gadget_ops ci_udc_ops = {
 	.pullup = ci_pullup,
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+	.udc_start		= ci_udc_gadget_start,
+	.udc_stop		= ci_udc_gadget_stop,
+#endif
 };
 
 static struct usb_ep_ops ci_ep_ops = {
@@ -866,7 +884,7 @@ void udc_irq(void)
 	}
 }
 
-int usb_gadget_handle_interrupts(int index)
+int ci_udc_handle_interrupts(void)
 {
 	u32 value;
 	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
@@ -1010,6 +1028,19 @@ static int ci_udc_probe(void)
 	return 0;
 }
 
+bool dfu_usb_get_reset(void)
+{
+	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+
+	return !!(readl(&udc->usbsts) & STS_URI);
+}
+
+#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
+int usb_gadget_handle_interrupts(int index)
+{
+	return ci_udc_handle_interrupts();
+}
+
 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 {
 	int ret;
@@ -1063,10 +1094,276 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 
 	return 0;
 }
+#else /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */
 
-bool dfu_usb_get_reset(void)
+static int ci_udc_gadget_start(struct usb_gadget *g,
+			       struct usb_gadget_driver *driver)
 {
-	struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+	if (!driver)
+		return -EINVAL;
+	if (!driver->bind || !driver->setup || !driver->disconnect)
+		return -EINVAL;
 
-	return !!(readl(&udc->usbsts) & STS_URI);
+	controller.driver = driver;
+	return 0;
+}
+
+static int ci_udc_gadget_stop(struct usb_gadget *g)
+{
+	controller.driver = NULL;
+
+	ci_ep_free_request(&controller.ep[0].ep, &controller.ep0_req->req);
+	free(controller.items_mem);
+	free(controller.epts);
+	return 0;
+}
+
+struct ci_udc_priv_data {
+	struct ehci_ctrl ctrl;
+	struct udevice otgdev;
+	struct clk_bulk		clks;
+	int phy_off;
+	struct power_domain otg_pd;
+	struct clk phy_clk;
+	struct power_domain phy_pd;
+};
+
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+	return ci_udc_handle_interrupts();
+}
+
+static int ci_udc_phy_setup(struct udevice *dev, struct ci_udc_priv_data *priv)
+{
+	struct udevice __maybe_unused phy_dev;
+	priv->phy_off = fdtdec_lookup_phandle(gd->fdt_blob,
+					      dev_of_offset(dev),
+					      "fsl,usbphy");
+	if (priv->phy_off < 0)
+		return -EINVAL;
+
+	phy_dev.node = offset_to_ofnode(priv->phy_off);
+
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+	/* Need to power on the PHY before access it */
+	if (!power_domain_get(&phy_dev, &priv->phy_pd)) {
+		if (power_domain_on(&priv->phy_pd))
+			return -EINVAL;
+	}
+#endif
+
+#if CONFIG_IS_ENABLED(CLK)
+	int ret;
+
+	ret = clk_get_by_index(&phy_dev, 0, &priv->phy_clk);
+	if (ret) {
+		printf("Failed to get phy_clk\n");
+		return ret;
+	}
+
+	ret = clk_enable(&priv->phy_clk);
+	if (ret) {
+		printf("Failed to enable phy_clk\n");
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+
+static int ci_udc_phy_shutdown(struct ci_udc_priv_data *priv)
+{
+	int ret = 0;
+
+#if CONFIG_IS_ENABLED(CLK)
+	if (priv->phy_clk.dev) {
+		ret = clk_disable(&priv->phy_clk);
+		if (ret)
+			return ret;
+
+		ret = clk_free(&priv->phy_clk);
+		if (ret)
+			return ret;
+	}
+#endif
+
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+	ret = power_domain_off(&priv->phy_pd);
+	if (ret)
+		printf("Power down USB PHY failed! (error = %d)\n", ret);
+#endif
+	return ret;
+}
+
+static int ci_udc_otg_clk_init(struct udevice *dev,
+			       struct clk_bulk *clks)
+{
+	int ret;
+
+	ret = clk_get_bulk(dev, clks);
+	if (ret == -ENOSYS)
+		return 0;
+
+	if (ret)
+		return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+	ret = clk_enable_bulk(clks);
+	if (ret) {
+		clk_release_bulk(clks);
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+
+static int ci_udc_otg_phy_mode(struct udevice *dev)
+{
+	struct ci_udc_priv_data *priv = dev_get_priv(dev);
+
+	void *__iomem phy_ctrl, *__iomem phy_status;
+	void *__iomem phy_base = (void *__iomem)devfdt_get_addr(&priv->otgdev);
+	u32 val;
+
+	if (is_mx6() || is_mx7ulp() || is_imx8()) {
+		phy_base = (void __iomem *)fdtdec_get_addr(gd->fdt_blob,
+							   priv->phy_off,
+							   "reg");
+		if ((fdt_addr_t)phy_base == FDT_ADDR_T_NONE)
+			return -EINVAL;
+
+		phy_ctrl = (void __iomem *)(phy_base + USBPHY_CTRL);
+		val = readl(phy_ctrl);
+		if (val & USBPHY_CTRL_OTG_ID)
+			return USB_INIT_DEVICE;
+		else
+			return USB_INIT_HOST;
+	} else if (is_mx7() || is_imx8mm() || is_imx8mn()) {
+		phy_status = (void __iomem *)(phy_base +
+					      USBNC_PHY_STATUS_OFFSET);
+		val = readl(phy_status);
+		if (val & USBNC_PHYSTATUS_ID_DIG)
+			return USB_INIT_DEVICE;
+		else
+			return USB_INIT_HOST;
+	} else {
+		return -EINVAL;
+	}
+}
+
+static int ci_udc_otg_ofdata_to_platdata(struct udevice *dev)
+{
+	struct ci_udc_priv_data *priv = dev_get_priv(dev);
+	int node = dev_of_offset(dev);
+	int usbotg_off;
+
+	if (usb_get_dr_mode(dev_ofnode(dev)) != USB_DR_MODE_PERIPHERAL) {
+		dev_dbg(dev, "Invalid mode\n");
+		return -ENODEV;
+	}
+
+	usbotg_off = fdtdec_lookup_phandle(gd->fdt_blob,
+					   node,
+					   "chipidea,usb");
+	if (usbotg_off < 0)
+		return -EINVAL;
+	priv->otgdev.node = offset_to_ofnode(usbotg_off);
+	priv->otgdev.parent = dev->parent;
+
+	return 0;
+}
+
+static int ci_udc_otg_probe(struct udevice *dev)
+{
+	struct ci_udc_priv_data *priv = dev_get_priv(dev);
+	struct usb_ehci *ehci;
+	int ret;
+
+	ehci = (struct usb_ehci *)devfdt_get_addr(&priv->otgdev);
+
+	pinctrl_select_state(&priv->otgdev, "default");
+
+#if defined(CONFIG_MX6)
+	if (mx6_usb_fused((u32)ehci)) {
+		printf("USB at 0x%x is fused, disable it\n", (u32)ehci);
+		return -ENODEV;
+	}
+#endif
+
+	ret = board_usb_init(dev->seq, USB_INIT_DEVICE);
+	if (ret) {
+		printf("Failed to initialize board for USB\n");
+		return ret;
+	}
+
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+	if (!power_domain_get(&priv->otgdev, &priv->otg_pd)) {
+		if (power_domain_on(&priv->otg_pd))
+			return -EINVAL;
+	}
+#endif
+
+	ret = ci_udc_phy_setup(&priv->otgdev, priv);
+	if (ret)
+		return ret;
+
+	ret = ci_udc_otg_clk_init(&priv->otgdev, &priv->clks);
+	if (ret)
+		return ret;
+
+	if (ci_udc_otg_phy_mode(dev) != USB_INIT_DEVICE)
+		return -ENODEV;
+
+	priv->ctrl.hccr = (struct ehci_hccr *)((ulong)&ehci->caplength);
+	priv->ctrl.hcor = (struct ehci_hcor *)((ulong)priv->ctrl.hccr +
+			HC_LENGTH(ehci_readl(&(priv->ctrl.hccr)->cr_capbase)));
+	controller.ctrl = &priv->ctrl;
+
+	ret = ci_udc_probe();
+	if (ret) {
+		DBG("udc probe failed, returned %d\n", ret);
+		return ret;
+	}
+
+	ret = usb_add_gadget_udc((struct device *)dev, &controller.gadget);
+
+	return ret;
+}
+
+static int ci_udc_otg_remove(struct udevice *dev)
+{
+	struct ci_udc_priv_data *priv = dev_get_priv(dev);
+
+	usb_del_gadget_udc(&controller.gadget);
+
+	clk_release_bulk(&priv->clks);
+	ci_udc_phy_shutdown(priv);
+#if CONFIG_IS_ENABLED(POWER_DOMAIN)
+	if (power_domain_off(&priv->otg_pd)) {
+		printf("Power down USB controller failed!\n");
+		return -EINVAL;
+	}
+#endif
+	board_usb_cleanup(dev->seq, USB_INIT_DEVICE);
+
+	controller.ctrl = NULL;
+	return 0;
 }
+
+static const struct udevice_id ci_udc_otg_ids[] = {
+	{ .compatible = "fsl,imx27-usb-gadget" },
+	{ }
+};
+
+U_BOOT_DRIVER(ci_udc_otg) = {
+	.name	= "ci-udc-otg",
+	.id	= UCLASS_USB_GADGET_GENERIC,
+	.of_match = ci_udc_otg_ids,
+	.ofdata_to_platdata = ci_udc_otg_ofdata_to_platdata,
+	.probe = ci_udc_otg_probe,
+	.remove = ci_udc_otg_remove,
+	.priv_auto_alloc_size = sizeof(struct ci_udc_priv_data),
+};
+
+#endif /* !CONFIG_IS_ENABLED(DM_USB_GADGET) */
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index 20617850f3..2bfae1f661 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -17,6 +17,7 @@
 #include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
 #include <asm/mach-imx/iomux-v3.h>
+#include <asm/mach-imx/regs-usbphy.h>
 #include <asm/mach-imx/sys_proto.h>
 #include <dm.h>
 #include <asm/mach-types.h>
@@ -37,18 +38,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define USB_H1_CTRL_OFFSET	0x04
 
-#define USBPHY_CTRL				0x00000030
-#define USBPHY_CTRL_SET				0x00000034
-#define USBPHY_CTRL_CLR				0x00000038
-#define USBPHY_CTRL_TOG				0x0000003c
-
-#define USBPHY_PWD				0x00000000
-#define USBPHY_CTRL_SFTRST			0x80000000
-#define USBPHY_CTRL_CLKGATE			0x40000000
-#define USBPHY_CTRL_ENUTMILEVEL3		0x00008000
-#define USBPHY_CTRL_ENUTMILEVEL2		0x00004000
-#define USBPHY_CTRL_OTG_ID			0x08000000
-
 #define ANADIG_USB2_CHRG_DETECT_EN_B		0x00100000
 #define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B	0x00080000
 
@@ -58,8 +47,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS	0x00000040
 
 #define USBNC_OFFSET		0x200
-#define USBNC_PHY_STATUS_OFFSET	0x23C
-#define USBNC_PHYSTATUS_ID_DIG	(1 << 4) /* otg_id status */
 #define USBNC_PHYCFG2_ACAENB	(1 << 4) /* otg_id detection enable */
 #define UCTRL_PWR_POL		(1 << 9) /* OTG Polarity of Power Pin */
 #define UCTRL_OVER_CUR_POL	(1 << 8) /* OTG Polarity of Overcurrent */
diff --git a/include/usb/ci_udc.h b/include/usb/ci_udc.h
index 06adb2bb4d..ddae8e178b 100644
--- a/include/usb/ci_udc.h
+++ b/include/usb/ci_udc.h
@@ -7,7 +7,10 @@
 
 #ifndef __CI_UDC_H__
 #define __CI_UDC_H__
+#include <usb/ehci-ci.h>
 
 #define EP_MAX_PACKET_SIZE	0x200
 #define EP0_MAX_PACKET_SIZE	64
+
+int ehci_mx6_common_init(struct usb_ehci *ehci, int index);
 #endif /* __CI_UDC_H__ */
-- 
2.28.0

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

* [PATCH 8/8] imx8mm_evk: add fastboot support
  2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
                   ` (6 preceding siblings ...)
  2020-10-12  6:23 ` [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET Peng Fan
@ 2020-10-12  6:23 ` Peng Fan
  2020-10-27  7:45   ` Wolfgang Denk
  7 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  6:23 UTC (permalink / raw)
  To: u-boot

Add fastboot support for U-Boot proper

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 arch/arm/dts/imx8mm-evk-u-boot.dtsi | 17 +++++++++++++++++
 configs/imx8mm_evk_defconfig        | 13 ++++++++++++-
 include/configs/imx8mm_evk.h        | 14 ++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/imx8mm-evk-u-boot.dtsi b/arch/arm/dts/imx8mm-evk-u-boot.dtsi
index 241dfd656f..d85fe7e17a 100644
--- a/arch/arm/dts/imx8mm-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx8mm-evk-u-boot.dtsi
@@ -6,6 +6,8 @@
 / {
 
 	aliases {
+		usbgadget0 = &usbg1;
+		usbgadget1 = &usbg2;
 		usb0 = &usbotg1;
 		usb1 = &usbotg2;
 	};
@@ -15,6 +17,21 @@
 		wdt = <&wdog1>;
 		u-boot,dm-spl;
 	};
+
+	usbg1: usbg1 {
+		compatible = "fsl,imx27-usb-gadget";
+		dr_mode = "peripheral";
+		chipidea,usb = <&usbotg1>;
+		status = "okay";
+	};
+
+	usbg2: usbg2 {
+		compatible = "fsl,imx27-usb-gadget";
+		dr_mode = "peripheral";
+		chipidea,usb = <&usbotg2>;
+		status = "okay";
+	};
+
 };
 
 &{/soc at 0} {
diff --git a/configs/imx8mm_evk_defconfig b/configs/imx8mm_evk_defconfig
index 10e95d8d5c..19560bdb7e 100644
--- a/configs/imx8mm_evk_defconfig
+++ b/configs/imx8mm_evk_defconfig
@@ -19,7 +19,6 @@ 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
@@ -64,6 +63,11 @@ CONFIG_SPL_CLK_COMPOSITE_CCF=y
 CONFIG_CLK_COMPOSITE_CCF=y
 CONFIG_SPL_CLK_IMX8MM=y
 CONFIG_CLK_IMX8MM=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x42800000
+CONFIG_FASTBOOT_BUF_SIZE=0x40000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=1
 CONFIG_MXC_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MXC=y
@@ -95,8 +99,15 @@ CONFIG_DM_THERMAL=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 # CONFIG_SPL_DM_USB is not set
+CONFIG_DM_USB_GADGET=y
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_MX7 is not set
 CONFIG_USB_EHCI_IMX=y
 CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="FSL"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
+CONFIG_CI_UDC=y
+CONFIG_SDP_LOADADDR=0x40400000
 CONFIG_IMX_WATCHDOG=y
diff --git a/include/configs/imx8mm_evk.h b/include/configs/imx8mm_evk.h
index 5e865f0bef..f6dccaaa15 100644
--- a/include/configs/imx8mm_evk.h
+++ b/include/configs/imx8mm_evk.h
@@ -148,4 +148,18 @@
 #define CONFIG_MXC_USB_PORTSC  (PORT_PTS_UTMI | PORT_PTS_PTW)
 #define CONFIG_USB_MAX_CONTROLLER_COUNT         2
 
+#define CONFIG_FASTBOOT_USB_DEV 0
+
+/* USB configs */
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_USBD_HS
+
+#define CONFIG_CMD_USB_MASS_STORAGE
+#define CONFIG_USB_GADGET_MASS_STORAGE
+#define CONFIG_USB_FUNCTION_MASS_STORAGE
+
+#endif
+
+#define CONFIG_USB_GADGET_VBUS_DRAW 2
+
 #endif
-- 
2.28.0

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-12  6:23 ` [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC) Peng Fan
@ 2020-10-12  8:50   ` Marek Vasut
  2020-10-12  9:43     ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Marek Vasut @ 2020-10-12  8:50 UTC (permalink / raw)
  To: u-boot

On 10/12/20 8:23 AM, Peng Fan wrote:
[...]
>  board/freescale/common/Kconfig  |    6 +
>  board/freescale/common/Makefile |    4 +
>  board/freescale/common/tcpc.c   | 1018 +++++++++++++++++++++++++++++++
>  board/freescale/common/tcpc.h   |  469 ++++++++++++++
>  4 files changed, 1497 insertions(+)
>  create mode 100644 board/freescale/common/tcpc.c
>  create mode 100644 board/freescale/common/tcpc.h

Shouldn't driver be in drivers/ ?

[...]

> diff --git a/board/freescale/common/tcpc.c b/board/freescale/common/tcpc.c
> new file mode 100644
> index 0000000000..fb532a3d87
> --- /dev/null
> +++ b/board/freescale/common/tcpc.c
> @@ -0,0 +1,1018 @@

[...]

> +#ifdef DEBUG
> +#define tcpc_debug_log(port, fmt, args...) tcpc_log(port, fmt, ##args)
> +#else
> +#define tcpc_debug_log(port, fmt, args...)
> +#endif

Use dev_dbg() or pr_debug() or just debug() ?

[...]

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

* [PATCH 3/8] phy: nop-phy: add optional clk
  2020-10-12  6:23 ` [PATCH 3/8] phy: nop-phy: add optional clk Peng Fan
@ 2020-10-12  8:52   ` Marek Vasut
  2020-10-12  9:12     ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Marek Vasut @ 2020-10-12  8:52 UTC (permalink / raw)
  To: u-boot

On 10/12/20 8:23 AM, Peng Fan wrote:
[...]
> +static int nop_phy_probe(struct udevice *dev)
> +{
> +	struct nop_phy_priv *priv = dev_get_priv(dev);
> +	int ret;
> +
> +	if (CONFIG_IS_ENABLED(CLK)) {
> +		ret = clk_get_by_name(dev, "main_clk", &priv->nop_clk);

So is this main_clk or nop_clk ?

Wouldn't it be better if the NOP PHY used the clk_bulk and enabled all
clock described in DT ?

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

* [PATCH 4/8] usb: imx: add i.MX usb ehci driver
  2020-10-12  6:23 ` [PATCH 4/8] usb: imx: add i.MX usb ehci driver Peng Fan
@ 2020-10-12  8:55   ` Marek Vasut
  2020-10-12  9:15     ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Marek Vasut @ 2020-10-12  8:55 UTC (permalink / raw)
  To: u-boot

On 10/12/20 8:23 AM, Peng Fan wrote:
> This driver is a modifed and cleaned-up version of drivers/usb/host/ehci-mx6.c,
> it is to replace the original ehci-mx6.c driver.
> 
> It dropped the hardcoding code and only support driver model with
> phy/clk/regulator/etc enabled.

So now we end up with two drivers ?

Can we rather do like Linux does and have drivers/usb/chipidea , since
this controller is chipidea-hdrc and the i.MX extras can then be in
ci_hdrc_imx.c or so.

[...]

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

* [PATCH 5/8] imx8m: enable usb power domain
  2020-10-12  6:23 ` [PATCH 5/8] imx8m: enable usb power domain Peng Fan
@ 2020-10-12  9:00   ` Marek Vasut
  2020-10-12  9:20     ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Marek Vasut @ 2020-10-12  9:00 UTC (permalink / raw)
  To: u-boot

On 10/12/20 8:23 AM, Peng Fan wrote:
> Enable usb power domain, we are not using a power domain driver now.
> Currently NXP use a ARM SIP based power domain driver, but this has been
> rejected by Linux Kernel, so we are thinking SCMI, however kernel stuff
> still not settle down, to make uboot feature work, we directly use SIP
> call for U-Boot and MMIO for SPL.

The i.MX8M power domain support was already submitted to mainline Linux
[1], and it is much nicer to let the OS (or in this case, U-Boot) do
that rather than hiding it into ATF.

https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=357903

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

* [PATCH 3/8] phy: nop-phy: add optional clk
  2020-10-12  8:52   ` Marek Vasut
@ 2020-10-12  9:12     ` Peng Fan
  0 siblings, 0 replies; 32+ messages in thread
From: Peng Fan @ 2020-10-12  9:12 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 3/8] phy: nop-phy: add optional clk
> 
> On 10/12/20 8:23 AM, Peng Fan wrote:
> [...]
> > +static int nop_phy_probe(struct udevice *dev) {
> > +	struct nop_phy_priv *priv = dev_get_priv(dev);
> > +	int ret;
> > +
> > +	if (CONFIG_IS_ENABLED(CLK)) {
> > +		ret = clk_get_by_name(dev, "main_clk", &priv->nop_clk);
> 
> So is this main_clk or nop_clk ?
> 
> Wouldn't it be better if the NOP PHY used the clk_bulk and enabled all clock
> described in DT ?

Bulk seems better.

Thanks,
Peng.

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

* [PATCH 4/8] usb: imx: add i.MX usb ehci driver
  2020-10-12  8:55   ` Marek Vasut
@ 2020-10-12  9:15     ` Peng Fan
  0 siblings, 0 replies; 32+ messages in thread
From: Peng Fan @ 2020-10-12  9:15 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 4/8] usb: imx: add i.MX usb ehci driver
> 
> On 10/12/20 8:23 AM, Peng Fan wrote:
> > This driver is a modifed and cleaned-up version of
> > drivers/usb/host/ehci-mx6.c, it is to replace the original ehci-mx6.c driver.
> >
> > It dropped the hardcoding code and only support driver model with
> > phy/clk/regulator/etc enabled.
> 
> So now we end up with two drivers ?
> 
> Can we rather do like Linux does and have drivers/usb/chipidea , since this
> controller is chipidea-hdrc and the i.MX extras can then be in ci_hdrc_imx.c or
> so.

Ah. It is not only ci_hdrc_imx.c, it has core.c, host.c and etc.

Regards,
Peng. 

> 
> [...]

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

* [PATCH 5/8] imx8m: enable usb power domain
  2020-10-12  9:00   ` Marek Vasut
@ 2020-10-12  9:20     ` Peng Fan
  2020-10-12 10:29       ` Marek Vasut
  0 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  9:20 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 5/8] imx8m: enable usb power domain
> 
> On 10/12/20 8:23 AM, Peng Fan wrote:
> > Enable usb power domain, we are not using a power domain driver now.
> > Currently NXP use a ARM SIP based power domain driver, but this has
> > been rejected by Linux Kernel, so we are thinking SCMI, however kernel
> > stuff still not settle down, to make uboot feature work, we directly
> > use SIP call for U-Boot and MMIO for SPL.
> 
> The i.MX8M power domain support was already submitted to mainline Linux
> [1], and it is much nicer to let the OS (or in this case, U-Boot) do that rather
> than hiding it into ATF.

oh.. that will conflict with NXP release. I not think NXP will use that in a short time.

We wanna use SCMI to hide the complex gpc stuff from Linux side and make
us easy support QNX/Windows/Linux.

Regards,
Peng.

> 
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatch
> work.kernel.org%2Fproject%2Flinux-arm-kernel%2Flist%2F%3Fseries%3D357
> 903&amp;data=02%7C01%7Cpeng.fan%40nxp.com%7C99fbfc009ea443756b
> a708d86e8d7387%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6
> 37380901087950322&amp;sdata=hSo8i19rPKknPY1bSdO64drzgpbpq9zejPFr7
> OcAL10%3D&amp;reserved=0

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-12  8:50   ` Marek Vasut
@ 2020-10-12  9:43     ` Peng Fan
  2020-10-12 10:21       ` Marek Vasut
  0 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-12  9:43 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
> 
> On 10/12/20 8:23 AM, Peng Fan wrote:
> [...]
> >  board/freescale/common/Kconfig  |    6 +
> >  board/freescale/common/Makefile |    4 +
> >  board/freescale/common/tcpc.c   | 1018
> +++++++++++++++++++++++++++++++
> >  board/freescale/common/tcpc.h   |  469 ++++++++++++++
> >  4 files changed, 1497 insertions(+)
> >  create mode 100644 board/freescale/common/tcpc.c  create mode
> 100644
> > board/freescale/common/tcpc.h
> 
> Shouldn't driver be in drivers/ ?

You mean drivers/usb/typec as kernel? There is no common framework now.

Regards,
Peng.

> 
> [...]
> 
> > diff --git a/board/freescale/common/tcpc.c
> > b/board/freescale/common/tcpc.c new file mode 100644 index
> > 0000000000..fb532a3d87
> > --- /dev/null
> > +++ b/board/freescale/common/tcpc.c
> > @@ -0,0 +1,1018 @@
> 
> [...]
> 
> > +#ifdef DEBUG
> > +#define tcpc_debug_log(port, fmt, args...) tcpc_log(port, fmt,
> > +##args) #else #define tcpc_debug_log(port, fmt, args...) #endif
> 
> Use dev_dbg() or pr_debug() or just debug() ?
> 
> [...]

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-12  9:43     ` Peng Fan
@ 2020-10-12 10:21       ` Marek Vasut
  2020-10-13  9:39         ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Marek Vasut @ 2020-10-12 10:21 UTC (permalink / raw)
  To: u-boot

On 10/12/20 11:43 AM, Peng Fan wrote:
>> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
>>
>> On 10/12/20 8:23 AM, Peng Fan wrote:
>> [...]
>>>  board/freescale/common/Kconfig  |    6 +
>>>  board/freescale/common/Makefile |    4 +
>>>  board/freescale/common/tcpc.c   | 1018
>> +++++++++++++++++++++++++++++++
>>>  board/freescale/common/tcpc.h   |  469 ++++++++++++++
>>>  4 files changed, 1497 insertions(+)
>>>  create mode 100644 board/freescale/common/tcpc.c  create mode
>> 100644
>>> board/freescale/common/tcpc.h
>>
>> Shouldn't driver be in drivers/ ?
> 
> You mean drivers/usb/typec as kernel?

Yes, looks much better than putting drivers into board/ , right ?

> There is no common framework now.

What can we do about that ?

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

* [PATCH 5/8] imx8m: enable usb power domain
  2020-10-12  9:20     ` Peng Fan
@ 2020-10-12 10:29       ` Marek Vasut
  0 siblings, 0 replies; 32+ messages in thread
From: Marek Vasut @ 2020-10-12 10:29 UTC (permalink / raw)
  To: u-boot

On 10/12/20 11:20 AM, Peng Fan wrote:
>> Subject: Re: [PATCH 5/8] imx8m: enable usb power domain
>>
>> On 10/12/20 8:23 AM, Peng Fan wrote:
>>> Enable usb power domain, we are not using a power domain driver now.
>>> Currently NXP use a ARM SIP based power domain driver, but this has
>>> been rejected by Linux Kernel, so we are thinking SCMI, however kernel
>>> stuff still not settle down, to make uboot feature work, we directly
>>> use SIP call for U-Boot and MMIO for SPL.
>>
>> The i.MX8M power domain support was already submitted to mainline Linux
>> [1], and it is much nicer to let the OS (or in this case, U-Boot) do that rather
>> than hiding it into ATF.
> 
> oh.. that will conflict with NXP release. I not think NXP will use that in a short time.

How does it conflict with NXP release ?

Note that I agree with Lucas that power management should be done
completely in the OS, the OS knows best what it needs from the hardware.
Splitting it between the OS and firmware will only lead to problems, and
you often cannot fix those easily as you cannot update the firmware, so
that makes it particularly hard for upstream to keep the platform well
supported, the OS would have to support all the various firmware
versions and its bugs and workarounds for those.

> We wanna use SCMI to hide the complex gpc stuff from Linux side and make
> us easy support QNX/Windows/Linux.

I think you want to check the argument between Lucas and Jacky, and you
might want to discuss it there in fact, so we don't have to duplicate
that discussion here .

[...]

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-12 10:21       ` Marek Vasut
@ 2020-10-13  9:39         ` Peng Fan
  2020-10-13  9:45           ` Marek Vasut
  0 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-13  9:39 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
> 
> On 10/12/20 11:43 AM, Peng Fan wrote:
> >> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port
> >> controller (TCPC)
> >>
> >> On 10/12/20 8:23 AM, Peng Fan wrote:
> >> [...]
> >>>  board/freescale/common/Kconfig  |    6 +
> >>>  board/freescale/common/Makefile |    4 +
> >>>  board/freescale/common/tcpc.c   | 1018
> >> +++++++++++++++++++++++++++++++
> >>>  board/freescale/common/tcpc.h   |  469 ++++++++++++++
> >>>  4 files changed, 1497 insertions(+)  create mode 100644
> >>> board/freescale/common/tcpc.c  create mode
> >> 100644
> >>> board/freescale/common/tcpc.h
> >>
> >> Shouldn't driver be in drivers/ ?
> >
> > You mean drivers/usb/typec as kernel?
> 
> Yes, looks much better than putting drivers into board/ , right ?
> 
> > There is no common framework now.
> 
> What can we do about that ?

I have no bandwidth to study the new typec area currently. I'll leave
this to Jun and Ye.

BTW: are you ok to take the ehci-mx6 patches?
https://patchwork.ozlabs.org/project/uboot/list/?series=202112

Thanks,
Peng.

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-13  9:39         ` Peng Fan
@ 2020-10-13  9:45           ` Marek Vasut
  2020-10-13 10:05             ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Marek Vasut @ 2020-10-13  9:45 UTC (permalink / raw)
  To: u-boot

On 10/13/20 11:39 AM, Peng Fan wrote:
>> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
>>
>> On 10/12/20 11:43 AM, Peng Fan wrote:
>>>> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port
>>>> controller (TCPC)
>>>>
>>>> On 10/12/20 8:23 AM, Peng Fan wrote:
>>>> [...]
>>>>>  board/freescale/common/Kconfig  |    6 +
>>>>>  board/freescale/common/Makefile |    4 +
>>>>>  board/freescale/common/tcpc.c   | 1018
>>>> +++++++++++++++++++++++++++++++
>>>>>  board/freescale/common/tcpc.h   |  469 ++++++++++++++
>>>>>  4 files changed, 1497 insertions(+)  create mode 100644
>>>>> board/freescale/common/tcpc.c  create mode
>>>> 100644
>>>>> board/freescale/common/tcpc.h
>>>>
>>>> Shouldn't driver be in drivers/ ?
>>>
>>> You mean drivers/usb/typec as kernel?
>>
>> Yes, looks much better than putting drivers into board/ , right ?
>>
>>> There is no common framework now.
>>
>> What can we do about that ?
> 
> I have no bandwidth to study the new typec area currently. I'll leave
> this to Jun and Ye.
> 
> BTW: are you ok to take the ehci-mx6 patches?
> https://patchwork.ozlabs.org/project/uboot/list/?series=202112

Sure, I am waiting for the cleanup patchset:

https://patchwork.ozlabs.org/project/uboot/patch/20200916125705.4341-14-peng.fan at nxp.com/

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-13  9:45           ` Marek Vasut
@ 2020-10-13 10:05             ` Peng Fan
  2020-10-13 10:14               ` Marek Vasut
  0 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-13 10:05 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
> 
> On 10/13/20 11:39 AM, Peng Fan wrote:
> >> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port
> >> controller (TCPC)
> >>
> >> On 10/12/20 11:43 AM, Peng Fan wrote:
> >>>> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port
> >>>> controller (TCPC)
> >>>>
> >>>> On 10/12/20 8:23 AM, Peng Fan wrote:
> >>>> [...]
> >>>>>  board/freescale/common/Kconfig  |    6 +
> >>>>>  board/freescale/common/Makefile |    4 +
> >>>>>  board/freescale/common/tcpc.c   | 1018
> >>>> +++++++++++++++++++++++++++++++
> >>>>>  board/freescale/common/tcpc.h   |  469 ++++++++++++++
> >>>>>  4 files changed, 1497 insertions(+)  create mode 100644
> >>>>> board/freescale/common/tcpc.c  create mode
> >>>> 100644
> >>>>> board/freescale/common/tcpc.h
> >>>>
> >>>> Shouldn't driver be in drivers/ ?
> >>>
> >>> You mean drivers/usb/typec as kernel?
> >>
> >> Yes, looks much better than putting drivers into board/ , right ?
> >>
> >>> There is no common framework now.
> >>
> >> What can we do about that ?
> >
> > I have no bandwidth to study the new typec area currently. I'll leave
> > this to Jun and Ye.
> >
> > BTW: are you ok to take the ehci-mx6 patches?
> > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatc
> >
> hwork.ozlabs.org%2Fproject%2Fuboot%2Flist%2F%3Fseries%3D202112&amp
> ;dat
> >
> a=02%7C01%7Cpeng.fan%40nxp.com%7C9b1ed52ddbf848fff1e408d86f5ddd
> 1e%7C68
> >
> 6ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637381796212195230&a
> mp;sdata=
> >
> BHlWLIhiVEEcRfKVXAQP9ldcyveozTCjpxo%2FrBMLD%2F4%3D&amp;reserved
> =0
> 
> Sure, I am waiting for the cleanup patchset:

With alias set in dtsi, we could remove bind function here to calculate req_seq.
So I would send the dtsi patch to Linux/uboot community, and remove
the find function.

Do you agree?

Thanks,
Peng.

> 
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatch
> work.ozlabs.org%2Fproject%2Fuboot%2Fpatch%2F20200916125705.4341-14
> -peng.fan%40nxp.com%2F&amp;data=02%7C01%7Cpeng.fan%40nxp.com%7
> C9b1ed52ddbf848fff1e408d86f5ddd1e%7C686ea1d3bc2b4c6fa92cd99c5c30
> 1635%7C0%7C0%7C637381796212195230&amp;sdata=Ofqu3wsb2CmStzt0V
> dMbotuTeIJyYeQIaCcb%2Bx9sY5Y%3D&amp;reserved=0

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

* [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
  2020-10-13 10:05             ` Peng Fan
@ 2020-10-13 10:14               ` Marek Vasut
  0 siblings, 0 replies; 32+ messages in thread
From: Marek Vasut @ 2020-10-13 10:14 UTC (permalink / raw)
  To: u-boot

On 10/13/20 12:05 PM, Peng Fan wrote:
>> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC)
>>
>> On 10/13/20 11:39 AM, Peng Fan wrote:
>>>> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port
>>>> controller (TCPC)
>>>>
>>>> On 10/12/20 11:43 AM, Peng Fan wrote:
>>>>>> Subject: Re: [PATCH 1/8] tcpc: Add driver for USB typec port
>>>>>> controller (TCPC)
>>>>>>
>>>>>> On 10/12/20 8:23 AM, Peng Fan wrote:
>>>>>> [...]
>>>>>>>  board/freescale/common/Kconfig  |    6 +
>>>>>>>  board/freescale/common/Makefile |    4 +
>>>>>>>  board/freescale/common/tcpc.c   | 1018
>>>>>> +++++++++++++++++++++++++++++++
>>>>>>>  board/freescale/common/tcpc.h   |  469 ++++++++++++++
>>>>>>>  4 files changed, 1497 insertions(+)  create mode 100644
>>>>>>> board/freescale/common/tcpc.c  create mode
>>>>>> 100644
>>>>>>> board/freescale/common/tcpc.h
>>>>>>
>>>>>> Shouldn't driver be in drivers/ ?
>>>>>
>>>>> You mean drivers/usb/typec as kernel?
>>>>
>>>> Yes, looks much better than putting drivers into board/ , right ?
>>>>
>>>>> There is no common framework now.
>>>>
>>>> What can we do about that ?
>>>
>>> I have no bandwidth to study the new typec area currently. I'll leave
>>> this to Jun and Ye.
>>>
>>> BTW: are you ok to take the ehci-mx6 patches?
>>> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatc
>>>
>> hwork.ozlabs.org%2Fproject%2Fuboot%2Flist%2F%3Fseries%3D202112&amp
>> ;dat
>>>
>> a=02%7C01%7Cpeng.fan%40nxp.com%7C9b1ed52ddbf848fff1e408d86f5ddd
>> 1e%7C68
>>>
>> 6ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637381796212195230&a
>> mp;sdata=
>>>
>> BHlWLIhiVEEcRfKVXAQP9ldcyveozTCjpxo%2FrBMLD%2F4%3D&amp;reserved
>> =0
>>
>> Sure, I am waiting for the cleanup patchset:
> 
> With alias set in dtsi, we could remove bind function here to calculate req_seq.
> So I would send the dtsi patch to Linux/uboot community, and remove
> the find function.
> 
> Do you agree?

I'm not quite sure what this means, so please send a patch and lets see.

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

* [PATCH 8/8] imx8mm_evk: add fastboot support
  2020-10-12  6:23 ` [PATCH 8/8] imx8mm_evk: add fastboot support Peng Fan
@ 2020-10-27  7:45   ` Wolfgang Denk
  2020-10-27  8:08     ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Wolfgang Denk @ 2020-10-27  7:45 UTC (permalink / raw)
  To: u-boot

Dear Peng Fan,

In message <20201012062354.3743-9-peng.fan@nxp.com> you wrote:
> Add fastboot support for U-Boot proper

...

> +	usbg1: usbg1 {
> +		compatible = "fsl,imx27-usb-gadget";
> +		dr_mode = "peripheral";
> +		chipidea,usb = <&usbotg1>;
> +		status = "okay";
> +	};
> +
> +	usbg2: usbg2 {
> +		compatible = "fsl,imx27-usb-gadget";
> +		dr_mode = "peripheral";
> +		chipidea,usb = <&usbotg2>;
> +		status = "okay";
> +	};

What is imx27-usb-gadget ?



Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"The algorithm to do that is extremely nasty. You might want  to  mug
someone with it."                   - M. Devine, Computer Science 340

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-12  6:23 ` [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET Peng Fan
@ 2020-10-27  7:45   ` Wolfgang Denk
  2020-10-27  8:09     ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Wolfgang Denk @ 2020-10-27  7:45 UTC (permalink / raw)
  To: u-boot

Dear Peng Fan,

In message <20201012062354.3743-8-peng.fan@nxp.com> you wrote:
>
> Convert the ci_udc driver to driver model by using the uclass
> UCLASS_USB_GADGET_GENERIC. The clk and power of USB controller and USB
> PHY both are initialized by parsing the device tree nodes.
...
> +static const struct udevice_id ci_udc_otg_ids[] = {
> +	{ .compatible = "fsl,imx27-usb-gadget" },
> +	{ }
> +};

What is imx27-usb-gadget ?


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
There are no data that cannot be plotted on a straight  line  if  the
axis are chosen correctly.

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

* [PATCH 8/8] imx8mm_evk: add fastboot support
  2020-10-27  7:45   ` Wolfgang Denk
@ 2020-10-27  8:08     ` Peng Fan
  0 siblings, 0 replies; 32+ messages in thread
From: Peng Fan @ 2020-10-27  8:08 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 8/8] imx8mm_evk: add fastboot support
> 
> Dear Peng Fan,
> 
> In message <20201012062354.3743-9-peng.fan@nxp.com> you wrote:
> > Add fastboot support for U-Boot proper
> 
> ...
> 
> > +	usbg1: usbg1 {
> > +		compatible = "fsl,imx27-usb-gadget";
> > +		dr_mode = "peripheral";
> > +		chipidea,usb = <&usbotg1>;
> > +		status = "okay";
> > +	};
> > +
> > +	usbg2: usbg2 {
> > +		compatible = "fsl,imx27-usb-gadget";
> > +		dr_mode = "peripheral";
> > +		chipidea,usb = <&usbotg2>;
> > +		status = "okay";
> > +	};
> 
> What is imx27-usb-gadget ?

This is U-Boot specific compatible to let the
ci_udc driver could match the node.

Thanks,
Peng.

> 
> 
> 
> Best regards,
> 
> Wolfgang Denk
> 
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> "The algorithm to do that is extremely nasty. You might want  to  mug
> someone with it."                   - M. Devine, Computer Science 340

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-27  7:45   ` Wolfgang Denk
@ 2020-10-27  8:09     ` Peng Fan
  2020-10-27  8:15       ` Wolfgang Denk
  0 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-27  8:09 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
> 
> Dear Peng Fan,
> 
> In message <20201012062354.3743-8-peng.fan@nxp.com> you wrote:
> >
> > Convert the ci_udc driver to driver model by using the uclass
> > UCLASS_USB_GADGET_GENERIC. The clk and power of USB controller and
> USB
> > PHY both are initialized by parsing the device tree nodes.
> ...
> > +static const struct udevice_id ci_udc_otg_ids[] = {
> > +	{ .compatible = "fsl,imx27-usb-gadget" },
> > +	{ }
> > +};
> 
> What is imx27-usb-gadget ?

This U-Boot specific compatible string. I have no better idea
what we need use here to make DM driver work.

Thanks,
Peng.

> 
> 
> Best regards,
> 
> Wolfgang Denk
> 
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> There are no data that cannot be plotted on a straight  line  if  the axis are
> chosen correctly.

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-27  8:09     ` Peng Fan
@ 2020-10-27  8:15       ` Wolfgang Denk
  2020-10-27  8:18         ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Wolfgang Denk @ 2020-10-27  8:15 UTC (permalink / raw)
  To: u-boot

Dear Peng Fan,

In message <DB6PR0402MB2760A2A57D48AED93592962488160@DB6PR0402MB2760.eurprd04.prod.outlook.com> you wrote:
>
> > > +static const struct udevice_id ci_udc_otg_ids[] = {
> > > +	{ .compatible = "fsl,imx27-usb-gadget" },
> > > +	{ }
> > > +};
> > 
> > What is imx27-usb-gadget ?
> 
> This U-Boot specific compatible string. I have no better idea
> what we need use here to make DM driver work.

But what is "imx27" ?   This is a i.MX8M family platform, right?
Not ancient i.MX27 ?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"Well I don't see why I have to make one man  miserable  when  I  can
make so many men happy."              - Ellyn Mustard, about marriage

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-27  8:15       ` Wolfgang Denk
@ 2020-10-27  8:18         ` Peng Fan
  2020-10-27  9:32           ` Wolfgang Denk
  0 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-27  8:18 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
> 
> Dear Peng Fan,
> 
> In message
> <DB6PR0402MB2760A2A57D48AED93592962488160@DB6PR0402MB2760.
> eurprd04.prod.outlook.com> you wrote:
> >
> > > > +static const struct udevice_id ci_udc_otg_ids[] = {
> > > > +	{ .compatible = "fsl,imx27-usb-gadget" },
> > > > +	{ }
> > > > +};
> > >
> > > What is imx27-usb-gadget ?
> >
> > This U-Boot specific compatible string. I have no better idea what we
> > need use here to make DM driver work.
> 
> But what is "imx27" ?   This is a i.MX8M family platform, right?
> Not ancient i.MX27 ?

This is just a compatible string means all controllers compatible with
i.MX27 USB could use this driver.

Yes this is for i.MX8MM, but the usb gadget feature could reuse
the i.MX27 code.

Thanks,
Peng.

> 
> Best regards,
> 
> Wolfgang Denk
> 
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> "Well I don't see why I have to make one man  miserable  when  I  can
> make so many men happy."              - Ellyn Mustard, about marriage

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-27  8:18         ` Peng Fan
@ 2020-10-27  9:32           ` Wolfgang Denk
  2020-10-27  9:39             ` Peng Fan
  0 siblings, 1 reply; 32+ messages in thread
From: Wolfgang Denk @ 2020-10-27  9:32 UTC (permalink / raw)
  To: u-boot

Dear Peng Fan,

In message <DB6PR0402MB2760ECB86DD133520449792C88160@DB6PR0402MB2760.eurprd04.prod.outlook.com> you wrote:
> > >
> > > > > +static const struct udevice_id ci_udc_otg_ids[] = {
> > > > > +	{ .compatible = "fsl,imx27-usb-gadget" },
> > > > > +	{ }
> > > > > +};
> > > >
> > > > What is imx27-usb-gadget ?
> > >
> > > This U-Boot specific compatible string. I have no better idea what we
> > > need use here to make DM driver work.
> > 
> > But what is "imx27" ?   This is a i.MX8M family platform, right?
> > Not ancient i.MX27 ?
> 
> This is just a compatible string means all controllers compatible with
> i.MX27 USB could use this driver.
> 
> Yes this is for i.MX8MM, but the usb gadget feature could reuse
> the i.MX27 code.

Maybe I'm missing something, but I cannot find imx27-usb-gadget
being used anywhere - not in U-Boot nor in Linux mainline ?

And if we introduce this completely new - then why imx27 ?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
If you think the problem is bad now, just wait until we've solved it.
                                                        Epstein's Law

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-27  9:32           ` Wolfgang Denk
@ 2020-10-27  9:39             ` Peng Fan
  2020-10-27 10:22               ` Wolfgang Denk
  0 siblings, 1 reply; 32+ messages in thread
From: Peng Fan @ 2020-10-27  9:39 UTC (permalink / raw)
  To: u-boot

> Subject: Re: [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
> 
> Dear Peng Fan,
> 
> In message
> <DB6PR0402MB2760ECB86DD133520449792C88160@DB6PR0402MB2760.
> eurprd04.prod.outlook.com> you wrote:
> > > >
> > > > > > +static const struct udevice_id ci_udc_otg_ids[] = {
> > > > > > +	{ .compatible = "fsl,imx27-usb-gadget" },
> > > > > > +	{ }
> > > > > > +};
> > > > >
> > > > > What is imx27-usb-gadget ?
> > > >
> > > > This U-Boot specific compatible string. I have no better idea what
> > > > we need use here to make DM driver work.
> > >
> > > But what is "imx27" ?   This is a i.MX8M family platform, right?
> > > Not ancient i.MX27 ?
> >
> > This is just a compatible string means all controllers compatible with
> > i.MX27 USB could use this driver.
> >
> > Yes this is for i.MX8MM, but the usb gadget feature could reuse the
> > i.MX27 code.
> 
> Maybe I'm missing something, but I cannot find imx27-usb-gadget being used
> anywhere - not in U-Boot nor in Linux mainline ?
> 
> And if we introduce this completely new - then why imx27 ?

ci udc driver is an driver long exist there.

This is just switch to driver module support. Not completely new.

I could use imx6-usb-gadget, but that means need add one
more for i.MX5 if need.

Thanks,
Peng.

> 
> Best regards,
> 
> Wolfgang Denk
> 
> --
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> If you think the problem is bad now, just wait until we've solved it.
> 
> Epstein's Law

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

* [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET
  2020-10-27  9:39             ` Peng Fan
@ 2020-10-27 10:22               ` Wolfgang Denk
  0 siblings, 0 replies; 32+ messages in thread
From: Wolfgang Denk @ 2020-10-27 10:22 UTC (permalink / raw)
  To: u-boot

Dear Peng Fan,

In message <DB6PR0402MB2760CF94CA69EACD95DE978588160@DB6PR0402MB2760.eurprd04.prod.outlook.com> you wrote:
>
> > > > > > > +static const struct udevice_id ci_udc_otg_ids[] = {
> > > > > > > +	{ .compatible = "fsl,imx27-usb-gadget" },
> > > > > > > +	{ }
> > > > > > > +};
...
> > Maybe I'm missing something, but I cannot find imx27-usb-gadget being used
> > anywhere - not in U-Boot nor in Linux mainline ?
> > 
> > And if we introduce this completely new - then why imx27 ?
> 
> ci udc driver is an driver long exist there.

Agreed.  But as far as I can see, no parts of the driver code
contain any references to imx27 (or even imx in general) at all.

> This is just switch to driver module support. Not completely new.

The compatible string "fsl,imx27-usb-gadget" is completely new.

We have all kinds of "fsl,imx27-usb" in U-Boot and Linux, but I
wonder what the rationale is there as well.  I cannot find it
documented anywhere.

All I can see is a comment

	"fsl,imx23-usbphy" is still a fallback for other strings

in Documentation/devicetree/bindings/phy/mxs-usb-phy.txt, but this
is for the USB PHY.

Yes, "fsl,imx27-usb" is being used a lot, but there are things which
look inconsistent to me; we have for example:

- "fsl,imx6ul-usb" in Linux arch/arm/boot/dts/imx7ulp.dtsi , but
  "fsl,imx27-usb" in U-Boot arch/arm/dts/imx7ulp.dtsi
  And actually arch/arm/boot/dts/imx6ul.dtsi then uses
  	compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";

- "fsl,imx7d-usb" in Linux arch/arm64/boot/dts/freescale/imx8mn.dtsi
  and the same in U-Boot arch/arm/dts/imx8mn.dtsi

- "fsl,imx7d-usb" in Linux arch/arm64/boot/dts/freescale/imx8mm.dtsi
  and the same in U-Boot arch/arm/dts/imx8mm.dtsi

> I could use imx6-usb-gadget, but that means need add one
> more for i.MX5 if need.

If you use "fsl,imx7d-usb" on the imx8mm, then would it not be
logical to use ""fsl,imx7d-usb-gadget"?


I'm trying to make sense from all these compatible strings, but it
looks pretty much random to me, so if we add to this we should at
least not increase the confusion.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
That said, there may be good reasons for what you did beyond obsequi-
ous sycophantic parody. Perhaps you might be so kind as to elucidate.
         -- Tom Christiansen in <5ldjbm$jtk$1@csnews.cs.colorado.edu>

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

end of thread, other threads:[~2020-10-27 10:22 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-12  6:23 [PATCH 0/8] i.MX8MM: add host/gadget support Peng Fan
2020-10-12  6:23 ` [PATCH 1/8] tcpc: Add driver for USB typec port controller (TCPC) Peng Fan
2020-10-12  8:50   ` Marek Vasut
2020-10-12  9:43     ` Peng Fan
2020-10-12 10:21       ` Marek Vasut
2020-10-13  9:39         ` Peng Fan
2020-10-13  9:45           ` Marek Vasut
2020-10-13 10:05             ` Peng Fan
2020-10-13 10:14               ` Marek Vasut
2020-10-12  6:23 ` [PATCH 2/8] power: regulator: add dummy helper Peng Fan
2020-10-12  6:23 ` [PATCH 3/8] phy: nop-phy: add optional clk Peng Fan
2020-10-12  8:52   ` Marek Vasut
2020-10-12  9:12     ` Peng Fan
2020-10-12  6:23 ` [PATCH 4/8] usb: imx: add i.MX usb ehci driver Peng Fan
2020-10-12  8:55   ` Marek Vasut
2020-10-12  9:15     ` Peng Fan
2020-10-12  6:23 ` [PATCH 5/8] imx8m: enable usb power domain Peng Fan
2020-10-12  9:00   ` Marek Vasut
2020-10-12  9:20     ` Peng Fan
2020-10-12 10:29       ` Marek Vasut
2020-10-12  6:23 ` [PATCH 6/8] imx8mm_evk: add usbotg1 host support Peng Fan
2020-10-12  6:23 ` [PATCH 7/8] usb: ci_udc: Convert driver to DM_USB_GADGET Peng Fan
2020-10-27  7:45   ` Wolfgang Denk
2020-10-27  8:09     ` Peng Fan
2020-10-27  8:15       ` Wolfgang Denk
2020-10-27  8:18         ` Peng Fan
2020-10-27  9:32           ` Wolfgang Denk
2020-10-27  9:39             ` Peng Fan
2020-10-27 10:22               ` Wolfgang Denk
2020-10-12  6:23 ` [PATCH 8/8] imx8mm_evk: add fastboot support Peng Fan
2020-10-27  7:45   ` Wolfgang Denk
2020-10-27  8:08     ` Peng Fan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.