Merge tag 'u-boot-amlogic-20200420' of https://gitlab.denx.de/u-boot/custodians/u-boot-amlogic

- enable DM_RNG on meson boards
- fix SMBIOS info on Odroid-C2
- Fix video output on GXBB/GXL/GXM boards
- add USB gadget support for GXL/GXM boards
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dd41090..33b4847 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -762,6 +762,7 @@
 config ARCH_MESON
 	bool "Amlogic Meson"
 	imply DISTRO_DEFAULTS
+	imply DM_RNG
 	help
 	  Support for the Meson SoC family developed by Amlogic Inc.,
 	  targeted at media players and tablet computers. We currently
diff --git a/arch/arm/dts/meson-gx-u-boot.dtsi b/arch/arm/dts/meson-gx-u-boot.dtsi
index b84e5ed..17d2cb9 100644
--- a/arch/arm/dts/meson-gx-u-boot.dtsi
+++ b/arch/arm/dts/meson-gx-u-boot.dtsi
@@ -11,6 +11,10 @@
 };
 
 &vpu {
+	reg = <0x0 0xd0100000 0x0 0x100000>,
+	      <0x0 0xc883c000 0x0 0x1000>,
+	      <0x0 0xc8838000 0x0 0x1000>;
+	reg-names = "vpu", "hhi", "dmc";
 	u-boot,dm-pre-reloc;
 };
 
diff --git a/arch/arm/dts/meson-gxl-s805x-libretech-ac-u-boot.dtsi b/arch/arm/dts/meson-gxl-s805x-libretech-ac-u-boot.dtsi
new file mode 100644
index 0000000..c35158d
--- /dev/null
+++ b/arch/arm/dts/meson-gxl-s805x-libretech-ac-u-boot.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-gx-u-boot.dtsi"
diff --git a/arch/arm/dts/meson-gxl-s905x-khadas-vim-u-boot.dtsi b/arch/arm/dts/meson-gxl-s905x-khadas-vim-u-boot.dtsi
index c35158d..39270ea 100644
--- a/arch/arm/dts/meson-gxl-s905x-khadas-vim-u-boot.dtsi
+++ b/arch/arm/dts/meson-gxl-s905x-khadas-vim-u-boot.dtsi
@@ -4,4 +4,4 @@
  * Author: Neil Armstrong <narmstrong@baylibre.com>
  */
 
-#include "meson-gx-u-boot.dtsi"
+#include "meson-gxl-u-boot.dtsi"
diff --git a/arch/arm/dts/meson-gxl-s905x-libretech-cc-u-boot.dtsi b/arch/arm/dts/meson-gxl-s905x-libretech-cc-u-boot.dtsi
index c35158d..474a3e1 100644
--- a/arch/arm/dts/meson-gxl-s905x-libretech-cc-u-boot.dtsi
+++ b/arch/arm/dts/meson-gxl-s905x-libretech-cc-u-boot.dtsi
@@ -4,4 +4,8 @@
  * Author: Neil Armstrong <narmstrong@baylibre.com>
  */
 
-#include "meson-gx-u-boot.dtsi"
+#include "meson-gxl-u-boot.dtsi"
+
+&dwc2 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/meson-gxl-s905x-p212-u-boot.dtsi b/arch/arm/dts/meson-gxl-s905x-p212-u-boot.dtsi
index c35158d..39270ea 100644
--- a/arch/arm/dts/meson-gxl-s905x-p212-u-boot.dtsi
+++ b/arch/arm/dts/meson-gxl-s905x-p212-u-boot.dtsi
@@ -4,4 +4,4 @@
  * Author: Neil Armstrong <narmstrong@baylibre.com>
  */
 
-#include "meson-gx-u-boot.dtsi"
+#include "meson-gxl-u-boot.dtsi"
diff --git a/arch/arm/dts/meson-gxl-u-boot.dtsi b/arch/arm/dts/meson-gxl-u-boot.dtsi
new file mode 100644
index 0000000..9e88afd
--- /dev/null
+++ b/arch/arm/dts/meson-gxl-u-boot.dtsi
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-gx-u-boot.dtsi"
+
+&usb0 {
+	dwc2: usb@c9100000 {
+		compatible = "snps,dwc2";
+		reg = <0x0 0xc9100000 0x0 0x40000>;
+		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
+		clock-names = "ddr";
+		phys = <&usb3_phy>, <&usb2_phy1>;
+		dr_mode = "peripheral";
+		g-rx-fifo-size = <192>;
+		g-np-tx-fifo-size = <128>;
+		g-tx-fifo-size = <128 128 16 16 16>;
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/include/asm/arch-meson/usb-gx.h b/arch/arm/include/asm/arch-meson/usb-gx.h
new file mode 100644
index 0000000..aeb8e0c
--- /dev/null
+++ b/arch/arm/include/asm/arch-meson/usb-gx.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 BayLibre SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+#ifndef _ARCH_MESON_USB_GX_H_
+#define _ARCH_MESON_USB_GX_H_
+
+#include <generic-phy.h>
+#include <linux/usb/otg.h>
+
+/* TOFIX add set_mode to struct phy_ops */
+void phy_meson_gxl_usb2_set_mode(struct phy *phy, enum usb_dr_mode mode);
+void phy_meson_gxl_usb3_set_mode(struct phy *phy, enum usb_dr_mode mode);
+
+#endif
diff --git a/arch/arm/mach-meson/board-gx.c b/arch/arm/mach-meson/board-gx.c
index 191fd49..3da9901 100644
--- a/arch/arm/mach-meson/board-gx.c
+++ b/arch/arm/mach-meson/board-gx.c
@@ -14,6 +14,11 @@
 #include <asm/io.h>
 #include <asm/armv8/mmu.h>
 #include <linux/sizes.h>
+#include <usb.h>
+#include <linux/usb/otg.h>
+#include <asm/arch/usb-gx.h>
+#include <usb/dwc2_udc.h>
+#include <clk.h>
 #include <phy.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -149,3 +154,116 @@
 	/* Enable power gate */
 	clrbits_le32(GX_MEM_PD_REG_0, GX_MEM_PD_REG_0_ETH_MASK);
 }
+
+#if CONFIG_IS_ENABLED(USB_XHCI_DWC3_OF_SIMPLE) && \
+	CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
+static struct dwc2_plat_otg_data meson_gx_dwc2_data;
+static struct phy usb_phys[2];
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	struct ofnode_phandle_args args;
+	struct udevice *clk_dev;
+	ofnode dwc2_node;
+	struct clk clk;
+	int ret, i;
+	u32 val;
+
+	/* find the dwc2 node */
+	dwc2_node = ofnode_by_compatible(ofnode_null(), "snps,dwc2");
+	if (!ofnode_valid(dwc2_node)) {
+		debug("Not found dwc2 node\n");
+		return -ENODEV;
+	}
+
+	if (!ofnode_is_available(dwc2_node)) {
+		debug("dwc2 is disabled in the device tree\n");
+		return -ENODEV;
+	}
+
+	/* get the PHYs */
+	for (i = 0; i < 2; i++) {
+		ret = generic_phy_get_by_node(dwc2_node, i, &usb_phys[i]);
+		if (ret && ret != -ENOENT) {
+			pr_err("Failed to get USB PHY%d for %s\n",
+			       i, ofnode_get_name(dwc2_node));
+			return ret;
+		}
+	}
+
+	for (i = 0; i < 2; i++) {
+		ret = generic_phy_init(&usb_phys[i]);
+		if (ret) {
+			pr_err("Can't init USB PHY%d for %s\n",
+			       i, ofnode_get_name(dwc2_node));
+			return ret;
+		}
+	}
+
+	for (i = 0; i < 2; i++) {
+		ret = generic_phy_power_on(&usb_phys[i]);
+		if (ret) {
+			pr_err("Can't power USB PHY%d for %s\n",
+			       i, ofnode_get_name(dwc2_node));
+			return ret;
+		}
+	}
+
+	phy_meson_gxl_usb3_set_mode(&usb_phys[0], USB_DR_MODE_PERIPHERAL);
+	phy_meson_gxl_usb2_set_mode(&usb_phys[1], USB_DR_MODE_PERIPHERAL);
+
+	meson_gx_dwc2_data.regs_otg = ofnode_get_addr(dwc2_node);
+	if (meson_gx_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
+		debug("usbotg: can't get base address\n");
+		return -ENODATA;
+	}
+
+	/* Enable clock */
+	ret = ofnode_parse_phandle_with_args(dwc2_node, "clocks",
+					     "#clock-cells", 0, 0, &args);
+	if (ret) {
+		debug("usbotg has no clocks defined in the device tree\n");
+		return ret;
+	}
+
+	ret = uclass_get_device_by_ofnode(UCLASS_CLK, args.node, &clk_dev);
+	if (ret)
+		return ret;
+
+	if (args.args_count != 1) {
+		debug("Can't find clock ID in the device tree\n");
+		return -ENODATA;
+	}
+
+	clk.dev = clk_dev;
+	clk.id = args.args[0];
+
+	ret = clk_enable(&clk);
+	if (ret) {
+		debug("Failed to enable usbotg clock\n");
+		return ret;
+	}
+
+	ofnode_read_u32(dwc2_node, "g-rx-fifo-size", &val);
+	meson_gx_dwc2_data.rx_fifo_sz = val;
+	ofnode_read_u32(dwc2_node, "g-np-tx-fifo-size", &val);
+	meson_gx_dwc2_data.np_tx_fifo_sz = val;
+	ofnode_read_u32(dwc2_node, "g-tx-fifo-size", &val);
+	meson_gx_dwc2_data.tx_fifo_sz = val;
+
+	return dwc2_udc_probe(&meson_gx_dwc2_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	int i;
+
+	phy_meson_gxl_usb3_set_mode(&usb_phys[0], USB_DR_MODE_HOST);
+	phy_meson_gxl_usb2_set_mode(&usb_phys[1], USB_DR_MODE_HOST);
+
+	for (i = 0; i < 2; i++)
+		usb_phys[i].dev = NULL;
+
+	return 0;
+}
+#endif
diff --git a/configs/khadas-vim2_defconfig b/configs/khadas-vim2_defconfig
index 9cb377e..a533566 100644
--- a/configs/khadas-vim2_defconfig
+++ b/configs/khadas-vim2_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -49,4 +50,10 @@
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e
+CONFIG_USB_GADGET_PRODUCT_NUM=0xfada
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/khadas-vim_defconfig b/configs/khadas-vim_defconfig
index e18a5e6..8a0af5c 100644
--- a/configs/khadas-vim_defconfig
+++ b/configs/khadas-vim_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -50,4 +51,10 @@
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e
+CONFIG_USB_GADGET_PRODUCT_NUM=0xfada
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/configs/libretech-ac_defconfig b/configs/libretech-ac_defconfig
index 09b87c5..7e48675 100644
--- a/configs/libretech-ac_defconfig
+++ b/configs/libretech-ac_defconfig
@@ -27,6 +27,7 @@
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -69,6 +70,12 @@
 CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_KEYBOARD=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e
+CONFIG_USB_GADGET_PRODUCT_NUM=0xfada
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_DM_VIDEO=y
 # CONFIG_VIDEO_BPP8 is not set
 # CONFIG_VIDEO_BPP16 is not set
diff --git a/configs/libretech-cc_defconfig b/configs/libretech-cc_defconfig
index 7c257b3..2c512eb 100644
--- a/configs/libretech-cc_defconfig
+++ b/configs/libretech-cc_defconfig
@@ -19,6 +19,7 @@
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -51,6 +52,12 @@
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e
+CONFIG_USB_GADGET_PRODUCT_NUM=0xfada
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_DM_VIDEO=y
 # CONFIG_VIDEO_BPP8 is not set
 # CONFIG_VIDEO_BPP16 is not set
diff --git a/configs/libretech-s905d-pc_defconfig b/configs/libretech-s905d-pc_defconfig
index 7e0c958..531d519 100644
--- a/configs/libretech-s905d-pc_defconfig
+++ b/configs/libretech-s905d-pc_defconfig
@@ -26,6 +26,7 @@
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -65,6 +66,12 @@
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e
+CONFIG_USB_GADGET_PRODUCT_NUM=0xfada
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_DM_VIDEO=y
 CONFIG_SYS_WHITE_ON_BLACK=y
diff --git a/configs/libretech-s912-pc_defconfig b/configs/libretech-s912-pc_defconfig
index 5f4ee32..595ec21 100644
--- a/configs/libretech-s912-pc_defconfig
+++ b/configs/libretech-s912-pc_defconfig
@@ -26,6 +26,7 @@
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -65,6 +66,12 @@
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x1b8e
+CONFIG_USB_GADGET_PRODUCT_NUM=0xfada
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_KEYBOARD=y
 CONFIG_DM_VIDEO=y
 CONFIG_SYS_WHITE_ON_BLACK=y
diff --git a/configs/odroid-c2_defconfig b/configs/odroid-c2_defconfig
index 64fbfdf..39279b4 100644
--- a/configs/odroid-c2_defconfig
+++ b/configs/odroid-c2_defconfig
@@ -7,6 +7,7 @@
 CONFIG_DEBUG_UART_BASE=0xc81004c0
 CONFIG_DEBUG_UART_CLOCK=24000000
 CONFIG_IDENT_STRING=" odroid-c2"
+CONFIG_SMBIOS_PRODUCT_NAME="ODROID-C2"
 CONFIG_DEBUG_UART=y
 CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
@@ -41,3 +42,4 @@
 CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_MESON_SERIAL=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SMBIOS_MANUFACTURER="Hardkernel Co., Ltd."
diff --git a/drivers/phy/meson-gxl-usb2.c b/drivers/phy/meson-gxl-usb2.c
index c98d12b..b4f4c3c 100644
--- a/drivers/phy/meson-gxl-usb2.c
+++ b/drivers/phy/meson-gxl-usb2.c
@@ -17,6 +17,9 @@
 #include <regmap.h>
 #include <power/regulator.h>
 #include <clk.h>
+#include <linux/usb/otg.h>
+
+#include <asm/arch/usb-gx.h>
 
 #include <linux/bitops.h>
 #include <linux/compat.h>
@@ -121,15 +124,30 @@
 	udelay(RESET_COMPLETE_TIME);
 }
 
-static void
-phy_meson_gxl_usb2_set_host_mode(struct phy_meson_gxl_usb2_priv *priv)
+void phy_meson_gxl_usb2_set_mode(struct phy *phy, enum usb_dr_mode mode)
 {
+	struct udevice *dev = phy->dev;
+	struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev);
 	uint val;
 
 	regmap_read(priv->regmap, U2P_R0, &val);
-	val |= U2P_R0_DM_PULLDOWN;
-	val |= U2P_R0_DP_PULLDOWN;
-	val &= ~U2P_R0_ID_PULLUP;
+
+	switch (mode) {
+	case USB_DR_MODE_UNKNOWN:
+	case USB_DR_MODE_HOST:
+	case USB_DR_MODE_OTG:
+		val |= U2P_R0_DM_PULLDOWN;
+		val |= U2P_R0_DP_PULLDOWN;
+		val &= ~U2P_R0_ID_PULLUP;
+		break;
+
+	case USB_DR_MODE_PERIPHERAL:
+		val &= ~U2P_R0_DM_PULLDOWN;
+		val &= ~U2P_R0_DP_PULLDOWN;
+		val |= U2P_R0_ID_PULLUP;
+		break;
+	}
+
 	regmap_write(priv->regmap, U2P_R0, val);
 
 	phy_meson_gxl_usb2_reset(priv);
@@ -146,7 +164,7 @@
 	val &= ~U2P_R0_POWER_ON_RESET;
 	regmap_write(priv->regmap, U2P_R0, val);
 
-	phy_meson_gxl_usb2_set_host_mode(priv);
+	phy_meson_gxl_usb2_set_mode(phy, USB_DR_MODE_HOST);
 
 #if CONFIG_IS_ENABLED(DM_REGULATOR)
 	if (priv->phy_supply) {
diff --git a/drivers/phy/meson-gxl-usb3.c b/drivers/phy/meson-gxl-usb3.c
index c2a8593..9de55bb 100644
--- a/drivers/phy/meson-gxl-usb3.c
+++ b/drivers/phy/meson-gxl-usb3.c
@@ -16,6 +16,9 @@
 #include <generic-phy.h>
 #include <regmap.h>
 #include <clk.h>
+#include <linux/usb/otg.h>
+
+#include <asm/arch/usb-gx.h>
 
 #include <linux/bitops.h>
 #include <linux/compat.h>
@@ -93,20 +96,35 @@
 #endif
 };
 
-static int
-phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv)
+void phy_meson_gxl_usb3_set_mode(struct phy *phy, enum usb_dr_mode mode)
 {
+	struct udevice *dev = phy->dev;
+	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
 	uint val;
 
-	regmap_read(priv->regmap, USB_R0, &val);
-	val &= ~USB_R0_U2D_ACT;
-	regmap_write(priv->regmap, USB_R0, val);
+	switch (mode) {
+	case USB_DR_MODE_UNKNOWN:
+	case USB_DR_MODE_HOST:
+	case USB_DR_MODE_OTG:
+		regmap_read(priv->regmap, USB_R0, &val);
+		val &= ~USB_R0_U2D_ACT;
+		regmap_write(priv->regmap, USB_R0, val);
 
-	regmap_read(priv->regmap, USB_R4, &val);
-	val &= ~USB_R4_P21_SLEEP_M0;
-	regmap_write(priv->regmap, USB_R4, val);
+		regmap_read(priv->regmap, USB_R4, &val);
+		val &= ~USB_R4_P21_SLEEP_M0;
+		regmap_write(priv->regmap, USB_R4, val);
+		break;
 
-	return 0;
+	case USB_DR_MODE_PERIPHERAL:
+		regmap_read(priv->regmap, USB_R0, &val);
+		val |= USB_R0_U2D_ACT;
+		regmap_write(priv->regmap, USB_R0, val);
+
+		regmap_read(priv->regmap, USB_R4, &val);
+		val |= USB_R4_P21_SLEEP_M0;
+		regmap_write(priv->regmap, USB_R4, val);
+		break;
+	}
 }
 
 static int phy_meson_gxl_usb3_power_on(struct phy *phy)
@@ -122,7 +140,9 @@
 	val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff);
 	regmap_write(priv->regmap, USB_R5, val);
 
-	return phy_meson_gxl_usb3_set_host_mode(priv);
+	phy_meson_gxl_usb3_set_mode(phy, USB_DR_MODE_HOST);
+
+	return 0;
 }
 
 static int phy_meson_gxl_usb3_power_off(struct phy *phy)
diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c
index e201a90..e463b0b 100644
--- a/drivers/phy/phy-uclass.c
+++ b/drivers/phy/phy-uclass.c
@@ -31,20 +31,20 @@
 	return 0;
 }
 
-int generic_phy_get_by_index(struct udevice *dev, int index,
-			     struct phy *phy)
+int generic_phy_get_by_node(ofnode node, int index, struct phy *phy)
 {
 	struct ofnode_phandle_args args;
 	struct phy_ops *ops;
 	struct udevice *phydev;
 	int i, ret;
 
-	debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy);
+	debug("%s(node=%s, index=%d, phy=%p)\n",
+	      __func__, ofnode_get_name(node), index, phy);
 
 	assert(phy);
 	phy->dev = NULL;
-	ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index,
-					 &args);
+	ret = ofnode_parse_phandle_with_args(node, "phys", "#phy-cells", 0,
+					     index, &args);
 	if (ret) {
 		debug("%s: dev_read_phandle_with_args failed: err=%d\n",
 		      __func__, ret);
@@ -90,6 +90,12 @@
 	return ret;
 }
 
+int generic_phy_get_by_index(struct udevice *dev, int index,
+			     struct phy *phy)
+{
+	return generic_phy_get_by_node(dev_ofnode(dev), index, phy);
+}
+
 int generic_phy_get_by_name(struct udevice *dev, const char *phy_name,
 			    struct phy *phy)
 {
diff --git a/include/generic-phy.h b/include/generic-phy.h
index 95caf58..7353702 100644
--- a/include/generic-phy.h
+++ b/include/generic-phy.h
@@ -7,6 +7,8 @@
 #ifndef __GENERIC_PHY_H
 #define __GENERIC_PHY_H
 
+#include <dm/ofnode.h>
+
 struct ofnode_phandle_args;
 
 /**
@@ -194,6 +196,33 @@
 			     struct phy *phy);
 
 /**
+ * generic_phy_get_by_node() - Get a PHY device by integer index on ofnode
+ *
+ * @node:	the device node
+ * @index:	The index in the list of available PHYs
+ * @phy:	A pointer to the PHY port
+ *
+ * This looks up a PHY device for a client device based on its ofnode and on
+ * its position in the list of the possible PHYs.
+ *
+ * example:
+ * usb1: usb_otg_ss@xxx {
+ *       compatible = "xxx";
+ *       reg = <xxx>;
+ *   .
+ *   .
+ *   phys = <&usb2_phy>, <&usb3_phy>;
+ *   .
+ *   .
+ * };
+ * the USB2 phy can be accessed by passing index '0' and the USB3 phy can
+ * be accessed by passing index '1'
+ *
+ * @return 0 if OK, or a negative error code
+ */
+int generic_phy_get_by_node(ofnode node, int index, struct phy *phy);
+
+/**
  * generic_phy_get_by_name() - Get a PHY device by its name.
  *
  * @user:	the client device