Browse Source

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

- generate unique mac address from SoC serial on S400 board
- Add USB support for GXL and AXG SoCs
- Update Gadget code to use the new GXL and AXG USB glue driver
- Add a VIM3 board support to add dynamic PCIe enable in OS DT
- Fix AXG pinmux with requesting GPIOs
- Add missing GPIOA_18 for AXG pinctrl
- Add Amlogic PWM driver
Tom Rini 3 years ago
parent
commit
987ab49366
63 changed files with 2315 additions and 397 deletions
  1. 12 0
      arch/arm/dts/meson-axg-s400-u-boot.dtsi
  2. 62 0
      arch/arm/dts/meson-axg-u-boot.dtsi
  3. 3 3
      arch/arm/dts/meson-axg.dtsi
  4. 38 17
      arch/arm/dts/meson-g12-common.dtsi
  5. 131 5
      arch/arm/dts/meson-g12b-odroid-n2.dts
  6. 75 3
      arch/arm/dts/meson-gx-libretech-pc.dtsi
  7. 18 5
      arch/arm/dts/meson-gx.dtsi
  8. 1 1
      arch/arm/dts/meson-gxbb-nanopi-k2.dts
  9. 1 1
      arch/arm/dts/meson-gxbb-odroidc2.dts
  10. 23 0
      arch/arm/dts/meson-gxbb.dtsi
  11. 0 4
      arch/arm/dts/meson-gxl-s805x-libretech-ac-u-boot.dtsi
  12. 72 1
      arch/arm/dts/meson-gxl-s805x-libretech-ac.dts
  13. 0 4
      arch/arm/dts/meson-gxl-s905d-libretech-pc-u-boot.dtsi
  14. 0 4
      arch/arm/dts/meson-gxl-s905x-khadas-vim-u-boot.dtsi
  15. 4 0
      arch/arm/dts/meson-gxl-s905x-khadas-vim.dts
  16. 0 4
      arch/arm/dts/meson-gxl-s905x-libretech-cc-u-boot.dtsi
  17. 74 3
      arch/arm/dts/meson-gxl-s905x-libretech-cc.dts
  18. 2 1
      arch/arm/dts/meson-gxl-s905x-p212.dtsi
  19. 0 16
      arch/arm/dts/meson-gxl-u-boot.dtsi
  20. 59 20
      arch/arm/dts/meson-gxl.dtsi
  21. 0 4
      arch/arm/dts/meson-gxm-khadas-vim2-u-boot.dtsi
  22. 2 1
      arch/arm/dts/meson-gxm-khadas-vim2.dts
  23. 0 4
      arch/arm/dts/meson-gxm-s912-libretech-pc-u-boot.dtsi
  24. 5 2
      arch/arm/dts/meson-gxm.dtsi
  25. 24 2
      arch/arm/dts/meson-khadas-vim3.dtsi
  26. 92 0
      arch/arm/dts/meson-sm1-khadas-vim3l.dts
  27. 88 0
      arch/arm/dts/meson-sm1-odroid-c4.dts
  28. 2 1
      arch/arm/include/asm/arch-meson/usb-gx.h
  29. 128 0
      arch/arm/mach-meson/board-axg.c
  30. 72 55
      arch/arm/mach-meson/board-gx.c
  31. 2 0
      board/amlogic/s400/s400.c
  32. 9 0
      board/amlogic/vim3/MAINTAINERS
  33. 6 0
      board/amlogic/vim3/Makefile
  34. 81 0
      board/amlogic/vim3/khadas-mcu.h
  35. 137 0
      board/amlogic/vim3/vim3.c
  36. 0 4
      board/amlogic/w400/MAINTAINERS
  37. 1 1
      configs/khadas-vim2_defconfig
  38. 4 1
      configs/khadas-vim3_defconfig
  39. 4 1
      configs/khadas-vim3l_defconfig
  40. 1 1
      configs/khadas-vim_defconfig
  41. 1 1
      configs/libretech-ac_defconfig
  42. 1 1
      configs/libretech-cc_defconfig
  43. 1 1
      configs/libretech-s905d-pc_defconfig
  44. 1 1
      configs/libretech-s912-pc_defconfig
  45. 1 1
      configs/p212_defconfig
  46. 15 0
      configs/s400_defconfig
  47. 27 0
      doc/board/amlogic/khadas-vim3.rst
  48. 27 0
      doc/board/amlogic/khadas-vim3l.rst
  49. 1 1
      drivers/phy/Kconfig
  50. 1 1
      drivers/phy/Makefile
  51. 0 219
      drivers/phy/meson-gxl-usb3.c
  52. 4 1
      drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c
  53. 1 0
      drivers/pinctrl/meson/pinctrl-meson-axg.c
  54. 7 0
      drivers/pwm/Kconfig
  55. 1 0
      drivers/pwm/Makefile
  56. 528 0
      drivers/pwm/pwm-meson.c
  57. 8 0
      drivers/usb/dwc3/Kconfig
  58. 1 0
      drivers/usb/dwc3/Makefile
  59. 425 0
      drivers/usb/dwc3/dwc3-meson-gxl.c
  60. 2 0
      include/dt-bindings/clock/g12a-clkc.h
  61. 1 1
      include/dt-bindings/reset/amlogic,meson-gxbb-reset.h
  62. 18 0
      include/dt-bindings/sound/meson-aiu.h
  63. 10 0
      include/dt-bindings/sound/meson-g12a-toacodec.h

+ 12 - 0
arch/arm/dts/meson-axg-s400-u-boot.dtsi

@@ -3,6 +3,8 @@
  * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
  * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
  */
  */
 
 
+#include "meson-axg-u-boot.dtsi"
+
 /* wifi module */
 /* wifi module */
 &sd_emmc_b {
 &sd_emmc_b {
 	status = "disabled";
 	status = "disabled";
@@ -12,3 +14,13 @@
 &sd_emmc_c {
 &sd_emmc_c {
 	status = "okay";
 	status = "okay";
 };
 };
+
+&usb {
+	status = "okay";
+	dr_mode = "otg";
+	vbus-supply = <&usb_pwr>;
+};
+
+&usb2_phy1 {
+	phy-supply = <&vcc_5v>;
+};

+ 62 - 0
arch/arm/dts/meson-axg-u-boot.dtsi

@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+/ {
+	soc {
+		usb: usb@ffe09080 {
+			compatible = "amlogic,meson-gxl-usb-ctrl";
+			reg = <0x0 0xffe09080 0x0 0x20>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1_DDR_BRIDGE>;
+			clock-names = "usb_ctrl", "ddr";
+			resets = <&reset RESET_USB_OTG>;
+
+			dr_mode = "otg";
+
+			phys = <&usb2_phy1>;
+			phy-names = "usb2-phy1";
+
+			dwc2: usb@ff400000 {
+				compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
+				reg = <0x0 0xff400000 0x0 0x40000>;
+				interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clkc CLKID_USB1>;
+				clock-names = "otg";
+				phys = <&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>;
+			};
+
+			dwc3: usb@ff500000 {
+				compatible = "snps,dwc3";
+				reg = <0x0 0xff500000 0x0 0x100000>;
+				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+				dr_mode = "host";
+				maximum-speed = "high-speed";
+				snps,dis_u2_susphy_quirk;
+			};
+		};
+	};
+};
+
+&apb {
+	usb2_phy1: phy@9020 {
+		compatible = "amlogic,meson-gxl-usb2-phy";
+		#phy-cells = <0>;
+		reg = <0x0 0x9020 0x0 0x20>;
+		clocks = <&clkc CLKID_USB>;
+		clock-names = "phy";
+		resets = <&reset RESET_USB_OTG>;
+		reset-names = "phy";
+		status = "okay";
+	};
+};

+ 3 - 3
arch/arm/dts/meson-axg.dtsi

@@ -1735,18 +1735,18 @@
 		};
 		};
 
 
 		sram: sram@fffc0000 {
 		sram: sram@fffc0000 {
-			compatible = "amlogic,meson-axg-sram", "mmio-sram";
+			compatible = "mmio-sram";
 			reg = <0x0 0xfffc0000 0x0 0x20000>;
 			reg = <0x0 0xfffc0000 0x0 0x20000>;
 			#address-cells = <1>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x0 0xfffc0000 0x20000>;
 			ranges = <0 0x0 0xfffc0000 0x20000>;
 
 
-			cpu_scp_lpri: scp-shmem@13000 {
+			cpu_scp_lpri: scp-sram@13000 {
 				compatible = "amlogic,meson-axg-scp-shmem";
 				compatible = "amlogic,meson-axg-scp-shmem";
 				reg = <0x13000 0x400>;
 				reg = <0x13000 0x400>;
 			};
 			};
 
 
-			cpu_scp_hpri: scp-shmem@13400 {
+			cpu_scp_hpri: scp-sram@13400 {
 				compatible = "amlogic,meson-axg-scp-shmem";
 				compatible = "amlogic,meson-axg-scp-shmem";
 				reg = <0x13400 0x400>;
 				reg = <0x13400 0x400>;
 			};
 			};

+ 38 - 17
arch/arm/dts/meson-g12-common.dtsi

@@ -52,6 +52,39 @@
 		secure-monitor = <&sm>;
 		secure-monitor = <&sm>;
 	};
 	};
 
 
+	gpu_opp_table: gpu-opp-table {
+		compatible = "operating-points-v2";
+
+		opp-124999998 {
+			opp-hz = /bits/ 64 <124999998>;
+			opp-microvolt = <800000>;
+		};
+		opp-249999996 {
+			opp-hz = /bits/ 64 <249999996>;
+			opp-microvolt = <800000>;
+		};
+		opp-285714281 {
+			opp-hz = /bits/ 64 <285714281>;
+			opp-microvolt = <800000>;
+		};
+		opp-399999994 {
+			opp-hz = /bits/ 64 <399999994>;
+			opp-microvolt = <800000>;
+		};
+		opp-499999992 {
+			opp-hz = /bits/ 64 <499999992>;
+			opp-microvolt = <800000>;
+		};
+		opp-666666656 {
+			opp-hz = /bits/ 64 <666666656>;
+			opp-microvolt = <800000>;
+		};
+		opp-799999987 {
+			opp-hz = /bits/ 64 <799999987>;
+			opp-microvolt = <800000>;
+		};
+	};
+
 	psci {
 	psci {
 		compatible = "arm,psci-1.0";
 		compatible = "arm,psci-1.0";
 		method = "smc";
 		method = "smc";
@@ -185,8 +218,10 @@
 			interrupt-names = "macirq";
 			interrupt-names = "macirq";
 			clocks = <&clkc CLKID_ETH>,
 			clocks = <&clkc CLKID_ETH>,
 				 <&clkc CLKID_FCLK_DIV2>,
 				 <&clkc CLKID_FCLK_DIV2>,
-				 <&clkc CLKID_MPLL2>;
-			clock-names = "stmmaceth", "clkin0", "clkin1";
+				 <&clkc CLKID_MPLL2>,
+				 <&clkc CLKID_FCLK_DIV2>;
+			clock-names = "stmmaceth", "clkin0", "clkin1",
+				      "timing-adjustment";
 			rx-fifo-depth = <4096>;
 			rx-fifo-depth = <4096>;
 			tx-fifo-depth = <2048>;
 			tx-fifo-depth = <2048>;
 			status = "disabled";
 			status = "disabled";
@@ -2360,21 +2395,7 @@
 			interrupt-names = "job", "mmu", "gpu";
 			interrupt-names = "job", "mmu", "gpu";
 			clocks = <&clkc CLKID_MALI>;
 			clocks = <&clkc CLKID_MALI>;
 			resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>;
 			resets = <&reset RESET_DVALIN_CAPB3>, <&reset RESET_DVALIN>;
-
-			/*
-			 * Mali clocking is provided by two identical clock paths
-			 * MALI_0 and MALI_1 muxed to a single clock by a glitch
-			 * free mux to safely change frequency while running.
-			 */
-			assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
-					  <&clkc CLKID_MALI_0>,
-					  <&clkc CLKID_MALI>; /* Glitch free mux */
-			assigned-clock-parents = <&clkc CLKID_FCLK_DIV2P5>,
-						 <0>, /* Do Nothing */
-						 <&clkc CLKID_MALI_0>;
-			assigned-clock-rates = <0>, /* Do Nothing */
-					       <800000000>,
-					       <0>; /* Do Nothing */
+			operating-points-v2 = <&gpu_opp_table>;
 			#cooling-cells = <2>;
 			#cooling-cells = <2>;
 		};
 		};
 	};
 	};

+ 131 - 5
arch/arm/dts/meson-g12b-odroid-n2.dts

@@ -9,6 +9,7 @@
 #include "meson-g12b-s922x.dtsi"
 #include "meson-g12b-s922x.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/meson-g12a-gpio.h>
 #include <dt-bindings/gpio/meson-g12a-gpio.h>
+#include <dt-bindings/sound/meson-g12a-toacodec.h>
 #include <dt-bindings/sound/meson-g12a-tohdmitx.h>
 #include <dt-bindings/sound/meson-g12a-tohdmitx.h>
 
 
 / {
 / {
@@ -20,6 +21,14 @@
 		ethernet0 = &ethmac;
 		ethernet0 = &ethmac;
 	};
 	};
 
 
+	dioo2133: audio-amplifier-0 {
+		compatible = "simple-audio-amplifier";
+		enable-gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
+		VCC-supply = <&vcc_5v>;
+		sound-name-prefix = "U19";
+		status = "okay";
+	};
+
 	chosen {
 	chosen {
 		stdout-path = "serial0:115200n8";
 		stdout-path = "serial0:115200n8";
 	};
 	};
@@ -209,11 +218,42 @@
 	sound {
 	sound {
 		compatible = "amlogic,axg-sound-card";
 		compatible = "amlogic,axg-sound-card";
 		model = "G12B-ODROID-N2";
 		model = "G12B-ODROID-N2";
-		audio-aux-devs = <&tdmout_b>;
+		audio-widgets = "Line", "Lineout";
+		audio-aux-devs = <&tdmout_b>, <&tdmout_c>, <&tdmin_a>,
+				 <&tdmin_b>, <&tdmin_c>, <&tdmin_lb>,
+				 <&dioo2133>;
 		audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
 		audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
 				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
 				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
 				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
 				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
-				"TDM_B Playback", "TDMOUT_B OUT";
+				"TDM_B Playback", "TDMOUT_B OUT",
+				"TDMOUT_C IN 0", "FRDDR_A OUT 2",
+				"TDMOUT_C IN 1", "FRDDR_B OUT 2",
+				"TDMOUT_C IN 2", "FRDDR_C OUT 2",
+				"TDM_C Playback", "TDMOUT_C OUT",
+				"TDMIN_A IN 4", "TDM_B Loopback",
+				"TDMIN_B IN 4", "TDM_B Loopback",
+				"TDMIN_C IN 4", "TDM_B Loopback",
+				"TDMIN_LB IN 1", "TDM_B Loopback",
+				"TDMIN_A IN 5", "TDM_C Loopback",
+				"TDMIN_B IN 5", "TDM_C Loopback",
+				"TDMIN_C IN 5", "TDM_C Loopback",
+				"TDMIN_LB IN 2", "TDM_C Loopback",
+				"TODDR_A IN 0", "TDMIN_A OUT",
+				"TODDR_B IN 0", "TDMIN_A OUT",
+				"TODDR_C IN 0", "TDMIN_A OUT",
+				"TODDR_A IN 1", "TDMIN_B OUT",
+				"TODDR_B IN 1", "TDMIN_B OUT",
+				"TODDR_C IN 1", "TDMIN_B OUT",
+				"TODDR_A IN 2", "TDMIN_C OUT",
+				"TODDR_B IN 2", "TDMIN_C OUT",
+				"TODDR_C IN 2", "TDMIN_C OUT",
+				"TODDR_A IN 6", "TDMIN_LB OUT",
+				"TODDR_B IN 6", "TDMIN_LB OUT",
+				"TODDR_C IN 6", "TDMIN_LB OUT",
+				"U19 INL", "ACODEC LOLP",
+				"U19 INR", "ACODEC LORP",
+				"Lineout", "U19 OUTL",
+				"Lineout", "U19 OUTR";
 
 
 		assigned-clocks = <&clkc CLKID_MPLL2>,
 		assigned-clocks = <&clkc CLKID_MPLL2>,
 				  <&clkc CLKID_MPLL0>,
 				  <&clkc CLKID_MPLL0>,
@@ -236,8 +276,20 @@
 			sound-dai = <&frddr_c>;
 			sound-dai = <&frddr_c>;
 		};
 		};
 
 
-		/* 8ch hdmi interface */
 		dai-link-3 {
 		dai-link-3 {
+			sound-dai = <&toddr_a>;
+		};
+
+		dai-link-4 {
+			sound-dai = <&toddr_b>;
+		};
+
+		dai-link-5 {
+			sound-dai = <&toddr_c>;
+		};
+
+		/* 8ch hdmi interface */
+		dai-link-6 {
 			sound-dai = <&tdmif_b>;
 			sound-dai = <&tdmif_b>;
 			dai-format = "i2s";
 			dai-format = "i2s";
 			dai-tdm-slot-tx-mask-0 = <1 1>;
 			dai-tdm-slot-tx-mask-0 = <1 1>;
@@ -246,22 +298,56 @@
 			dai-tdm-slot-tx-mask-3 = <1 1>;
 			dai-tdm-slot-tx-mask-3 = <1 1>;
 			mclk-fs = <256>;
 			mclk-fs = <256>;
 
 
-			codec {
+			codec-0 {
 				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
 				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
 			};
 			};
+
+			codec-1 {
+				sound-dai = <&toacodec TOACODEC_IN_B>;
+			};
+		};
+
+		/* i2s jack output interface */
+		dai-link-7 {
+			sound-dai = <&tdmif_c>;
+			dai-format = "i2s";
+			dai-tdm-slot-tx-mask-0 = <1 1>;
+			mclk-fs = <256>;
+
+			codec-0 {
+				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_C>;
+			};
+
+			codec-1 {
+				sound-dai = <&toacodec TOACODEC_IN_C>;
+			};
 		};
 		};
 
 
 		/* hdmi glue */
 		/* hdmi glue */
-		dai-link-4 {
+		dai-link-8 {
 			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
 			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
 
 
 			codec {
 			codec {
 				sound-dai = <&hdmi_tx>;
 				sound-dai = <&hdmi_tx>;
 			};
 			};
 		};
 		};
+
+		/* acodec glue */
+		dai-link-9 {
+			sound-dai = <&toacodec TOACODEC_OUT>;
+
+			codec {
+				sound-dai = <&acodec>;
+			};
+		};
 	};
 	};
 };
 };
 
 
+&acodec {
+	AVDD-supply = <&vddao_1v8>;
+	status = "okay";
+};
+
 &arb {
 &arb {
 	status = "okay";
 	status = "okay";
 };
 };
@@ -476,14 +562,54 @@
 	status = "okay";
 	status = "okay";
 };
 };
 
 
+&tdmif_c {
+	status = "okay";
+};
+
+&tdmin_a {
+	status = "okay";
+};
+
+&tdmin_b {
+	status = "okay";
+};
+
+&tdmin_c {
+	status = "okay";
+};
+
+&tdmin_lb {
+	status = "okay";
+};
+
 &tdmout_b {
 &tdmout_b {
 	status = "okay";
 	status = "okay";
 };
 };
 
 
+&tdmout_c {
+	status = "okay";
+};
+
+&toacodec {
+	status = "okay";
+};
+
 &tohdmitx {
 &tohdmitx {
 	status = "okay";
 	status = "okay";
 };
 };
 
 
+&toddr_a {
+	status = "okay";
+};
+
+&toddr_b {
+	status = "okay";
+};
+
+&toddr_c {
+	status = "okay";
+};
+
 &uart_AO {
 &uart_AO {
 	status = "okay";
 	status = "okay";
 	pinctrl-0 = <&uart_ao_a_pins>;
 	pinctrl-0 = <&uart_ao_a_pins>;

+ 75 - 3
arch/arm/dts/meson-gx-libretech-pc.dtsi

@@ -8,6 +8,7 @@
 
 
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/leds/common.h>
+#include <dt-bindings/sound/meson-aiu.h>
 
 
 / {
 / {
 	adc-keys {
 	adc-keys {
@@ -29,6 +30,13 @@
 		spi0 = &spifc;
 		spi0 = &spifc;
 	};
 	};
 
 
+	dio2133: analog-amplifier {
+		compatible = "simple-audio-amplifier";
+		sound-name-prefix = "AU2";
+		VCC-supply = <&vcc5v>;
+		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
+	};
+
 	chosen {
 	chosen {
 		stdout-path = "serial0:115200n8";
 		stdout-path = "serial0:115200n8";
 	};
 	};
@@ -96,14 +104,14 @@
 	leds {
 	leds {
 		compatible = "gpio-leds";
 		compatible = "gpio-leds";
 
 
-		green {
+		led-green {
 			color = <LED_COLOR_ID_GREEN>;
 			color = <LED_COLOR_ID_GREEN>;
 			function = LED_FUNCTION_DISK_ACTIVITY;
 			function = LED_FUNCTION_DISK_ACTIVITY;
 			gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>;
 			gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "disk-activity";
 			linux,default-trigger = "disk-activity";
 		};
 		};
 
 
-		blue {
+		led-blue {
 			color = <LED_COLOR_ID_BLUE>;
 			color = <LED_COLOR_ID_BLUE>;
 			function = LED_FUNCTION_STATUS;
 			function = LED_FUNCTION_STATUS;
 			gpios = <&gpio GPIODV_28 GPIO_ACTIVE_HIGH>;
 			gpios = <&gpio GPIODV_28 GPIO_ACTIVE_HIGH>;
@@ -175,6 +183,69 @@
 		regulator-settling-time-up-us = <200>;
 		regulator-settling-time-up-us = <200>;
 		regulator-settling-time-down-us = <50000>;
 		regulator-settling-time-down-us = <50000>;
 	};
 	};
+
+	sound {
+		compatible = "amlogic,gx-sound-card";
+		model = "GXL-LIBRETECH-S9XX-PC";
+		audio-aux-devs = <&dio2133>;
+		audio-widgets = "Speaker", "7J4-14 LEFT",
+				"Speaker", "7J4-11 RIGHT";
+		audio-routing = "AU2 INL", "ACODEC LOLN",
+				"AU2 INR", "ACODEC LORN",
+				"7J4-14 LEFT", "AU2 OUTL",
+				"7J4-11 RIGHT", "AU2 OUTR";
+		assigned-clocks = <&clkc CLKID_MPLL0>,
+				  <&clkc CLKID_MPLL1>,
+				  <&clkc CLKID_MPLL2>;
+		assigned-clock-parents = <0>, <0>, <0>;
+		assigned-clock-rates = <294912000>,
+				       <270950400>,
+				       <393216000>;
+		status = "okay";
+
+		dai-link-0 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+			dai-format = "i2s";
+			mclk-fs = <256>;
+
+			codec-0 {
+				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+			};
+
+			codec-1 {
+				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
+			};
+		};
+
+		dai-link-2 {
+			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&hdmi_tx>;
+			};
+		};
+
+		dai-link-3 {
+			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&acodec>;
+			};
+		};
+	};
+};
+
+&acodec {
+	AVDD-supply = <&vddio_ao18>;
+	status = "okay";
+};
+
+&aiu {
+	status = "okay";
 };
 };
 
 
 &cec_AO {
 &cec_AO {
@@ -360,8 +431,9 @@
 	status = "okay";
 	status = "okay";
 };
 };
 
 
-&usb0 {
+&usb {
 	status = "okay";
 	status = "okay";
+	dr_mode = "host";
 };
 };
 
 
 &usb2_phy0 {
 &usb2_phy0 {

+ 18 - 5
arch/arm/dts/meson-gx.dtsi

@@ -278,6 +278,17 @@
 				#reset-cells = <1>;
 				#reset-cells = <1>;
 			};
 			};
 
 
+			aiu: audio-controller@5400 {
+				compatible = "amlogic,aiu";
+				#sound-dai-cells = <2>;
+				sound-name-prefix = "AIU";
+				reg = <0x0 0x5400 0x0 0x2ac>;
+				interrupts = <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>,
+					     <GIC_SPI 50 IRQ_TYPE_EDGE_RISING>;
+				interrupt-names = "i2s", "spdif";
+				status = "disabled";
+			};
+
 			uart_A: serial@84c0 {
 			uart_A: serial@84c0 {
 				compatible = "amlogic,meson-gx-uart";
 				compatible = "amlogic,meson-gx-uart";
 				reg = <0x0 0x84c0 0x0 0x18>;
 				reg = <0x0 0x84c0 0x0 0x18>;
@@ -398,20 +409,20 @@
 		};
 		};
 
 
 		sram: sram@c8000000 {
 		sram: sram@c8000000 {
-			compatible = "amlogic,meson-gx-sram", "amlogic,meson-gxbb-sram", "mmio-sram";
+			compatible = "mmio-sram";
 			reg = <0x0 0xc8000000 0x0 0x14000>;
 			reg = <0x0 0xc8000000 0x0 0x14000>;
 
 
 			#address-cells = <1>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x0 0xc8000000 0x14000>;
 			ranges = <0 0x0 0xc8000000 0x14000>;
 
 
-			cpu_scp_lpri: scp-shmem@0 {
-				compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem";
+			cpu_scp_lpri: scp-sram@0 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
 				reg = <0x13000 0x400>;
 				reg = <0x13000 0x400>;
 			};
 			};
 
 
-			cpu_scp_hpri: scp-shmem@200 {
-				compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem";
+			cpu_scp_hpri: scp-sram@200 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
 				reg = <0x13400 0x400>;
 				reg = <0x13400 0x400>;
 			};
 			};
 		};
 		};
@@ -626,6 +637,8 @@
 			interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
 			interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
 			#address-cells = <1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			#size-cells = <0>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "HDMITX";
 			status = "disabled";
 			status = "disabled";
 
 
 			/* VPU VENC Input */
 			/* VPU VENC Input */

+ 1 - 1
arch/arm/dts/meson-gxbb-nanopi-k2.dts

@@ -29,7 +29,7 @@
 	leds {
 	leds {
 		compatible = "gpio-leds";
 		compatible = "gpio-leds";
 
 
-		stat {
+		led-stat {
 			label = "nanopi-k2:blue:stat";
 			label = "nanopi-k2:blue:stat";
 			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
 			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
 			default-state = "on";
 			default-state = "on";

+ 1 - 1
arch/arm/dts/meson-gxbb-odroidc2.dts

@@ -49,7 +49,7 @@
 
 
 	leds {
 	leds {
 		compatible = "gpio-leds";
 		compatible = "gpio-leds";
-		blue {
+		led-blue {
 			label = "c2:blue:alive";
 			label = "c2:blue:alive";
 			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_LOW>;
 			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_LOW>;
 			linux,default-trigger = "heartbeat";
 			linux,default-trigger = "heartbeat";

+ 23 - 0
arch/arm/dts/meson-gxbb.dtsi

@@ -60,6 +60,29 @@
 	};
 	};
 };
 };
 
 
+&aiu {
+	compatible = "amlogic,aiu-gxbb", "amlogic,aiu";
+	clocks = <&clkc CLKID_AIU_GLUE>,
+		 <&clkc CLKID_I2S_OUT>,
+		 <&clkc CLKID_AOCLK_GATE>,
+		 <&clkc CLKID_CTS_AMCLK>,
+		 <&clkc CLKID_MIXER_IFACE>,
+		 <&clkc CLKID_IEC958>,
+		 <&clkc CLKID_IEC958_GATE>,
+		 <&clkc CLKID_CTS_MCLK_I958>,
+		 <&clkc CLKID_CTS_I958>;
+	clock-names = "pclk",
+		      "i2s_pclk",
+		      "i2s_aoclk",
+		      "i2s_mclk",
+		      "i2s_mixer",
+		      "spdif_pclk",
+		      "spdif_aoclk",
+		      "spdif_mclk",
+		      "spdif_mclk_sel";
+	resets = <&reset RESET_AIU>;
+};
+
 &aobus {
 &aobus {
 	pinctrl_aobus: pinctrl@14 {
 	pinctrl_aobus: pinctrl@14 {
 		compatible = "amlogic,meson-gxbb-aobus-pinctrl";
 		compatible = "amlogic,meson-gxbb-aobus-pinctrl";

+ 0 - 4
arch/arm/dts/meson-gxl-s805x-libretech-ac-u-boot.dtsi

@@ -5,7 +5,3 @@
  */
  */
 
 
 #include "meson-gxl-u-boot.dtsi"
 #include "meson-gxl-u-boot.dtsi"
-
-&dwc2 {
-	status = "okay";
-};

+ 72 - 1
arch/arm/dts/meson-gxl-s805x-libretech-ac.dts

@@ -8,6 +8,7 @@
 /dts-v1/;
 /dts-v1/;
 
 
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/sound/meson-aiu.h>
 
 
 #include "meson-gxl-s905x.dtsi"
 #include "meson-gxl-s905x.dtsi"
 
 
@@ -97,6 +98,15 @@
 		regulator-always-on;
 		regulator-always-on;
 	};
 	};
 
 
+	vddio_ao18: regulator-vddio_ao18 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_AO18";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_3v3>;
+		regulator-always-on;
+	};
+
 	vddio_boot: regulator-vddio_boot {
 	vddio_boot: regulator-vddio_boot {
 		compatible = "regulator-fixed";
 		compatible = "regulator-fixed";
 		regulator-name = "VDDIO_BOOT";
 		regulator-name = "VDDIO_BOOT";
@@ -105,6 +115,66 @@
 		vin-supply = <&vcc_3v3>;
 		vin-supply = <&vcc_3v3>;
 		regulator-always-on;
 		regulator-always-on;
 	};
 	};
+
+	sound {
+		compatible = "amlogic,gx-sound-card";
+		model = "GXL-LIBRETECH-S805X-AC";
+		audio-widgets = "Speaker", "9J5-3 LEFT",
+				"Speaker", "9J5-2 RIGHT";
+		audio-routing = "9J5-3 LEFT", "ACODEC LOLN",
+				"9J5-2 RIGHT", "ACODEC LORN";
+		assigned-clocks = <&clkc CLKID_MPLL0>,
+				  <&clkc CLKID_MPLL1>,
+				  <&clkc CLKID_MPLL2>;
+		assigned-clock-parents = <0>, <0>, <0>;
+		assigned-clock-rates = <294912000>,
+				       <270950400>,
+				       <393216000>;
+		status = "okay";
+
+		dai-link-0 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+			dai-format = "i2s";
+			mclk-fs = <256>;
+
+			codec-0 {
+				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+			};
+
+			codec-1 {
+				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
+			};
+		};
+
+		dai-link-2 {
+			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&hdmi_tx>;
+			};
+		};
+
+		dai-link-3 {
+			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&acodec>;
+			};
+		};
+	};
+};
+
+&acodec {
+	AVDD-supply = <&vddio_ao18>;
+	status = "okay";
+};
+
+&aiu {
+	status = "okay";
 };
 };
 
 
 &cec_AO {
 &cec_AO {
@@ -243,6 +313,7 @@
 	pinctrl-names = "default";
 	pinctrl-names = "default";
 };
 };
 
 
-&usb0 {
+&usb {
 	status = "okay";
 	status = "okay";
+	dr_mode = "host";
 };
 };

+ 0 - 4
arch/arm/dts/meson-gxl-s905d-libretech-pc-u-boot.dtsi

@@ -5,7 +5,3 @@
  */
  */
 
 
 #include "meson-gxl-u-boot.dtsi"
 #include "meson-gxl-u-boot.dtsi"
-
-&dwc2 {
-	status = "okay";
-};

+ 0 - 4
arch/arm/dts/meson-gxl-s905x-khadas-vim-u-boot.dtsi

@@ -5,7 +5,3 @@
  */
  */
 
 
 #include "meson-gxl-u-boot.dtsi"
 #include "meson-gxl-u-boot.dtsi"
-
-&dwc2 {
-	status = "okay";
-};

+ 4 - 0
arch/arm/dts/meson-gxl-s905x-khadas-vim.dts

@@ -207,3 +207,7 @@
 	pinctrl-0 = <&uart_ao_b_pins>;
 	pinctrl-0 = <&uart_ao_b_pins>;
 	pinctrl-names = "default";
 	pinctrl-names = "default";
 };
 };
+
+&usb {
+	dr_mode = "peripheral";
+};

+ 0 - 4
arch/arm/dts/meson-gxl-s905x-libretech-cc-u-boot.dtsi

@@ -5,7 +5,3 @@
  */
  */
 
 
 #include "meson-gxl-u-boot.dtsi"
 #include "meson-gxl-u-boot.dtsi"
-
-&dwc2 {
-	status = "okay";
-};

+ 74 - 3
arch/arm/dts/meson-gxl-s905x-libretech-cc.dts

@@ -8,6 +8,7 @@
 /dts-v1/;
 /dts-v1/;
 
 
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/sound/meson-aiu.h>
 
 
 #include "meson-gxl-s905x.dtsi"
 #include "meson-gxl-s905x.dtsi"
 
 
@@ -21,6 +22,13 @@
 		ethernet0 = &ethmac;
 		ethernet0 = &ethmac;
 	};
 	};
 
 
+	dio2133: analog-amplifier {
+		compatible = "simple-audio-amplifier";
+		sound-name-prefix = "AU2";
+		VCC-supply = <&hdmi_5v>;
+		enable-gpios = <&gpio GPIOH_5 GPIO_ACTIVE_HIGH>;
+	};
+
 	chosen {
 	chosen {
 		stdout-path = "serial0:115200n8";
 		stdout-path = "serial0:115200n8";
 	};
 	};
@@ -54,14 +62,14 @@
 	leds {
 	leds {
 		compatible = "gpio-leds";
 		compatible = "gpio-leds";
 
 
-		system {
+		led-system {
 			label = "librecomputer:system-status";
 			label = "librecomputer:system-status";
 			gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
 			gpios = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
 			default-state = "on";
 			default-state = "on";
 			panic-indicator;
 			panic-indicator;
 		};
 		};
 
 
-		blue {
+		led-blue {
 			label = "librecomputer:blue";
 			label = "librecomputer:blue";
 			gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
 			gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 			linux,default-trigger = "heartbeat";
@@ -124,6 +132,68 @@
 		regulator-max-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
 		vin-supply = <&vcc_3v3>;
 		vin-supply = <&vcc_3v3>;
 	};
 	};
+
+	sound {
+		compatible = "amlogic,gx-sound-card";
+		model = "GXL-LIBRETECH-S905X-CC";
+		audio-aux-devs = <&dio2133>;
+		audio-widgets = "Line", "Lineout";
+		audio-routing = "AU2 INL", "ACODEC LOLN",
+				"AU2 INR", "ACODEC LORN",
+				"Lineout", "AU2 OUTL",
+				"Lineout", "AU2 OUTR";
+		assigned-clocks = <&clkc CLKID_MPLL0>,
+				  <&clkc CLKID_MPLL1>,
+				  <&clkc CLKID_MPLL2>;
+		assigned-clock-parents = <0>, <0>, <0>;
+		assigned-clock-rates = <294912000>,
+				       <270950400>,
+				       <393216000>;
+		status = "okay";
+
+		dai-link-0 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_FIFO>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&aiu AIU_CPU CPU_I2S_ENCODER>;
+			dai-format = "i2s";
+			mclk-fs = <256>;
+
+			codec-0 {
+				sound-dai = <&aiu AIU_HDMI CTRL_I2S>;
+			};
+
+			codec-1 {
+				sound-dai = <&aiu AIU_ACODEC CTRL_I2S>;
+			};
+		};
+
+		dai-link-2 {
+			sound-dai = <&aiu AIU_HDMI CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&hdmi_tx>;
+			};
+		};
+
+		dai-link-3 {
+			sound-dai = <&aiu AIU_ACODEC CTRL_OUT>;
+
+			codec-0 {
+				sound-dai = <&acodec>;
+			};
+		};
+	};
+};
+
+&acodec {
+	AVDD-supply = <&vddio_ao18>;
+	status = "okay";
+};
+
+&aiu {
+	status = "okay";
 };
 };
 
 
 &cec_AO {
 &cec_AO {
@@ -272,8 +342,9 @@
 	pinctrl-names = "default";
 	pinctrl-names = "default";
 };
 };
 
 
-&usb0 {
+&usb {
 	status = "okay";
 	status = "okay";
+	dr_mode = "host";
 };
 };
 
 
 &usb2_phy0 {
 &usb2_phy0 {

+ 2 - 1
arch/arm/dts/meson-gxl-s905x-p212.dtsi

@@ -195,8 +195,9 @@
 	pinctrl-names = "default";
 	pinctrl-names = "default";
 };
 };
 
 
-&usb0 {
+&usb {
 	status = "okay";
 	status = "okay";
+	dr_mode = "host";
 };
 };
 
 
 &usb2_phy0 {
 &usb2_phy0 {

+ 0 - 16
arch/arm/dts/meson-gxl-u-boot.dtsi

@@ -5,19 +5,3 @@
  */
  */
 
 
 #include "meson-gx-u-boot.dtsi"
 #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";
-	};
-};

+ 59 - 20
arch/arm/dts/meson-gxl.dtsi

@@ -14,29 +14,57 @@
 	compatible = "amlogic,meson-gxl";
 	compatible = "amlogic,meson-gxl";
 
 
 	soc {
 	soc {
-		usb0: usb@c9000000 {
-			status = "disabled";
-			compatible = "amlogic,meson-gxl-dwc3";
+		usb: usb@d0078080 {
+			compatible = "amlogic,meson-gxl-usb-ctrl";
+			reg = <0x0 0xd0078080 0x0 0x20>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <2>;
 			#address-cells = <2>;
 			#size-cells = <2>;
 			#size-cells = <2>;
 			ranges;
 			ranges;
 
 
-			clocks = <&clkc CLKID_USB>;
-			clock-names = "usb_general";
+			clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1_DDR_BRIDGE>;
+			clock-names = "usb_ctrl", "ddr";
 			resets = <&reset RESET_USB_OTG>;
 			resets = <&reset RESET_USB_OTG>;
-			reset-names = "usb_otg";
 
 
-			dwc3: dwc3@c9000000 {
+			dr_mode = "otg";
+
+			phys = <&usb2_phy0>, <&usb2_phy1>;
+			phy-names = "usb2-phy0", "usb2-phy1";
+
+			dwc2: usb@c9100000 {
+				compatible = "amlogic,meson-g12a-usb", "snps,dwc2";
+				reg = <0x0 0xc9100000 0x0 0x40000>;
+				interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clkc CLKID_USB1>;
+				clock-names = "otg";
+				phys = <&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>;
+			};
+
+			dwc3: usb@c9000000 {
 				compatible = "snps,dwc3";
 				compatible = "snps,dwc3";
 				reg = <0x0 0xc9000000 0x0 0x100000>;
 				reg = <0x0 0xc9000000 0x0 0x100000>;
 				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 				dr_mode = "host";
 				dr_mode = "host";
 				maximum-speed = "high-speed";
 				maximum-speed = "high-speed";
 				snps,dis_u2_susphy_quirk;
 				snps,dis_u2_susphy_quirk;
-				phys = <&usb3_phy>, <&usb2_phy0>, <&usb2_phy1>;
 			};
 			};
 		};
 		};
 
 
+		acodec: audio-controller@c8832000 {
+			compatible = "amlogic,t9015";
+			reg = <0x0 0xc8832000 0x0 0x14>;
+			#sound-dai-cells = <0>;
+			sound-name-prefix = "ACODEC";
+			clocks = <&clkc CLKID_ACODEC>;
+			clock-names = "pclk";
+			resets = <&reset RESET_ACODEC>;
+			status = "disabled";
+		};
+
 		crypto: crypto@c883e000 {
 		crypto: crypto@c883e000 {
 			compatible = "amlogic,gxl-crypto";
 			compatible = "amlogic,gxl-crypto";
 			reg = <0x0 0xc883e000 0x0 0x36>;
 			reg = <0x0 0xc883e000 0x0 0x36>;
@@ -49,6 +77,29 @@
 	};
 	};
 };
 };
 
 
+&aiu {
+	compatible = "amlogic,aiu-gxl", "amlogic,aiu";
+	clocks = <&clkc CLKID_AIU_GLUE>,
+		 <&clkc CLKID_I2S_OUT>,
+		 <&clkc CLKID_AOCLK_GATE>,
+		 <&clkc CLKID_CTS_AMCLK>,
+		 <&clkc CLKID_MIXER_IFACE>,
+		 <&clkc CLKID_IEC958>,
+		 <&clkc CLKID_IEC958_GATE>,
+		 <&clkc CLKID_CTS_MCLK_I958>,
+		 <&clkc CLKID_CTS_I958>;
+	clock-names = "pclk",
+		      "i2s_pclk",
+		      "i2s_aoclk",
+		      "i2s_mclk",
+		      "i2s_mixer",
+		      "spdif_pclk",
+		      "spdif_aoclk",
+		      "spdif_mclk",
+		      "spdif_mclk_sel";
+	resets = <&reset RESET_AIU>;
+};
+
 &apb {
 &apb {
 	usb2_phy0: phy@78000 {
 	usb2_phy0: phy@78000 {
 		compatible = "amlogic,meson-gxl-usb2-phy";
 		compatible = "amlogic,meson-gxl-usb2-phy";
@@ -71,18 +122,6 @@
 		reset-names = "phy";
 		reset-names = "phy";
 		status = "okay";
 		status = "okay";
 	};
 	};
-
-	usb3_phy: phy@78080 {
-		compatible = "amlogic,meson-gxl-usb3-phy";
-		#phy-cells = <0>;
-		reg = <0x0 0x78080 0x0 0x20>;
-		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&clkc CLKID_USB>, <&clkc_AO CLKID_AO_CEC_32K>;
-		clock-names = "phy", "peripheral";
-		resets = <&reset RESET_USB_OTG>, <&reset RESET_USB_OTG>;
-		reset-names = "phy", "peripheral";
-		status = "okay";
-	};
 };
 };
 
 
 &efuse {
 &efuse {

+ 0 - 4
arch/arm/dts/meson-gxm-khadas-vim2-u-boot.dtsi

@@ -12,10 +12,6 @@
 	};
 	};
 };
 };
 
 
-&dwc2 {
-	status = "okay";
-};
-
 &sd_emmc_c {
 &sd_emmc_c {
 	status = "okay";
 	status = "okay";
 	pinctrl-0 = <&emmc_pins>;
 	pinctrl-0 = <&emmc_pins>;

+ 2 - 1
arch/arm/dts/meson-gxm-khadas-vim2.dts

@@ -380,6 +380,7 @@
 	vref-supply = <&vddio_ao18>;
 	vref-supply = <&vddio_ao18>;
 };
 };
 
 
-&usb0 {
+&usb {
 	status = "okay";
 	status = "okay";
+	dr_mode = "peripheral";
 };
 };

+ 0 - 4
arch/arm/dts/meson-gxm-s912-libretech-pc-u-boot.dtsi

@@ -5,7 +5,3 @@
  */
  */
 
 
 #include "meson-gxl-u-boot.dtsi"
 #include "meson-gxl-u-boot.dtsi"
-
-&dwc2 {
-	status = "okay";
-};

+ 5 - 2
arch/arm/dts/meson-gxm.dtsi

@@ -169,8 +169,11 @@
 	compatible = "amlogic,meson-gxm-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
 	compatible = "amlogic,meson-gxm-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
 };
 };
 
 
-&dwc3 {
-	phys = <&usb3_phy>, <&usb2_phy0>, <&usb2_phy1>, <&usb2_phy2>;
+&usb {
+	compatible = "amlogic,meson-gxm-usb-ctrl";
+
+	phy-names = "usb2-phy0", "usb2-phy1", "usb2-phy2";
+	phys = <&usb2_phy0>, <&usb2_phy1>, <&usb2_phy2>;
 };
 };
 
 
 &vdec {
 &vdec {

+ 24 - 2
arch/arm/dts/meson-khadas-vim3.dtsi

@@ -183,6 +183,23 @@
 	hdmi-phandle = <&hdmi_tx>;
 	hdmi-phandle = <&hdmi_tx>;
 };
 };
 
 
+&cpu_thermal {
+	trips {
+		cpu_active: cpu-active {
+			temperature = <80000>; /* millicelsius */
+			hysteresis = <2000>; /* millicelsius */
+			type = "active";
+		};
+	};
+
+	cooling-maps {
+		map {
+			trip = <&cpu_active>;
+			cooling-device = <&khadas_mcu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+		};
+	};
+};
+
 &ext_mdio {
 &ext_mdio {
 	external_phy: ethernet-phy@0 {
 	external_phy: ethernet-phy@0 {
 		/* Realtek RTL8211F (0x001cc916) */
 		/* Realtek RTL8211F (0x001cc916) */
@@ -222,6 +239,12 @@
 	pinctrl-0 = <&i2c_ao_sck_pins>, <&i2c_ao_sda_pins>;
 	pinctrl-0 = <&i2c_ao_sck_pins>, <&i2c_ao_sda_pins>;
 	pinctrl-names = "default";
 	pinctrl-names = "default";
 
 
+	khadas_mcu: system-controller@18 {
+		compatible = "khadas,mcu";
+		reg = <0x18>;
+		#cooling-cells = <2>;
+	};
+
 	gpio_expander: gpio-controller@20 {
 	gpio_expander: gpio-controller@20 {
 		compatible = "ti,tca6408";
 		compatible = "ti,tca6408";
 		reg = <0x20>;
 		reg = <0x20>;
@@ -270,7 +293,6 @@
 
 
 	bus-width = <4>;
 	bus-width = <4>;
 	cap-sd-highspeed;
 	cap-sd-highspeed;
-	sd-uhs-sdr50;
 	max-frequency = <100000000>;
 	max-frequency = <100000000>;
 
 
 	non-removable;
 	non-removable;
@@ -337,7 +359,7 @@
 	pinctrl-0 = <&nor_pins>;
 	pinctrl-0 = <&nor_pins>;
 	pinctrl-names = "default";
 	pinctrl-names = "default";
 
 
-	w25q32: spi-flash@0 {
+	w25q128: spi-flash@0 {
 		#address-cells = <1>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		#size-cells = <1>;
 		compatible = "winbond,w25q128fw", "jedec,spi-nor";
 		compatible = "winbond,w25q128fw", "jedec,spi-nor";

+ 92 - 0
arch/arm/dts/meson-sm1-khadas-vim3l.dts

@@ -8,6 +8,7 @@
 
 
 #include "meson-sm1.dtsi"
 #include "meson-sm1.dtsi"
 #include "meson-khadas-vim3.dtsi"
 #include "meson-khadas-vim3.dtsi"
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
 
 
 / {
 / {
 	compatible = "khadas,vim3l", "amlogic,sm1";
 	compatible = "khadas,vim3l", "amlogic,sm1";
@@ -31,6 +32,69 @@
 		regulator-boot-on;
 		regulator-boot-on;
 		regulator-always-on;
 		regulator-always-on;
 	};
 	};
+
+	sound {
+		compatible = "amlogic,axg-sound-card";
+		model = "SM1-KHADAS-VIM3L";
+		audio-aux-devs = <&tdmout_a>;
+		audio-routing = "TDMOUT_A IN 0", "FRDDR_A OUT 0",
+				"TDMOUT_A IN 1", "FRDDR_B OUT 0",
+				"TDMOUT_A IN 2", "FRDDR_C OUT 0",
+				"TDM_A Playback", "TDMOUT_A OUT";
+
+		assigned-clocks = <&clkc CLKID_MPLL2>,
+				  <&clkc CLKID_MPLL0>,
+				  <&clkc CLKID_MPLL1>;
+		assigned-clock-parents = <0>, <0>, <0>;
+		assigned-clock-rates = <294912000>,
+				       <270950400>,
+				       <393216000>;
+		status = "okay";
+
+		dai-link-0 {
+			sound-dai = <&frddr_a>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&frddr_b>;
+		};
+
+		dai-link-2 {
+			sound-dai = <&frddr_c>;
+		};
+
+		/* 8ch hdmi interface */
+		dai-link-3 {
+			sound-dai = <&tdmif_a>;
+			dai-format = "i2s";
+			dai-tdm-slot-tx-mask-0 = <1 1>;
+			dai-tdm-slot-tx-mask-1 = <1 1>;
+			dai-tdm-slot-tx-mask-2 = <1 1>;
+			dai-tdm-slot-tx-mask-3 = <1 1>;
+			mclk-fs = <256>;
+
+			codec {
+				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_A>;
+			};
+		};
+
+		/* hdmi glue */
+		dai-link-4 {
+			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
+
+			codec {
+				sound-dai = <&hdmi_tx>;
+			};
+		};
+	};
+};
+
+&arb {
+	status = "okay";
+};
+
+&clkc_audio {
+	status = "okay";
 };
 };
 
 
 &cpu0 {
 &cpu0 {
@@ -61,6 +125,18 @@
 	clock-latency = <50000>;
 	clock-latency = <50000>;
 };
 };
 
 
+&frddr_a {
+	status = "okay";
+};
+
+&frddr_b {
+	status = "okay";
+};
+
+&frddr_c {
+	status = "okay";
+};
+
 &pwm_AO_cd {
 &pwm_AO_cd {
 	pinctrl-0 = <&pwm_ao_d_e_pins>;
 	pinctrl-0 = <&pwm_ao_d_e_pins>;
 	pinctrl-names = "default";
 	pinctrl-names = "default";
@@ -88,8 +164,24 @@
 	status = "okay";
 	status = "okay";
 };
 };
 
 
+&sd_emmc_a {
+	sd-uhs-sdr50;
+};
+
 &usb {
 &usb {
 	phys = <&usb2_phy0>, <&usb2_phy1>;
 	phys = <&usb2_phy0>, <&usb2_phy1>;
 	phy-names = "usb2-phy0", "usb2-phy1";
 	phy-names = "usb2-phy0", "usb2-phy1";
 };
 };
  */
  */
+
+&tdmif_a {
+	status = "okay";
+};
+
+&tdmout_a {
+	status = "okay";
+};
+
+&tohdmitx {
+	status = "okay";
+};

+ 88 - 0
arch/arm/dts/meson-sm1-odroid-c4.dts

@@ -8,6 +8,7 @@
 #include "meson-sm1.dtsi"
 #include "meson-sm1.dtsi"
 #include <dt-bindings/gpio/meson-g12a-gpio.h>
 #include <dt-bindings/gpio/meson-g12a-gpio.h>
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/leds/common.h>
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
 
 
 / {
 / {
 	compatible = "hardkernel,odroid-c4", "amlogic,sm1";
 	compatible = "hardkernel,odroid-c4", "amlogic,sm1";
@@ -186,6 +187,69 @@
 			};
 			};
 		};
 		};
 	};
 	};
+
+	sound {
+		compatible = "amlogic,axg-sound-card";
+		model = "SM1-ODROID-C4";
+		audio-aux-devs = <&tdmout_b>;
+		audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
+				"TDMOUT_B IN 1", "FRDDR_B OUT 1",
+				"TDMOUT_B IN 2", "FRDDR_C OUT 1",
+				"TDM_B Playback", "TDMOUT_B OUT";
+
+		assigned-clocks = <&clkc CLKID_MPLL2>,
+				  <&clkc CLKID_MPLL0>,
+				  <&clkc CLKID_MPLL1>;
+		assigned-clock-parents = <0>, <0>, <0>;
+		assigned-clock-rates = <294912000>,
+				       <270950400>,
+				       <393216000>;
+		status = "okay";
+
+		dai-link-0 {
+			sound-dai = <&frddr_a>;
+		};
+
+		dai-link-1 {
+			sound-dai = <&frddr_b>;
+		};
+
+		dai-link-2 {
+			sound-dai = <&frddr_c>;
+		};
+
+		/* 8ch hdmi interface */
+		dai-link-3 {
+			sound-dai = <&tdmif_b>;
+			dai-format = "i2s";
+			dai-tdm-slot-tx-mask-0 = <1 1>;
+			dai-tdm-slot-tx-mask-1 = <1 1>;
+			dai-tdm-slot-tx-mask-2 = <1 1>;
+			dai-tdm-slot-tx-mask-3 = <1 1>;
+			mclk-fs = <256>;
+
+			codec {
+				sound-dai = <&tohdmitx TOHDMITX_I2S_IN_B>;
+			};
+		};
+
+		/* hdmi glue */
+		dai-link-4 {
+			sound-dai = <&tohdmitx TOHDMITX_I2S_OUT>;
+
+			codec {
+				sound-dai = <&hdmi_tx>;
+			};
+		};
+	};
+};
+
+&arb {
+	status = "okay";
+};
+
+&clkc_audio {
+	status = "okay";
 };
 };
 
 
 &cpu0 {
 &cpu0 {
@@ -237,6 +301,18 @@
 	amlogic,tx-delay-ns = <2>;
 	amlogic,tx-delay-ns = <2>;
 };
 };
 
 
+&frddr_a {
+	status = "okay";
+};
+
+&frddr_b {
+	status = "okay";
+};
+
+&frddr_c {
+	status = "okay";
+};
+
 &gpio {
 &gpio {
 	gpio-line-names =
 	gpio-line-names =
 		/* GPIOZ */
 		/* GPIOZ */
@@ -381,6 +457,18 @@
 	vqmmc-supply = <&flash_1v8>;
 	vqmmc-supply = <&flash_1v8>;
 };
 };
 
 
+&tdmif_b {
+	status = "okay";
+};
+
+&tdmout_b {
+	status = "okay";
+};
+
+&tohdmitx {
+	status = "okay";
+};
+
 &uart_AO {
 &uart_AO {
 	status = "okay";
 	status = "okay";
 	pinctrl-0 = <&uart_ao_a_pins>;
 	pinctrl-0 = <&uart_ao_a_pins>;

+ 2 - 1
arch/arm/include/asm/arch-meson/usb-gx.h

@@ -11,6 +11,7 @@
 
 
 /* TOFIX add set_mode to struct phy_ops */
 /* 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_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);
+
+int dwc3_meson_gxl_force_mode(struct udevice *dev, enum usb_dr_mode mode);
 
 
 #endif
 #endif

+ 128 - 0
arch/arm/mach-meson/board-axg.c

@@ -14,6 +14,11 @@
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/armv8/mmu.h>
 #include <asm/armv8/mmu.h>
 #include <linux/sizes.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>
 #include <phy.h>
 
 
 DECLARE_GLOBAL_DATA_PTR;
 DECLARE_GLOBAL_DATA_PTR;
@@ -118,3 +123,126 @@ void meson_eth_init(phy_interface_t mode, unsigned int flags)
 	/* Enable power gate */
 	/* Enable power gate */
 	clrbits_le32(AXG_MEM_PD_REG_0, AXG_MEM_PD_REG_0_ETH_MASK);
 	clrbits_le32(AXG_MEM_PD_REG_0, AXG_MEM_PD_REG_0_ETH_MASK);
 }
 }
+
+#if CONFIG_IS_ENABLED(USB_DWC3_MESON_GXL) && \
+	CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
+static struct dwc2_plat_otg_data meson_gx_dwc2_data;
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	struct fdtdec_phandle_args args;
+	const void *blob = gd->fdt_blob;
+	int node, dwc2_node;
+	struct udevice *dev, *clk_dev;
+	struct clk clk;
+	int ret;
+
+	/* find the usb glue node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					     "amlogic,meson-gxl-usb-ctrl");
+	if (node < 0) {
+		debug("Not found usb-control node\n");
+		return -ENODEV;
+	}
+
+	if (!fdtdec_get_is_enabled(blob, node)) {
+		debug("usb is disabled in the device tree\n");
+		return -ENODEV;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
+	if (ret) {
+		debug("Not found usb-control device\n");
+		return ret;
+	}
+
+	/* find the dwc2 node */
+	dwc2_node = fdt_node_offset_by_compatible(blob, node,
+						  "amlogic,meson-g12a-usb");
+	if (dwc2_node < 0) {
+		debug("Not found dwc2 node\n");
+		return -ENODEV;
+	}
+
+	if (!fdtdec_get_is_enabled(blob, dwc2_node)) {
+		debug("dwc2 is disabled in the device tree\n");
+		return -ENODEV;
+	}
+
+	meson_gx_dwc2_data.regs_otg = fdtdec_get_addr(blob, dwc2_node, "reg");
+	if (meson_gx_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
+		debug("usbotg: can't get base address\n");
+		return -ENODATA;
+	}
+
+	/* Enable clock */
+	ret = fdtdec_parse_phandle_with_args(blob, 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_of_offset(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;
+	}
+
+	meson_gx_dwc2_data.rx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+						     "g-rx-fifo-size", 0);
+	meson_gx_dwc2_data.np_tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+							"g-np-tx-fifo-size", 0);
+	meson_gx_dwc2_data.tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+						     "g-tx-fifo-size", 0);
+
+	/* Switch to peripheral mode */
+	ret = dwc3_meson_gxl_force_mode(dev, USB_DR_MODE_PERIPHERAL);
+	if (ret)
+		return ret;
+
+	return dwc2_udc_probe(&meson_gx_dwc2_data);
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	const void *blob = gd->fdt_blob;
+	struct udevice *dev;
+	int node;
+	int ret;
+
+	/* find the usb glue node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					     "amlogic,meson-gxl-usb-ctrl");
+	if (node < 0) {
+		debug("Not found usb-control node\n");
+		return -ENODEV;
+	}
+
+	if (!fdtdec_get_is_enabled(blob, node))
+		return -ENODEV;
+
+	ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
+	if (ret)
+		return ret;
+
+	/* Switch to OTG mode */
+	ret = dwc3_meson_gxl_force_mode(dev, USB_DR_MODE_HOST);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+#endif

+ 72 - 55
arch/arm/mach-meson/board-gx.c

@@ -156,79 +156,70 @@ void meson_eth_init(phy_interface_t mode, unsigned int flags)
 	clrbits_le32(GX_MEM_PD_REG_0, GX_MEM_PD_REG_0_ETH_MASK);
 	clrbits_le32(GX_MEM_PD_REG_0, GX_MEM_PD_REG_0_ETH_MASK);
 }
 }
 
 
-#if CONFIG_IS_ENABLED(USB_XHCI_DWC3_OF_SIMPLE) && \
+#if CONFIG_IS_ENABLED(USB_DWC3_MESON_GXL) && \
 	CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
 	CONFIG_IS_ENABLED(USB_GADGET_DWC2_OTG)
 static struct dwc2_plat_otg_data meson_gx_dwc2_data;
 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)
 int board_usb_init(int index, enum usb_init_type init)
 {
 {
-	struct ofnode_phandle_args args;
-	struct udevice *clk_dev;
-	ofnode dwc2_node;
+	struct fdtdec_phandle_args args;
+	const void *blob = gd->fdt_blob;
+	int node, dwc2_node;
+	struct udevice *dev, *clk_dev;
 	struct clk clk;
 	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;
+	int ret;
+
+	/* find the usb glue node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					     "amlogic,meson-gxl-usb-ctrl");
+	if (node < 0) {
+		node = fdt_node_offset_by_compatible(blob, -1,
+					"amlogic,meson-gxm-usb-ctrl");
+		if (node < 0) {
+			debug("Not found usb-control node\n");
+			return -ENODEV;
+		}
 	}
 	}
 
 
-	if (!ofnode_is_available(dwc2_node)) {
-		debug("dwc2 is disabled in the device tree\n");
+	if (!fdtdec_get_is_enabled(blob, node)) {
+		debug("usb is disabled in the device tree\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	/* get the PHYs */
-	for (i = 0; i < 2; i++) {
-		ret = generic_phy_get_by_index_nodev(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;
-		}
+	ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
+	if (ret) {
+		debug("Not found usb-control device\n");
+		return ret;
 	}
 	}
 
 
-	for (i = 0; i < 2; i++) {
-		ret = generic_phy_init(&usb_phys[i]);
-		if (ret) {
-			pr_debug("Can't init USB PHY%d for %s\n",
-				 i, ofnode_get_name(dwc2_node));
-			return ret;
-		}
+	/* find the dwc2 node */
+	dwc2_node = fdt_node_offset_by_compatible(blob, node,
+						  "amlogic,meson-g12a-usb");
+	if (dwc2_node < 0) {
+		debug("Not found dwc2 node\n");
+		return -ENODEV;
 	}
 	}
 
 
-	for (i = 0; i < 2; i++) {
-		ret = generic_phy_power_on(&usb_phys[i]);
-		if (ret) {
-			pr_debug("Can't power USB PHY%d for %s\n",
-				 i, ofnode_get_name(dwc2_node));
-			return ret;
-		}
+	if (!fdtdec_get_is_enabled(blob, dwc2_node)) {
+		debug("dwc2 is disabled in the device tree\n");
+		return -ENODEV;
 	}
 	}
 
 
-	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);
+	meson_gx_dwc2_data.regs_otg = fdtdec_get_addr(blob, dwc2_node, "reg");
 	if (meson_gx_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
 	if (meson_gx_dwc2_data.regs_otg == FDT_ADDR_T_NONE) {
 		debug("usbotg: can't get base address\n");
 		debug("usbotg: can't get base address\n");
 		return -ENODATA;
 		return -ENODATA;
 	}
 	}
 
 
 	/* Enable clock */
 	/* Enable clock */
-	ret = ofnode_parse_phandle_with_args(dwc2_node, "clocks",
+	ret = fdtdec_parse_phandle_with_args(blob, dwc2_node, "clocks",
 					     "#clock-cells", 0, 0, &args);
 					     "#clock-cells", 0, 0, &args);
 	if (ret) {
 	if (ret) {
 		debug("usbotg has no clocks defined in the device tree\n");
 		debug("usbotg has no clocks defined in the device tree\n");
 		return ret;
 		return ret;
 	}
 	}
 
 
-	ret = uclass_get_device_by_ofnode(UCLASS_CLK, args.node, &clk_dev);
+	ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &clk_dev);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
@@ -246,25 +237,51 @@ int board_usb_init(int index, enum usb_init_type init)
 		return ret;
 		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;
+	meson_gx_dwc2_data.rx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+						     "g-rx-fifo-size", 0);
+	meson_gx_dwc2_data.np_tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+							"g-np-tx-fifo-size", 0);
+	meson_gx_dwc2_data.tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
+						     "g-tx-fifo-size", 0);
+
+	/* Switch to peripheral mode */
+	ret = dwc3_meson_gxl_force_mode(dev, USB_DR_MODE_PERIPHERAL);
+	if (ret)
+		return ret;
 
 
 	return dwc2_udc_probe(&meson_gx_dwc2_data);
 	return dwc2_udc_probe(&meson_gx_dwc2_data);
 }
 }
 
 
 int board_usb_cleanup(int index, enum usb_init_type init)
 int board_usb_cleanup(int index, enum usb_init_type init)
 {
 {
-	int i;
+	const void *blob = gd->fdt_blob;
+	struct udevice *dev;
+	int node;
+	int ret;
+
+	/* find the usb glue node */
+	node = fdt_node_offset_by_compatible(blob, -1,
+					     "amlogic,meson-gxl-usb-ctrl");
+	if (node < 0) {
+		node = fdt_node_offset_by_compatible(blob, -1,
+					"amlogic,meson-gxm-usb-ctrl");
+		if (node < 0) {
+			debug("Not found usb-control node\n");
+			return -ENODEV;
+		}
+	}
 
 
-	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);
+	if (!fdtdec_get_is_enabled(blob, node))
+		return -ENODEV;
 
 
-	for (i = 0; i < 2; i++)
-		usb_phys[i].dev = NULL;
+	ret = uclass_get_device_by_of_offset(UCLASS_SIMPLE_BUS, node, &dev);
+	if (ret)
+		return ret;
+
+	/* Switch to OTG mode */
+	ret = dwc3_meson_gxl_force_mode(dev, USB_DR_MODE_HOST);
+	if (ret)
+		return ret;
 
 
 	return 0;
 	return 0;
 }
 }

+ 2 - 0
board/amlogic/s400/s400.c

@@ -18,5 +18,7 @@ int misc_init_r(void)
 {
 {
 	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
 	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
 
 
+	meson_generate_serial_ethaddr();
+
 	return 0;
 	return 0;
 }
 }

+ 9 - 0
board/amlogic/vim3/MAINTAINERS

@@ -0,0 +1,9 @@
+VIM3
+M:	Neil Armstrong <narmstrong@baylibre.com>
+S:	Maintained
+L:	u-boot-amlogic@groups.io
+F:	board/amlogic/vim3/
+F:	configs/khadas-vim3_defconfig
+F:	configs/khadas-vim3l_defconfig
+F:	doc/board/amlogic/khadas-vim3.rst
+F:	doc/board/amlogic/khadas-vim3l.rst

+ 6 - 0
board/amlogic/vim3/Makefile

@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2020 BayLibre, SAS
+# Author: Neil Armstrong <narmstrong@baylibre.com>
+
+obj-y	:= vim3.o

+ 81 - 0
board/amlogic/vim3/khadas-mcu.h

@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Khadas System control Microcontroller Register map
+ *
+ * Copyright (C) 2020 BayLibre SAS
+ *
+ * Author(s): Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef MFD_KHADAS_MCU_H
+#define MFD_KHADAS_MCU_H
+
+#define KHADAS_MCU_PASSWD_VEN_0_REG		0x00 /* RO */
+#define KHADAS_MCU_PASSWD_VEN_1_REG		0x01 /* RO */
+#define KHADAS_MCU_PASSWD_VEN_2_REG		0x02 /* RO */
+#define KHADAS_MCU_PASSWD_VEN_3_REG		0x03 /* RO */
+#define KHADAS_MCU_PASSWD_VEN_4_REG		0x04 /* RO */
+#define KHADAS_MCU_PASSWD_VEN_5_REG		0x05 /* RO */
+#define KHADAS_MCU_MAC_0_REG			0x06 /* RO */
+#define KHADAS_MCU_MAC_1_REG			0x07 /* RO */
+#define KHADAS_MCU_MAC_2_REG			0x08 /* RO */
+#define KHADAS_MCU_MAC_3_REG			0x09 /* RO */
+#define KHADAS_MCU_MAC_4_REG			0x0a /* RO */
+#define KHADAS_MCU_MAC_5_REG			0x0b /* RO */
+#define KHADAS_MCU_USID_0_REG			0x0c /* RO */
+#define KHADAS_MCU_USID_1_REG			0x0d /* RO */
+#define KHADAS_MCU_USID_2_REG			0x0e /* RO */
+#define KHADAS_MCU_USID_3_REG			0x0f /* RO */
+#define KHADAS_MCU_USID_4_REG			0x10 /* RO */
+#define KHADAS_MCU_USID_5_REG			0x11 /* RO */
+#define KHADAS_MCU_VERSION_0_REG		0x12 /* RO */
+#define KHADAS_MCU_VERSION_1_REG		0x13 /* RO */
+#define KHADAS_MCU_DEVICE_NO_0_REG		0x14 /* RO */
+#define KHADAS_MCU_DEVICE_NO_1_REG		0x15 /* RO */
+#define KHADAS_MCU_FACTORY_TEST_REG		0x16 /* R */
+#define KHADAS_MCU_BOOT_MODE_REG		0x20 /* RW */
+#define KHADAS_MCU_BOOT_EN_WOL_REG		0x21 /* RW */
+#define KHADAS_MCU_BOOT_EN_RTC_REG		0x22 /* RW */
+#define KHADAS_MCU_BOOT_EN_EXP_REG		0x23 /* RW */
+#define KHADAS_MCU_BOOT_EN_IR_REG		0x24 /* RW */
+#define KHADAS_MCU_BOOT_EN_DCIN_REG		0x25 /* RW */
+#define KHADAS_MCU_BOOT_EN_KEY_REG		0x26 /* RW */
+#define KHADAS_MCU_KEY_MODE_REG			0x27 /* RW */
+#define KHADAS_MCU_LED_MODE_ON_REG		0x28 /* RW */
+#define KHADAS_MCU_LED_MODE_OFF_REG		0x29 /* RW */
+#define KHADAS_MCU_SHUTDOWN_NORMAL_REG		0x2c /* RW */
+#define KHADAS_MCU_MAC_SWITCH_REG		0x2d /* RW */
+#define KHADAS_MCU_MCU_SLEEP_MODE_REG		0x2e /* RW */
+#define KHADAS_MCU_IR_CODE1_0_REG		0x2f /* RW */
+#define KHADAS_MCU_IR_CODE1_1_REG		0x30 /* RW */
+#define KHADAS_MCU_IR_CODE1_2_REG		0x31 /* RW */
+#define KHADAS_MCU_IR_CODE1_3_REG		0x32 /* RW */
+#define KHADAS_MCU_USB_PCIE_SWITCH_REG		0x33 /* RW */
+#define KHADAS_MCU_IR_CODE2_0_REG		0x34 /* RW */
+#define KHADAS_MCU_IR_CODE2_1_REG		0x35 /* RW */
+#define KHADAS_MCU_IR_CODE2_2_REG		0x36 /* RW */
+#define KHADAS_MCU_IR_CODE2_3_REG		0x37 /* RW */
+#define KHADAS_MCU_PASSWD_USER_0_REG		0x40 /* RW */
+#define KHADAS_MCU_PASSWD_USER_1_REG		0x41 /* RW */
+#define KHADAS_MCU_PASSWD_USER_2_REG		0x42 /* RW */
+#define KHADAS_MCU_PASSWD_USER_3_REG		0x43 /* RW */
+#define KHADAS_MCU_PASSWD_USER_4_REG		0x44 /* RW */
+#define KHADAS_MCU_PASSWD_USER_5_REG		0x45 /* RW */
+#define KHADAS_MCU_USER_DATA_0_REG		0x46 /* RW 56 bytes */
+#define KHADAS_MCU_PWR_OFF_CMD_REG		0x80 /* WO */
+#define KHADAS_MCU_PASSWD_START_REG		0x81 /* WO */
+#define KHADAS_MCU_CHECK_VEN_PASSWD_REG		0x82 /* WO */
+#define KHADAS_MCU_CHECK_USER_PASSWD_REG	0x83 /* WO */
+#define KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG	0x86 /* RO */
+#define KHADAS_MCU_WOL_INIT_START_REG		0x87 /* WO */
+#define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG	0x88 /* WO */
+
+enum {
+	KHADAS_BOARD_VIM1 = 0x1,
+	KHADAS_BOARD_VIM2,
+	KHADAS_BOARD_VIM3,
+	KHADAS_BOARD_EDGE = 0x11,
+	KHADAS_BOARD_EDGE_V,
+};
+
+#endif /* MFD_KHADAS_MCU_H */

+ 137 - 0
board/amlogic/vim3/vim3.c

@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2020 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <env_internal.h>
+#include <init.h>
+#include <net.h>
+#include <asm/io.h>
+#include <asm/arch/eth.h>
+#include <i2c.h>
+#include "khadas-mcu.h"
+
+/*
+ * The VIM3 on-board  MCU can mux the PCIe/USB3.0 shared differential
+ * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between
+ * an USB3.0 Type A connector and a M.2 Key M slot.
+ * The PHY driving these differential lines is shared between
+ * the USB3.0 controller and the PCIe Controller, thus only
+ * a single controller can use it.
+ */
+int meson_ft_board_setup(void *blob, struct bd_info *bd)
+{
+	struct udevice *bus, *dev;
+	int node, i2c_node, ret;
+	unsigned int i2c_addr;
+	u32 *val;
+
+	/* Find I2C device */
+	node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "khadas,mcu");
+	if (node < 0) {
+		printf("vim3: cannot find khadas,mcu node\n");
+		return 0;
+	}
+
+	/* Get addr */
+	val = (u32 *)fdt_getprop(gd->fdt_blob, node, "reg", NULL);
+	if (!val) {
+		printf("vim3: cannot find khadas,mcu node i2c addr\n");
+		return 0;
+	}
+	i2c_addr = fdt32_to_cpu(*val);
+
+	/* Get i2c device */
+	i2c_node = fdt_parent_offset(gd->fdt_blob, node);
+	if (node < 0) {
+		printf("vim3: cannot find khadas,mcu i2c node\n");
+		return 0;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_I2C, i2c_node, &bus);
+	if (ret < 0) {
+		printf("vim3: cannot find i2c bus (%d)\n", ret);
+		return 0;
+	}
+
+	ret = i2c_get_chip(bus, i2c_addr, 1, &dev);
+	if (ret < 0) {
+		printf("vim3: cannot find i2c chip (%d)\n", ret);
+		return 0;
+	}
+
+	/* Read USB_PCIE_SWITCH_REG */
+	ret = dm_i2c_reg_read(dev, KHADAS_MCU_USB_PCIE_SWITCH_REG);
+	if (ret < 0) {
+		printf("vim3: failed to read i2c reg (%d)\n", ret);
+		return 0;
+	}
+	debug("MCU_USB_PCIE_SWITCH_REG: %d\n", ret);
+
+	/*
+	 * If in PCIe mode, alter DT
+	 * 0:Enable USB3.0,Disable PCIE, 1:Disable USB3.0, Enable PCIE
+	 */
+	if (ret > 0) {
+		static char data[32] __aligned(4);
+		const void *ptmp;
+		int len;
+
+		/* Find USB node */
+		node = fdt_node_offset_by_compatible(blob, -1, "amlogic,meson-g12a-usb-ctrl");
+		if (node < 0) {
+			printf("vim3: cannot find amlogic,meson-g12a-usb-ctrl node\n");
+			return 0;
+		}
+
+		/* Update PHY names (mandatory to disable USB3.0) */
+		len = strlcpy(data, "usb2-phy0", 32) + 1;
+		len += strlcpy(&data[len], "usb2-phy1", 32 - len) + 1;
+		ret = fdt_setprop(blob, node, "phy-names", data, len);
+		if (ret < 0) {
+			printf("vim3: failed to update usb phy names property (%d)\n", ret);
+			return 0;
+		}
+
+		/* Update PHY list, by keeping the 2 first entries (optional) */
+		ptmp = fdt_getprop(blob, node, "phys", &len);
+		if (ptmp) {
+			memcpy(data, ptmp, min_t(unsigned int, 2 * sizeof(u32), len));
+
+			ret = fdt_setprop(blob, node, "phys", data,
+					  min_t(unsigned int, 2 * sizeof(u32), len));
+			if (ret < 0)
+				printf("vim3: failed to update usb phys property (%d)\n", ret);
+		} else
+			printf("vim3: cannot find usb node phys property\n");
+
+		/* Find PCIe node */
+		node = fdt_node_offset_by_compatible(blob, -1, "amlogic,g12a-pcie");
+		if (node < 0) {
+			printf("vim3: cannot find amlogic,g12a-pcie node\n");
+			return 0;
+		}
+
+		/* Enable PCIe */
+		len = strlcpy(data, "okay", 32);
+		ret = fdt_setprop(blob, node, "status", data, len);
+		if (ret < 0) {
+			printf("vim3: failed to enable pcie node (%d)\n", ret);
+			return 0;
+		}
+
+		printf("vim3: successfully enabled PCIe\n");
+	}
+
+	return 0;
+}
+
+int misc_init_r(void)
+{
+	meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0);
+
+	return 0;
+}

+ 0 - 4
board/amlogic/w400/MAINTAINERS

@@ -3,8 +3,4 @@ M:	Neil Armstrong <narmstrong@baylibre.com>
 S:	Maintained
 S:	Maintained
 L:	u-boot-amlogic@groups.io
 L:	u-boot-amlogic@groups.io
 F:	board/amlogic/w400/
 F:	board/amlogic/w400/
-F:	configs/khadas-vim3_defconfig
-F:	configs/khadas-vim3l_defconfig
 F:	doc/board/amlogic/w400.rst
 F:	doc/board/amlogic/w400.rst
-F:	doc/board/amlogic/khadas-vim3.rst
-F:	doc/board/amlogic/khadas-vim3l.rst

+ 1 - 1
configs/khadas-vim2_defconfig

@@ -41,6 +41,7 @@ CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
+CONFIG_USB_DWC3_MESON_GXL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR=y
@@ -56,7 +57,6 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3=y
 # CONFIG_USB_DWC3_GADGET is not set
 # CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET=y

+ 4 - 1
configs/khadas-vim3_defconfig

@@ -1,5 +1,5 @@
 CONFIG_ARM=y
 CONFIG_ARM=y
-CONFIG_SYS_BOARD="w400"
+CONFIG_SYS_BOARD="vim3"
 CONFIG_ARCH_MESON=y
 CONFIG_ARCH_MESON=y
 CONFIG_SYS_TEXT_BASE=0x01000000
 CONFIG_SYS_TEXT_BASE=0x01000000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_NR_DRAM_BANKS=1
@@ -17,6 +17,7 @@ CONFIG_MISC_INIT_R=y
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
 # CONFIG_CMD_LOADS is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SF_TEST=y
@@ -28,6 +29,8 @@ CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MESON=y
 CONFIG_DM_MMC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_MTD=y

+ 4 - 1
configs/khadas-vim3l_defconfig

@@ -1,5 +1,5 @@
 CONFIG_ARM=y
 CONFIG_ARM=y
-CONFIG_SYS_BOARD="w400"
+CONFIG_SYS_BOARD="vim3"
 CONFIG_ARCH_MESON=y
 CONFIG_ARCH_MESON=y
 CONFIG_SYS_TEXT_BASE=0x01000000
 CONFIG_SYS_TEXT_BASE=0x01000000
 CONFIG_NR_DRAM_BANKS=1
 CONFIG_NR_DRAM_BANKS=1
@@ -17,6 +17,7 @@ CONFIG_MISC_INIT_R=y
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_IMI is not set
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
 # CONFIG_CMD_LOADS is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SF_TEST=y
@@ -28,6 +29,8 @@ CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_OF_CONTROL=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MESON=y
 CONFIG_DM_MMC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_MTD=y

+ 1 - 1
configs/khadas-vim_defconfig

@@ -37,6 +37,7 @@ CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
+CONFIG_USB_DWC3_MESON_GXL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR=y
@@ -49,7 +50,6 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3=y
 # CONFIG_USB_DWC3_GADGET is not set
 # CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET=y

+ 1 - 1
configs/libretech-ac_defconfig

@@ -49,6 +49,7 @@ CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
+CONFIG_USB_DWC3_MESON_GXL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_POWER_DOMAIN=y
@@ -66,7 +67,6 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3=y
 # CONFIG_USB_DWC3_GADGET is not set
 # CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_KEYBOARD=y

+ 1 - 1
configs/libretech-cc_defconfig

@@ -36,6 +36,7 @@ CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
+CONFIG_USB_DWC3_MESON_GXL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_POWER_DOMAIN=y
@@ -50,7 +51,6 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3=y
 # CONFIG_USB_DWC3_GADGET is not set
 # CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET=y

+ 1 - 1
configs/libretech-s905d-pc_defconfig

@@ -44,6 +44,7 @@ CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
+CONFIG_USB_DWC3_MESON_GXL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_POWER_DOMAIN=y
@@ -61,7 +62,6 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3=y
 # CONFIG_USB_DWC3_GADGET is not set
 # CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_KEYBOARD=y

+ 1 - 1
configs/libretech-s912-pc_defconfig

@@ -43,6 +43,7 @@ CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
+CONFIG_USB_DWC3_MESON_GXL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_POWER_DOMAIN=y
@@ -60,7 +61,6 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3=y
 # CONFIG_USB_DWC3_GADGET is not set
 # CONFIG_USB_DWC3_GADGET is not set
 CONFIG_USB_KEYBOARD=y
 CONFIG_USB_KEYBOARD=y

+ 1 - 1
configs/p212_defconfig

@@ -34,6 +34,7 @@ CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_PHY=y
 CONFIG_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_MESON_GXL_USB_PHY=y
+CONFIG_USB_DWC3_MESON_GXL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_PINCTRL_MESON_GXL=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR=y
@@ -46,6 +47,5 @@ CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DM_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DWC3_OF_SIMPLE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_OF_LIBFDT_OVERLAY=y

+ 15 - 0
configs/s400_defconfig

@@ -18,6 +18,8 @@ CONFIG_MISC_INIT_R=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
 CONFIG_OF_CONTROL=y
@@ -28,6 +30,7 @@ CONFIG_MMC_MESON_GX=y
 CONFIG_PHY_REALTEK=y
 CONFIG_PHY_REALTEK=y
 CONFIG_DM_ETH=y
 CONFIG_DM_ETH=y
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_ETH_DESIGNWARE=y
+CONFIG_MESON_GXL_USB_PHY=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL=y
 CONFIG_PINCTRL_MESON_AXG=y
 CONFIG_PINCTRL_MESON_AXG=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR=y
@@ -36,4 +39,16 @@ CONFIG_DM_RESET=y
 CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_DEBUG_UART_SKIP_INIT=y
 CONFIG_MESON_SERIAL=y
 CONFIG_MESON_SERIAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_MESON_GXL=y
+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
 CONFIG_OF_LIBFDT_OVERLAY=y

+ 27 - 0
doc/board/amlogic/khadas-vim3.rst

@@ -18,6 +18,33 @@ Technology Co., Ltd. with the following specifications:
 
 
 Schematics are available on the manufacturer website.
 Schematics are available on the manufacturer website.
 
 
+PCIe Setup
+----------
+The VIM3 on-board  MCU can mux the PCIe/USB3.0 shared differential
+lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between
+an USB3.0 Type A connector and a M.2 Key M slot.
+The PHY driving these differential lines is shared between
+the USB3.0 controller and the PCIe Controller, thus only
+a single controller can use it.
+
+To setup for PCIe, run the following commands from U-Boot:
+
+.. code-block:: none
+
+    i2c dev i2c@5000
+    i2c mw 0x18 0x33 1
+
+Then power-cycle the board.
+
+To set back to USB3.0, run the following commands from U-Boot:
+
+.. code-block:: none
+
+    i2c dev i2c@5000
+    i2c mw 0x18 0x33 0
+
+Then power-cycle the board.
+
 U-Boot compilation
 U-Boot compilation
 ------------------
 ------------------
 
 

+ 27 - 0
doc/board/amlogic/khadas-vim3l.rst

@@ -18,6 +18,33 @@ Technology Co., Ltd. with the following specifications:
 
 
 Schematics are available on the manufacturer website.
 Schematics are available on the manufacturer website.
 
 
+PCIe Setup
+----------
+The VIM3 on-board  MCU can mux the PCIe/USB3.0 shared differential
+lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between
+an USB3.0 Type A connector and a M.2 Key M slot.
+The PHY driving these differential lines is shared between
+the USB3.0 controller and the PCIe Controller, thus only
+a single controller can use it.
+
+To setup for PCIe, run the following commands from U-Boot:
+
+.. code-block:: none
+
+    i2c dev i2c@5000
+    i2c mw 0x18 0x33 1
+
+Then power-cycle the board.
+
+To set back to USB3.0, run the following commands from U-Boot:
+
+.. code-block:: none
+
+    i2c dev i2c@5000
+    i2c mw 0x18 0x33 0
+
+Then power-cycle the board.
+
 U-Boot compilation
 U-Boot compilation
 ------------------
 ------------------
 
 

+ 1 - 1
drivers/phy/Kconfig

@@ -177,7 +177,7 @@ config MESON_GXBB_USB_PHY
 
 
 config MESON_GXL_USB_PHY
 config MESON_GXL_USB_PHY
 	bool "Amlogic Meson GXL USB PHYs"
 	bool "Amlogic Meson GXL USB PHYs"
-	depends on PHY && ARCH_MESON && (MESON_GXL || MESON_GXM)
+	depends on PHY && ARCH_MESON && (MESON_GXL || MESON_GXM || MESON_AXG)
 	imply REGMAP
 	imply REGMAP
 	help
 	help
 	  This is the generic phy driver for the Amlogic Meson GXL
 	  This is the generic phy driver for the Amlogic Meson GXL

+ 1 - 1
drivers/phy/Makefile

@@ -19,7 +19,7 @@ obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o
 obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o
 obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o
 obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o
 obj-$(CONFIG_MESON_GXBB_USB_PHY) += meson-gxbb-usb2.o
-obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
+obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o
 obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
 obj-$(CONFIG_MESON_G12A_USB_PHY) += meson-g12a-usb2.o meson-g12a-usb3-pcie.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o

+ 0 - 219
drivers/phy/meson-gxl-usb3.c

@@ -1,219 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Meson GXL USB3 PHY driver
- *
- * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
- * Copyright (C) 2018 BayLibre, SAS
- * Author: Neil Armstrong <narmstron@baylibre.com>
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <asm/io.h>
-#include <bitfield.h>
-#include <dm.h>
-#include <errno.h>
-#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>
-#include <linux/bitfield.h>
-
-#define USB_R0							0x00
-	#define USB_R0_P30_FSEL_MASK				GENMASK(5, 0)
-	#define USB_R0_P30_PHY_RESET				BIT(6)
-	#define USB_R0_P30_TEST_POWERDOWN_HSP			BIT(7)
-	#define USB_R0_P30_TEST_POWERDOWN_SSP			BIT(8)
-	#define USB_R0_P30_ACJT_LEVEL_MASK			GENMASK(13, 9)
-	#define USB_R0_P30_TX_BOOST_LEVEL_MASK			GENMASK(16, 14)
-	#define USB_R0_P30_LANE0_TX2RX_LOOPBACK			BIT(17)
-	#define USB_R0_P30_LANE0_EXT_PCLK_REQ			BIT(18)
-	#define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK		GENMASK(28, 19)
-	#define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK		GENMASK(30, 29)
-	#define USB_R0_U2D_ACT					BIT(31)
-
-#define USB_R1							0x04
-	#define USB_R1_U3H_BIGENDIAN_GS				BIT(0)
-	#define USB_R1_U3H_PME_ENABLE				BIT(1)
-	#define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK		GENMASK(6, 2)
-	#define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK		GENMASK(11, 7)
-	#define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK		GENMASK(15, 12)
-	#define USB_R1_U3H_HOST_U3_PORT_DISABLE			BIT(16)
-	#define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT	BIT(17)
-	#define USB_R1_U3H_HOST_MSI_ENABLE			BIT(18)
-	#define USB_R1_U3H_FLADJ_30MHZ_REG_MASK			GENMASK(24, 19)
-	#define USB_R1_P30_PCS_TX_SWING_FULL_MASK		GENMASK(31, 25)
-
-#define USB_R2							0x08
-	#define USB_R2_P30_CR_DATA_IN_MASK			GENMASK(15, 0)
-	#define USB_R2_P30_CR_READ				BIT(16)
-	#define USB_R2_P30_CR_WRITE				BIT(17)
-	#define USB_R2_P30_CR_CAP_ADDR				BIT(18)
-	#define USB_R2_P30_CR_CAP_DATA				BIT(19)
-	#define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK		GENMASK(25, 20)
-	#define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK		GENMASK(31, 26)
-
-#define USB_R3							0x0c
-	#define USB_R3_P30_SSC_ENABLE				BIT(0)
-	#define USB_R3_P30_SSC_RANGE_MASK			GENMASK(3, 1)
-	#define USB_R3_P30_SSC_REF_CLK_SEL_MASK			GENMASK(12, 4)
-	#define USB_R3_P30_REF_SSP_EN				BIT(13)
-	#define USB_R3_P30_LOS_BIAS_MASK			GENMASK(18, 16)
-	#define USB_R3_P30_LOS_LEVEL_MASK			GENMASK(23, 19)
-	#define USB_R3_P30_MPLL_MULTIPLIER_MASK			GENMASK(30, 24)
-
-#define USB_R4							0x10
-	#define USB_R4_P21_PORT_RESET_0				BIT(0)
-	#define USB_R4_P21_SLEEP_M0				BIT(1)
-	#define USB_R4_MEM_PD_MASK				GENMASK(3, 2)
-	#define USB_R4_P21_ONLY					BIT(4)
-
-#define USB_R5							0x14
-	#define USB_R5_ID_DIG_SYNC				BIT(0)
-	#define USB_R5_ID_DIG_REG				BIT(1)
-	#define USB_R5_ID_DIG_CFG_MASK				GENMASK(3, 2)
-	#define USB_R5_ID_DIG_EN_0				BIT(4)
-	#define USB_R5_ID_DIG_EN_1				BIT(5)
-	#define USB_R5_ID_DIG_CURR				BIT(6)
-	#define USB_R5_ID_DIG_IRQ				BIT(7)
-	#define USB_R5_ID_DIG_TH_MASK				GENMASK(15, 8)
-	#define USB_R5_ID_DIG_CNT_MASK				GENMASK(23, 16)
-
-/* read-only register */
-#define USB_R6							0x18
-	#define USB_R6_P30_CR_DATA_OUT_MASK			GENMASK(15, 0)
-	#define USB_R6_P30_CR_ACK				BIT(16)
-
-struct phy_meson_gxl_usb3_priv {
-	struct regmap		*regmap;
-#if CONFIG_IS_ENABLED(CLK)
-	struct clk		clk;
-#endif
-};
-
-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;
-
-	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);
-		break;
-
-	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)
-{
-	struct udevice *dev = phy->dev;
-	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
-	uint val;
-
-	regmap_read(priv->regmap, USB_R5, &val);
-	val |= USB_R5_ID_DIG_EN_0;
-	val |= USB_R5_ID_DIG_EN_1;
-	val &= ~USB_R5_ID_DIG_TH_MASK;
-	val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff);
-	regmap_write(priv->regmap, USB_R5, val);
-
-	phy_meson_gxl_usb3_set_mode(phy, USB_DR_MODE_HOST);
-
-	return 0;
-}
-
-static int phy_meson_gxl_usb3_power_off(struct phy *phy)
-{
-	struct udevice *dev = phy->dev;
-	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
-	uint val;
-
-	regmap_read(priv->regmap, USB_R5, &val);
-	val &= ~USB_R5_ID_DIG_EN_0;
-	val &= ~USB_R5_ID_DIG_EN_1;
-	regmap_write(priv->regmap, USB_R5, val);
-
-	return 0;
-}
-
-static int phy_meson_gxl_usb3_init(struct phy *phy)
-{
-	struct udevice *dev = phy->dev;
-	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
-	uint val;
-
-	regmap_read(priv->regmap, USB_R1, &val);
-	val &= ~USB_R1_U3H_FLADJ_30MHZ_REG_MASK;
-	val |= FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20);
-	regmap_write(priv->regmap, USB_R1, val);
-
-	return 0;
-}
-
-struct phy_ops meson_gxl_usb3_phy_ops = {
-	.init = phy_meson_gxl_usb3_init,
-	.power_on = phy_meson_gxl_usb3_power_on,
-	.power_off = phy_meson_gxl_usb3_power_off,
-};
-
-int meson_gxl_usb3_phy_probe(struct udevice *dev)
-{
-	struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev);
-	int ret;
-
-	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
-	if (ret)
-		return ret;
-	
-#if CONFIG_IS_ENABLED(CLK)
-	ret = clk_get_by_index(dev, 0, &priv->clk);
-	if (ret < 0)
-		return ret;
-
-	ret = clk_enable(&priv->clk);
-	if (ret && ret != -ENOSYS && ret != -ENOTSUPP) {
-		pr_err("failed to enable PHY clock\n");
-		clk_free(&priv->clk);
-		return ret;
-	}
-#endif
-
-	return 0;
-}
-
-static const struct udevice_id meson_gxl_usb3_phy_ids[] = {
-	{ .compatible = "amlogic,meson-gxl-usb3-phy" },
-	{ }
-};
-
-U_BOOT_DRIVER(meson_gxl_usb3_phy) = {
-	.name = "meson_gxl_usb3_phy",
-	.id = UCLASS_PHY,
-	.of_match = meson_gxl_usb3_phy_ids,
-	.probe = meson_gxl_usb3_phy_probe,
-	.ops = &meson_gxl_usb3_phy_ops,
-	.priv_auto_alloc_size = sizeof(struct phy_meson_gxl_usb3_priv),
-};

+ 4 - 1
drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c

@@ -165,7 +165,10 @@ const struct pinctrl_ops meson_axg_pinctrl_ops = {
 static int meson_axg_gpio_request(struct udevice *dev,
 static int meson_axg_gpio_request(struct udevice *dev,
 				  unsigned int offset, const char *label)
 				  unsigned int offset, const char *label)
 {
 {
-	return meson_axg_pmx_update_function(dev->parent, offset, 0);
+	struct meson_pinctrl *priv = dev_get_priv(dev->parent);
+
+	return meson_axg_pmx_update_function(dev->parent,
+					     offset + priv->data->pin_base, 0);
 }
 }
 
 
 static const struct dm_gpio_ops meson_axg_gpio_ops = {
 static const struct dm_gpio_ops meson_axg_gpio_ops = {

+ 1 - 0
drivers/pinctrl/meson/pinctrl-meson-axg.c

@@ -298,6 +298,7 @@ static struct meson_pmx_group meson_axg_periphs_groups[] = {
 	GPIO_GROUP(GPIOA_15, EE_OFF),
 	GPIO_GROUP(GPIOA_15, EE_OFF),
 	GPIO_GROUP(GPIOA_16, EE_OFF),
 	GPIO_GROUP(GPIOA_16, EE_OFF),
 	GPIO_GROUP(GPIOA_17, EE_OFF),
 	GPIO_GROUP(GPIOA_17, EE_OFF),
+	GPIO_GROUP(GPIOA_18, EE_OFF),
 	GPIO_GROUP(GPIOA_19, EE_OFF),
 	GPIO_GROUP(GPIOA_19, EE_OFF),
 	GPIO_GROUP(GPIOA_20, EE_OFF),
 	GPIO_GROUP(GPIOA_20, EE_OFF),
 
 

+ 7 - 0
drivers/pwm/Kconfig

@@ -23,6 +23,13 @@ config PWM_IMX
 	help
 	help
 	  This PWM is found i.MX27 and later i.MX SoCs.
 	  This PWM is found i.MX27 and later i.MX SoCs.
 
 
+config PWM_MESON
+	bool "Enable support for Amlogic Meson SoCs PWM"
+	depends on DM_PWM
+	help
+	  This PWM is found on Amlogic Meson SoCs. It supports a
+	  programmable period and duty cycle for 2 independant channels.
+
 config PWM_MTK
 config PWM_MTK
 	bool "Enable support for MediaTek PWM"
 	bool "Enable support for MediaTek PWM"
 	depends on DM_PWM
 	depends on DM_PWM

+ 1 - 0
drivers/pwm/Makefile

@@ -12,6 +12,7 @@ obj-$(CONFIG_DM_PWM)		+= pwm-uclass.o
 
 
 obj-$(CONFIG_PWM_EXYNOS)	+= exynos_pwm.o
 obj-$(CONFIG_PWM_EXYNOS)	+= exynos_pwm.o
 obj-$(CONFIG_PWM_IMX)		+= pwm-imx.o pwm-imx-util.o
 obj-$(CONFIG_PWM_IMX)		+= pwm-imx.o pwm-imx-util.o
+obj-$(CONFIG_PWM_MESON)		+= pwm-meson.o
 obj-$(CONFIG_PWM_MTK)		+= pwm-mtk.o
 obj-$(CONFIG_PWM_MTK)		+= pwm-mtk.o
 obj-$(CONFIG_PWM_ROCKCHIP)	+= rk_pwm.o
 obj-$(CONFIG_PWM_ROCKCHIP)	+= rk_pwm.o
 obj-$(CONFIG_PWM_SANDBOX)	+= sandbox_pwm.o
 obj-$(CONFIG_PWM_SANDBOX)	+= sandbox_pwm.o

+ 528 - 0
drivers/pwm/pwm-meson.c

@@ -0,0 +1,528 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2020 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Amlogic, Inc.
+ *
+ * This PWM is only a set of Gates, Dividers and Counters:
+ * PWM output is achieved by calculating a clock that permits calculating
+ * two periods (low and high). The counter then has to be set to switch after
+ * N cycles for the first half period.
+ * The hardware has no "polarity" setting. This driver reverses the period
+ * cycles (the low length is inverted with the high length) for
+ * PWM_POLARITY_INVERSED.
+ * Setting the polarity will disable and re-enable the PWM output.
+ * Disabling the PWM stops the output immediately (without waiting for the
+ * current period to complete first).
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <div64.h>
+#include <dm.h>
+#include <pwm.h>
+#include <regmap.h>
+#include <linux/io.h>
+#include <linux/math64.h>
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+
+#define NSEC_PER_SEC 1000000000L
+
+#define REG_PWM_A		0x0
+#define REG_PWM_B		0x4
+#define PWM_LOW_MASK		GENMASK(15, 0)
+#define PWM_HIGH_MASK		GENMASK(31, 16)
+
+#define REG_MISC_AB		0x8
+#define MISC_B_CLK_EN		BIT(23)
+#define MISC_A_CLK_EN		BIT(15)
+#define MISC_CLK_DIV_MASK	0x7f
+#define MISC_B_CLK_DIV_SHIFT	16
+#define MISC_A_CLK_DIV_SHIFT	8
+#define MISC_B_CLK_SEL_SHIFT	6
+#define MISC_A_CLK_SEL_SHIFT	4
+#define MISC_CLK_SEL_MASK	0x3
+#define MISC_B_EN		BIT(1)
+#define MISC_A_EN		BIT(0)
+
+#define MESON_NUM_PWMS		2
+
+static struct meson_pwm_channel_data {
+	u8		reg_offset;
+	u8		clk_sel_shift;
+	u8		clk_div_shift;
+	u32		clk_en_mask;
+	u32		pwm_en_mask;
+} meson_pwm_per_channel_data[MESON_NUM_PWMS] = {
+	{
+		.reg_offset	= REG_PWM_A,
+		.clk_sel_shift	= MISC_A_CLK_SEL_SHIFT,
+		.clk_div_shift	= MISC_A_CLK_DIV_SHIFT,
+		.clk_en_mask	= MISC_A_CLK_EN,
+		.pwm_en_mask	= MISC_A_EN,
+	},
+	{
+		.reg_offset	= REG_PWM_B,
+		.clk_sel_shift	= MISC_B_CLK_SEL_SHIFT,
+		.clk_div_shift	= MISC_B_CLK_DIV_SHIFT,
+		.clk_en_mask	= MISC_B_CLK_EN,
+		.pwm_en_mask	= MISC_B_EN,
+	}
+};
+
+struct meson_pwm_channel {
+	unsigned int hi;
+	unsigned int lo;
+	u8 pre_div;
+	uint period_ns;
+	uint duty_ns;
+	bool configured;
+	bool enabled;
+	bool polarity;
+	struct clk clk;
+};
+
+struct meson_pwm_data {
+	const long *parent_ids;
+	unsigned int num_parents;
+};
+
+struct meson_pwm {
+	const struct meson_pwm_data *data;
+	struct meson_pwm_channel channels[MESON_NUM_PWMS];
+	void __iomem *base;
+};
+
+static int meson_pwm_set_enable(struct udevice *dev, uint channel, bool enable);
+
+static int meson_pwm_set_config(struct udevice *dev, uint channeln,
+				 uint period_ns, uint duty_ns)
+{
+	struct meson_pwm *priv = dev_get_priv(dev);
+	struct meson_pwm_channel *channel;
+	struct meson_pwm_channel_data *channel_data;
+	unsigned int duty, period, pre_div, cnt, duty_cnt;
+	unsigned long fin_freq;
+
+	if (channeln >= MESON_NUM_PWMS)
+		return -ENODEV;
+
+	channel = &priv->channels[channeln];
+	channel_data = &meson_pwm_per_channel_data[channeln];
+
+	period = period_ns;
+	if (channel->polarity)
+		duty = period_ns - duty_ns;
+	else
+		duty = duty_ns;
+
+	debug("%s%d: polarity %s duty %d period %d\n", __func__, channeln,
+	      channel->polarity ? "true" : "false", duty, period);
+
+	fin_freq = clk_get_rate(&channel->clk);
+	if (fin_freq == 0) {
+		printf("%s%d: invalid source clock frequency\n", __func__, channeln);
+		return -EINVAL;
+	}
+
+	debug("%s%d: fin_freq: %lu Hz\n", __func__, channeln, fin_freq);
+
+	pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xffffLL);
+	if (pre_div > MISC_CLK_DIV_MASK) {
+		printf("%s%d: unable to get period pre_div\n", __func__, channeln);
+		return -EINVAL;
+	}
+
+	cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1));
+	if (cnt > 0xffff) {
+		printf("%s%d: unable to get period cnt\n", __func__, channeln);
+		return -EINVAL;
+	}
+
+	debug("%s%d: period=%u pre_div=%u cnt=%u\n", __func__, channeln, period, pre_div, cnt);
+
+	if (duty == period) {
+		channel->pre_div = pre_div;
+		channel->hi = cnt;
+		channel->lo = 0;
+	} else if (duty == 0) {
+		channel->pre_div = pre_div;
+		channel->hi = 0;
+		channel->lo = cnt;
+	} else {
+		/* Then check is we can have the duty with the same pre_div */
+		duty_cnt = div64_u64(fin_freq * (u64)duty, NSEC_PER_SEC * (pre_div + 1));
+		if (duty_cnt > 0xffff) {
+			printf("%s%d: unable to get duty cycle\n", __func__, channeln);
+			return -EINVAL;
+		}
+
+		debug("%s%d: duty=%u pre_div=%u duty_cnt=%u\n",
+		      __func__, channeln, duty, pre_div, duty_cnt);
+
+		channel->pre_div = pre_div;
+		channel->hi = duty_cnt;
+		channel->lo = cnt - duty_cnt;
+	}
+
+	channel->period_ns = period_ns;
+	channel->duty_ns = duty_ns;
+	channel->configured = true;
+
+	if (channel->enabled) {
+		meson_pwm_set_enable(dev, channeln, false);
+		meson_pwm_set_enable(dev, channeln, true);
+	}
+
+	return 0;
+}
+
+static int meson_pwm_set_enable(struct udevice *dev, uint channeln, bool enable)
+{
+	struct meson_pwm *priv = dev_get_priv(dev);
+	struct meson_pwm_channel *channel;
+	struct meson_pwm_channel_data *channel_data;
+	u32 value;
+
+	if (channeln >= MESON_NUM_PWMS)
+		return -ENODEV;
+
+	channel = &priv->channels[channeln];
+	channel_data = &meson_pwm_per_channel_data[channeln];
+
+	if (!channel->configured)
+		return -EINVAL;
+
+	if (enable) {
+		if (channel->enabled)
+			return 0;
+
+		value = readl(priv->base + REG_MISC_AB);
+		value &= ~(MISC_CLK_DIV_MASK << channel_data->clk_div_shift);
+		value |= channel->pre_div << channel_data->clk_div_shift;
+		value |= channel_data->clk_en_mask;
+		writel(value, priv->base + REG_MISC_AB);
+
+		value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) |
+			FIELD_PREP(PWM_LOW_MASK, channel->lo);
+		writel(value, priv->base + channel_data->reg_offset);
+
+		value = readl(priv->base + REG_MISC_AB);
+		value |= channel_data->pwm_en_mask;
+		writel(value, priv->base + REG_MISC_AB);
+
+		debug("%s%d: enabled\n", __func__, channeln);
+		channel->enabled = true;
+	} else {
+		if (!channel->enabled)
+			return 0;
+
+		value = readl(priv->base + REG_MISC_AB);
+		value &= channel_data->pwm_en_mask;
+		writel(value, priv->base + REG_MISC_AB);
+
+		debug("%s%d: disabled\n", __func__, channeln);
+		channel->enabled = false;
+	}
+
+	return 0;
+}
+
+static int meson_pwm_set_invert(struct udevice *dev, uint channeln, bool polarity)
+{
+	struct meson_pwm *priv = dev_get_priv(dev);
+	struct meson_pwm_channel *channel;
+
+	if (channeln >= MESON_NUM_PWMS)
+		return -ENODEV;
+
+	debug("%s%d: set invert %s\n", __func__, channeln, polarity ? "true" : "false");
+
+	channel = &priv->channels[channeln];
+
+	channel->polarity = polarity;
+
+	if (!channel->configured)
+		return 0;
+
+	return meson_pwm_set_config(dev, channeln, channel->period_ns, channel->duty_ns);
+}
+
+static int meson_pwm_ofdata_to_platdata(struct udevice *dev)
+{
+	struct meson_pwm *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+static int meson_pwm_probe(struct udevice *dev)
+{
+	struct meson_pwm *priv = dev_get_priv(dev);
+	struct meson_pwm_data *data;
+	unsigned int i, p;
+	char name[255];
+	int err;
+	u32 reg;
+
+	data = (struct meson_pwm_data *)dev_get_driver_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	for (i = 0; i < MESON_NUM_PWMS; i++) {
+		struct meson_pwm_channel *channel = &priv->channels[i];
+		struct meson_pwm_channel_data *channel_data = &meson_pwm_per_channel_data[i];
+
+		snprintf(name, sizeof(name), "clkin%u", i);
+
+		err = clk_get_by_name(dev, name, &channel->clk);
+		/* If clock is not specified, use the already set clock */
+		if (err == -ENODATA) {
+			struct udevice *cdev;
+			struct uclass *uc;
+
+			/* Get parent from mux */
+			p = (readl(priv->base + REG_MISC_AB) >> channel_data->clk_sel_shift) &
+				MISC_CLK_SEL_MASK;
+
+			if (p >= data->num_parents) {
+				printf("%s%d: hw parent is invalid\n", __func__, i);
+				return -EINVAL;
+			}
+
+			if (data->parent_ids[p] == -1) {
+				/* Search for xtal clk */
+				const char *str;
+
+				err = uclass_get(UCLASS_CLK, &uc);
+				if (err)
+					return err;
+
+				uclass_foreach_dev(cdev, uc) {
+					if (strcmp(cdev->driver->name, "fixed_rate_clock"))
+						continue;
+
+					str = ofnode_read_string(cdev->node, "clock-output-names");
+					if (!str)
+						continue;
+
+					if (!strcmp(str, "xtal")) {
+						err = uclass_get_device_by_ofnode(UCLASS_CLK,
+										  cdev->node,
+										  &cdev);
+						if (err) {
+							printf("%s%d: Failed to get xtal clk\n", __func__, i);
+							return err;
+						}
+
+						break;
+					}
+				}
+
+				if (!cdev) {
+					printf("%s%d: Failed to find xtal clk device\n", __func__, i);
+					return -EINVAL;
+				}
+
+				channel->clk.dev = cdev;
+				channel->clk.id = 0;
+				channel->clk.data = 0;
+			} else {
+				/* Look for parent clock */
+				err = uclass_get(UCLASS_CLK, &uc);
+				if (err)
+					return err;
+
+				uclass_foreach_dev(cdev, uc) {
+					if (strstr(cdev->driver->name, "meson_clk"))
+						break;
+				}
+
+				if (!cdev) {
+					printf("%s%d: Failed to find clk device\n", __func__, i);
+					return -EINVAL;
+				}
+
+				err = uclass_get_device_by_ofnode(UCLASS_CLK, cdev->node, &cdev);
+				if (err) {
+					printf("%s%d: Failed to get clk controller\n", __func__, i);
+					return err;
+				}
+
+				channel->clk.dev = cdev;
+				channel->clk.id = data->parent_ids[p];
+				channel->clk.data = 0;
+			}
+
+			/* We have our source clock, do not alter HW clock mux */
+			continue;
+		} else
+			return err;
+
+		/* Get id in list */
+		for (p = 0 ; p < data->num_parents ; ++p) {
+			if (!strcmp(channel->clk.dev->driver->name, "fixed_rate_clock")) {
+				if (data->parent_ids[p] == -1)
+					break;
+			} else {
+				if (data->parent_ids[p] == channel->clk.id)
+					break;
+			}
+		}
+
+		/* Invalid clock ID */
+		if (p == data->num_parents) {
+			printf("%s%d: source clock is invalid\n", __func__, i);
+			return -EINVAL;
+		}
+
+		/* switch parent in mux */
+		reg = readl(priv->base + REG_MISC_AB);
+
+		debug("%s%d: switching parent %d to %d\n", __func__, i,
+		      (reg >> channel_data->clk_sel_shift) & MISC_CLK_SEL_MASK, p);
+
+		reg &= MISC_CLK_SEL_MASK << channel_data->clk_sel_shift;
+		reg |= (p & MISC_CLK_SEL_MASK) << channel_data->clk_sel_shift;
+		writel(reg, priv->base + REG_MISC_AB);
+	}
+
+	return 0;
+}
+
+static const struct pwm_ops meson_pwm_ops = {
+	.set_config	= meson_pwm_set_config,
+	.set_enable	= meson_pwm_set_enable,
+	.set_invert	= meson_pwm_set_invert,
+};
+
+#define XTAL 			-1
+
+/* Local clock ids aliases to avoid define conflicts */
+#define GXBB_CLKID_HDMI_PLL		2
+#define GXBB_CLKID_FCLK_DIV3		5
+#define GXBB_CLKID_FCLK_DIV4		6
+#define GXBB_CLKID_CLK81		12
+
+static const long pwm_gxbb_parent_ids[] = {
+	XTAL, GXBB_CLKID_HDMI_PLL, GXBB_CLKID_FCLK_DIV4, GXBB_CLKID_FCLK_DIV3
+};
+
+static const struct meson_pwm_data pwm_gxbb_data = {
+	.parent_ids = pwm_gxbb_parent_ids,
+	.num_parents = ARRAY_SIZE(pwm_gxbb_parent_ids),
+};
+
+/*
+ * Only the 2 first inputs of the GXBB AO PWMs are valid
+ * The last 2 are grounded
+ */
+static const long pwm_gxbb_ao_parent_ids[] = {
+	XTAL, GXBB_CLKID_CLK81
+};
+
+static const struct meson_pwm_data pwm_gxbb_ao_data = {
+	.parent_ids = pwm_gxbb_ao_parent_ids,
+	.num_parents = ARRAY_SIZE(pwm_gxbb_ao_parent_ids),
+};
+
+/* Local clock ids aliases to avoid define conflicts */
+#define AXG_CLKID_FCLK_DIV3		3
+#define AXG_CLKID_FCLK_DIV4		4
+#define AXG_CLKID_FCLK_DIV5		5
+#define AXG_CLKID_CLK81			10
+
+static const long pwm_axg_ee_parent_ids[] = {
+	XTAL, AXG_CLKID_FCLK_DIV5, AXG_CLKID_FCLK_DIV4, AXG_CLKID_FCLK_DIV3
+};
+
+static const struct meson_pwm_data pwm_axg_ee_data = {
+	.parent_ids = pwm_axg_ee_parent_ids,
+	.num_parents = ARRAY_SIZE(pwm_axg_ee_parent_ids),
+};
+
+static const long pwm_axg_ao_parent_ids[] = {
+	AXG_CLKID_CLK81, XTAL, AXG_CLKID_FCLK_DIV4, AXG_CLKID_FCLK_DIV5
+};
+
+static const struct meson_pwm_data pwm_axg_ao_data = {
+	.parent_ids = pwm_axg_ao_parent_ids,
+	.num_parents = ARRAY_SIZE(pwm_axg_ao_parent_ids),
+};
+
+/* Local clock ids aliases to avoid define conflicts */
+#define G12A_CLKID_FCLK_DIV3		3
+#define G12A_CLKID_FCLK_DIV4		4
+#define G12A_CLKID_FCLK_DIV5		5
+#define G12A_CLKID_CLK81		10
+#define G12A_CLKID_HDMI_PLL		128
+
+static const long pwm_g12a_ao_ab_parent_ids[] = {
+	XTAL, G12A_CLKID_CLK81, G12A_CLKID_FCLK_DIV4, G12A_CLKID_FCLK_DIV5
+};
+
+static const struct meson_pwm_data pwm_g12a_ao_ab_data = {
+	.parent_ids = pwm_g12a_ao_ab_parent_ids,
+	.num_parents = ARRAY_SIZE(pwm_g12a_ao_ab_parent_ids),
+};
+
+static const long pwm_g12a_ao_cd_parent_ids[] = {
+	XTAL, G12A_CLKID_CLK81,
+};
+
+static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
+	.parent_ids = pwm_g12a_ao_cd_parent_ids,
+	.num_parents = ARRAY_SIZE(pwm_g12a_ao_cd_parent_ids),
+};
+
+static const long pwm_g12a_ee_parent_ids[] = {
+	XTAL, G12A_CLKID_HDMI_PLL, G12A_CLKID_FCLK_DIV4, G12A_CLKID_FCLK_DIV3
+};
+
+static const struct meson_pwm_data pwm_g12a_ee_data = {
+	.parent_ids = pwm_g12a_ee_parent_ids,
+	.num_parents = ARRAY_SIZE(pwm_g12a_ee_parent_ids),
+};
+
+static const struct udevice_id meson_pwm_ids[] = {
+	{
+		.compatible = "amlogic,meson-gxbb-pwm",
+		.data = (ulong)&pwm_gxbb_data
+	},
+	{
+		.compatible = "amlogic,meson-gxbb-ao-pwm",
+		.data = (ulong)&pwm_gxbb_ao_data
+	},
+	{
+		.compatible = "amlogic,meson-axg-ee-pwm",
+		.data = (ulong)&pwm_axg_ee_data
+	},
+	{
+		.compatible = "amlogic,meson-axg-ao-pwm",
+		.data = (ulong)&pwm_axg_ao_data
+	},
+	{
+		.compatible = "amlogic,meson-g12a-ee-pwm",
+		.data = (ulong)&pwm_g12a_ee_data
+	},
+	{
+		.compatible = "amlogic,meson-g12a-ao-pwm-ab",
+		.data = (ulong)&pwm_g12a_ao_ab_data
+	},
+	{
+		.compatible = "amlogic,meson-g12a-ao-pwm-cd",
+		.data = (ulong)&pwm_g12a_ao_cd_data
+	},
+};
+
+U_BOOT_DRIVER(meson_pwm) = {
+	.name	= "meson_pwm",
+	.id	= UCLASS_PWM,
+	.of_match = meson_pwm_ids,
+	.ops	= &meson_pwm_ops,
+	.ofdata_to_platdata = meson_pwm_ofdata_to_platdata,
+	.probe	 = meson_pwm_probe,
+	.priv_auto_alloc_size	= sizeof(struct meson_pwm),
+};

+ 8 - 0
drivers/usb/dwc3/Kconfig

@@ -38,6 +38,14 @@ config USB_DWC3_MESON_G12A
 	  Select this for Amlogic Meson G12A Platforms.
 	  Select this for Amlogic Meson G12A Platforms.
 	  This wrapper supports Host and Peripheral operation modes.
 	  This wrapper supports Host and Peripheral operation modes.
 
 
+config USB_DWC3_MESON_GXL
+	bool "Amlogic Meson GXL USB wrapper"
+	depends on DM_USB && USB_DWC3 && ARCH_MESON
+	imply PHY
+	help
+	  Select this for Amlogic Meson GXL and GXM Platforms.
+	  This wrapper supports Host and Peripheral operation modes.
+
 config USB_DWC3_UNIPHIER
 config USB_DWC3_UNIPHIER
 	bool "DesignWare USB3 Host Support on UniPhier Platforms"
 	bool "DesignWare USB3 Host Support on UniPhier Platforms"
 	depends on ARCH_UNIPHIER && USB_XHCI_DWC3
 	depends on ARCH_UNIPHIER && USB_XHCI_DWC3

+ 1 - 0
drivers/usb/dwc3/Makefile

@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_DWC3_GADGET)		+= gadget.o ep0.o
 
 
 obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
 obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
 obj-$(CONFIG_USB_DWC3_MESON_G12A)	+= dwc3-meson-g12a.o
 obj-$(CONFIG_USB_DWC3_MESON_G12A)	+= dwc3-meson-g12a.o
+obj-$(CONFIG_USB_DWC3_MESON_GXL)	+= dwc3-meson-gxl.o
 obj-$(CONFIG_USB_DWC3_GENERIC)		+= dwc3-generic.o
 obj-$(CONFIG_USB_DWC3_GENERIC)		+= dwc3-generic.o
 obj-$(CONFIG_USB_DWC3_UNIPHIER)		+= dwc3-uniphier.o
 obj-$(CONFIG_USB_DWC3_UNIPHIER)		+= dwc3-uniphier.o
 obj-$(CONFIG_USB_DWC3_PHY_OMAP)		+= ti_usb_phy.o
 obj-$(CONFIG_USB_DWC3_PHY_OMAP)		+= ti_usb_phy.o

+ 425 - 0
drivers/usb/dwc3/dwc3-meson-gxl.c

@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Amlogic GXL DWC3 Glue layer
+ *
+ * Copyright (C) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#define DEBUG
+#include <common.h>
+#include <asm-generic/io.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dwc3-uboot.h>
+#include <generic-phy.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <malloc.h>
+#include <regmap.h>
+#include <usb.h>
+#include "core.h"
+#include "gadget.h"
+#include <reset.h>
+#include <clk.h>
+#include <power/regulator.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compat.h>
+#include <asm/arch/usb-gx.h>
+
+/* USB Glue Control Registers */
+
+#define USB_R0							0x00
+	#define USB_R0_P30_FSEL_MASK				GENMASK(5, 0)
+	#define USB_R0_P30_PHY_RESET				BIT(6)
+	#define USB_R0_P30_TEST_POWERDOWN_HSP			BIT(7)
+	#define USB_R0_P30_TEST_POWERDOWN_SSP			BIT(8)
+	#define USB_R0_P30_ACJT_LEVEL_MASK			GENMASK(13, 9)
+	#define USB_R0_P30_TX_BOOST_LEVEL_MASK			GENMASK(16, 14)
+	#define USB_R0_P30_LANE0_TX2RX_LOOPBACK			BIT(17)
+	#define USB_R0_P30_LANE0_EXT_PCLK_REQ			BIT(18)
+	#define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK		GENMASK(28, 19)
+	#define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK		GENMASK(30, 29)
+	#define USB_R0_U2D_ACT					BIT(31)
+
+#define USB_R1							0x04
+	#define USB_R1_U3H_BIGENDIAN_GS				BIT(0)
+	#define USB_R1_U3H_PME_ENABLE				BIT(1)
+	#define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK		GENMASK(6, 2)
+	#define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK		GENMASK(11, 7)
+	#define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK		GENMASK(15, 12)
+	#define USB_R1_U3H_HOST_U3_PORT_DISABLE			BIT(16)
+	#define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT	BIT(17)
+	#define USB_R1_U3H_HOST_MSI_ENABLE			BIT(18)
+	#define USB_R1_U3H_FLADJ_30MHZ_REG_MASK			GENMASK(24, 19)
+	#define USB_R1_P30_PCS_TX_SWING_FULL_MASK		GENMASK(31, 25)
+
+#define USB_R2							0x08
+	#define USB_R2_P30_CR_DATA_IN_MASK			GENMASK(15, 0)
+	#define USB_R2_P30_CR_READ				BIT(16)
+	#define USB_R2_P30_CR_WRITE				BIT(17)
+	#define USB_R2_P30_CR_CAP_ADDR				BIT(18)
+	#define USB_R2_P30_CR_CAP_DATA				BIT(19)
+	#define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK		GENMASK(25, 20)
+	#define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK		GENMASK(31, 26)
+
+#define USB_R3							0x0c
+	#define USB_R3_P30_SSC_ENABLE				BIT(0)
+	#define USB_R3_P30_SSC_RANGE_MASK			GENMASK(3, 1)
+	#define USB_R3_P30_SSC_REF_CLK_SEL_MASK			GENMASK(12, 4)
+	#define USB_R3_P30_REF_SSP_EN				BIT(13)
+	#define USB_R3_P30_LOS_BIAS_MASK			GENMASK(18, 16)
+	#define USB_R3_P30_LOS_LEVEL_MASK			GENMASK(23, 19)
+	#define USB_R3_P30_MPLL_MULTIPLIER_MASK			GENMASK(30, 24)
+
+#define USB_R4							0x10
+	#define USB_R4_P21_PORT_RESET_0				BIT(0)
+	#define USB_R4_P21_SLEEP_M0				BIT(1)
+	#define USB_R4_MEM_PD_MASK				GENMASK(3, 2)
+	#define USB_R4_P21_ONLY					BIT(4)
+
+#define USB_R5							0x14
+	#define USB_R5_ID_DIG_SYNC				BIT(0)
+	#define USB_R5_ID_DIG_REG				BIT(1)
+	#define USB_R5_ID_DIG_CFG_MASK				GENMASK(3, 2)
+	#define USB_R5_ID_DIG_EN_0				BIT(4)
+	#define USB_R5_ID_DIG_EN_1				BIT(5)
+	#define USB_R5_ID_DIG_CURR				BIT(6)
+	#define USB_R5_ID_DIG_IRQ				BIT(7)
+	#define USB_R5_ID_DIG_TH_MASK				GENMASK(15, 8)
+	#define USB_R5_ID_DIG_CNT_MASK				GENMASK(23, 16)
+
+/* read-only register */
+#define USB_R6							0x18
+	#define USB_R6_P30_CR_DATA_OUT_MASK			GENMASK(15, 0)
+	#define USB_R6_P30_CR_ACK				BIT(16)
+
+enum {
+	USB2_HOST_PHY0 = 0,
+	USB2_OTG_PHY1,
+	USB2_HOST_PHY2,
+	PHY_COUNT,
+};
+
+static const char *phy_names[PHY_COUNT] = {
+	"usb2-phy0", "usb2-phy1", "usb2-phy2",
+};
+
+struct dwc3_meson_gxl {
+	struct udevice		*dev;
+	struct regmap           *regmap;
+	struct clk		clk;
+	struct reset_ctl	reset;
+	struct phy		phys[PHY_COUNT];
+	enum usb_dr_mode	otg_mode;
+	enum usb_dr_mode	otg_phy_mode;
+	unsigned int		usb2_ports;
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+	struct udevice		*vbus_supply;
+#endif
+};
+
+#define U2P_REG_SIZE						0x20
+#define USB_REG_OFFSET						0x80
+
+#define USB2_OTG_PHY						USB2_OTG_PHY1
+
+static void dwc3_meson_gxl_usb2_set_mode(struct dwc3_meson_gxl *priv, enum usb_dr_mode mode)
+{
+	switch (mode) {
+	case USB_DR_MODE_HOST:
+	case USB_DR_MODE_OTG:
+	case USB_DR_MODE_UNKNOWN:
+		regmap_update_bits(priv->regmap, USB_R1,
+				   USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK, 0);
+		regmap_update_bits(priv->regmap, USB_R0,
+				   USB_R0_U2D_ACT, 0);
+		regmap_update_bits(priv->regmap, USB_R4,
+				   USB_R4_P21_SLEEP_M0, 0);
+		break;
+
+	case USB_DR_MODE_PERIPHERAL:
+		regmap_update_bits(priv->regmap, USB_R0,
+				   USB_R0_U2D_ACT, USB_R0_U2D_ACT);
+		regmap_update_bits(priv->regmap, USB_R0,
+				   USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
+		regmap_update_bits(priv->regmap, USB_R4,
+				   USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
+		break;
+	}
+}
+
+static int dwc3_meson_gxl_usb2_init(struct dwc3_meson_gxl *priv)
+{
+	int i;
+
+	for (i = 0; i < PHY_COUNT; ++i) {
+		if (!priv->phys[i].dev)
+			continue;
+
+		phy_meson_gxl_usb2_set_mode(&priv->phys[i],
+				(i == USB2_OTG_PHY) ? USB_DR_MODE_PERIPHERAL
+						    : USB_DR_MODE_HOST);
+	}
+
+	return 0;
+}
+
+static int dwc3_meson_gxl_usb_init(struct dwc3_meson_gxl *priv)
+{
+	int ret;
+	
+	ret = dwc3_meson_gxl_usb2_init(priv);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(priv->regmap, USB_R1,
+			   USB_R1_U3H_FLADJ_30MHZ_REG_MASK,
+			   FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20));
+
+	regmap_update_bits(priv->regmap, USB_R5,
+			   USB_R5_ID_DIG_EN_0,
+			   USB_R5_ID_DIG_EN_0);
+	regmap_update_bits(priv->regmap, USB_R5,
+			   USB_R5_ID_DIG_EN_1,
+			   USB_R5_ID_DIG_EN_1);
+	regmap_update_bits(priv->regmap, USB_R5,
+			   USB_R5_ID_DIG_TH_MASK,
+			   FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff));
+
+	dwc3_meson_gxl_usb2_set_mode(priv, priv->otg_phy_mode);
+
+	return 0;
+}
+
+int dwc3_meson_gxl_force_mode(struct udevice *dev, enum usb_dr_mode mode)
+{
+	struct dwc3_meson_gxl *priv = dev_get_platdata(dev);
+
+	if (!priv)
+		return -EINVAL;
+
+	if (mode != USB_DR_MODE_HOST && mode != USB_DR_MODE_PERIPHERAL)
+		return -EINVAL;
+
+	if (!priv->phys[USB2_OTG_PHY].dev)
+		return -EINVAL;
+
+	if (mode == priv->otg_phy_mode)
+		return 0;
+
+	if (mode == USB_DR_MODE_HOST)
+		debug("%s: switching to Host Mode\n", __func__);
+	else
+		debug("%s: switching to Device Mode\n", __func__);
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+	if (priv->vbus_supply) {
+		int ret = regulator_set_enable(priv->vbus_supply,
+					(mode == USB_DR_MODE_PERIPHERAL));
+		if (ret)
+			return ret;
+	}
+#endif
+	priv->otg_phy_mode = mode;
+
+	phy_meson_gxl_usb2_set_mode(&priv->phys[USB2_OTG_PHY], mode);
+
+	dwc3_meson_gxl_usb2_set_mode(priv, mode);
+
+	return 0;
+}
+
+static int dwc3_meson_gxl_get_phys(struct dwc3_meson_gxl *priv)
+{
+	int i, ret;
+
+	for (i = 0 ; i < PHY_COUNT ; ++i) {
+		ret = generic_phy_get_by_name(priv->dev, phy_names[i],
+					      &priv->phys[i]);
+		if (ret == -ENOENT || ret == -ENODATA) {
+			priv->phys[i].dev = NULL;
+			continue;
+		}
+
+		if (ret)
+			return ret;
+
+		priv->usb2_ports++;
+	}
+
+	debug("%s: usb2 ports: %d\n", __func__, priv->usb2_ports);
+
+	return 0;
+}
+
+static int dwc3_meson_gxl_reset_init(struct dwc3_meson_gxl *priv)
+{
+	int ret;
+
+	ret = reset_get_by_index(priv->dev, 0, &priv->reset);
+	if (ret)
+		return ret;
+
+	ret = reset_assert(&priv->reset);
+	udelay(1);
+	ret |= reset_deassert(&priv->reset);
+	if (ret) {
+		reset_free(&priv->reset);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dwc3_meson_gxl_clk_init(struct dwc3_meson_gxl *priv)
+{
+	int ret;
+
+	ret = clk_get_by_index(priv->dev, 0, &priv->clk);
+	if (ret)
+		return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+	ret = clk_enable(&priv->clk);
+	if (ret) {
+		clk_free(&priv->clk);
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+
+static int dwc3_meson_gxl_probe(struct udevice *dev)
+{
+	struct dwc3_meson_gxl *priv = dev_get_platdata(dev);
+	int ret, i;
+
+	priv->dev = dev;
+
+	ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
+	if (ret)
+		return ret;
+
+	ret = dwc3_meson_gxl_clk_init(priv);
+	if (ret)
+		return ret;
+
+	ret = dwc3_meson_gxl_reset_init(priv);
+	if (ret)
+		return ret;
+
+	ret = dwc3_meson_gxl_get_phys(priv);
+	if (ret)
+		return ret;
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+	ret = device_get_supply_regulator(dev, "vbus-supply",
+					  &priv->vbus_supply);
+	if (ret && ret != -ENOENT) {
+		pr_err("Failed to get PHY regulator\n");
+		return ret;
+	}
+
+	if (priv->vbus_supply) {
+		ret = regulator_set_enable(priv->vbus_supply, true);
+		if (ret)
+			return ret;
+	}
+#endif
+
+	/* On GXL PHY must be started in device mode for DWC2 init */
+	priv->otg_mode = USB_DR_MODE_PERIPHERAL;
+
+	ret = dwc3_meson_gxl_usb_init(priv);
+	if (ret)
+		return ret;
+
+	priv->otg_mode = usb_get_dr_mode(dev->node);
+
+	if (priv->otg_mode == USB_DR_MODE_PERIPHERAL)
+		priv->otg_phy_mode = USB_DR_MODE_PERIPHERAL;
+	else
+		priv->otg_phy_mode = USB_DR_MODE_HOST;
+
+	for (i = 0 ; i < PHY_COUNT ; ++i) {
+		if (!priv->phys[i].dev)
+			continue;
+
+		ret = generic_phy_init(&priv->phys[i]);
+		if (ret)
+			goto err_phy_init;
+	}
+
+	for (i = 0; i < PHY_COUNT; ++i) {
+		if (!priv->phys[i].dev)
+			continue;
+
+		ret = generic_phy_power_on(&priv->phys[i]);
+		if (ret)
+			goto err_phy_init;
+	}
+
+	if (priv->phys[USB2_OTG_PHY].dev)
+		phy_meson_gxl_usb2_set_mode(&priv->phys[USB2_OTG_PHY],
+					    priv->otg_phy_mode);
+
+	dwc3_meson_gxl_usb2_set_mode(priv, priv->otg_phy_mode);
+
+	return 0;
+
+err_phy_init:
+	for (i = 0 ; i < PHY_COUNT ; ++i) {
+		if (!priv->phys[i].dev)
+			continue;
+
+		 generic_phy_exit(&priv->phys[i]);
+	}
+
+	return ret;
+}
+
+static int dwc3_meson_gxl_remove(struct udevice *dev)
+{
+	struct dwc3_meson_gxl *priv = dev_get_platdata(dev);
+	int i;
+
+	reset_release_all(&priv->reset, 1);
+
+	clk_release_all(&priv->clk, 1);
+
+	for (i = 0; i < PHY_COUNT; ++i) {
+		if (!priv->phys[i].dev)
+			continue;
+
+		 generic_phy_power_off(&priv->phys[i]);
+	}
+
+	for (i = 0 ; i < PHY_COUNT ; ++i) {
+		if (!priv->phys[i].dev)
+			continue;
+
+		 generic_phy_exit(&priv->phys[i]);
+	}
+
+	return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc3_meson_gxl_ids[] = {
+	{ .compatible = "amlogic,meson-gxl-usb-ctrl" },
+	{ .compatible = "amlogic,meson-gxm-usb-ctrl" },
+	{ }
+};
+
+U_BOOT_DRIVER(dwc3_generic_wrapper) = {
+	.name	= "dwc3-meson-gxl",
+	.id	= UCLASS_SIMPLE_BUS,
+	.of_match = dwc3_meson_gxl_ids,
+	.probe = dwc3_meson_gxl_probe,
+	.remove = dwc3_meson_gxl_remove,
+	.platdata_auto_alloc_size = sizeof(struct dwc3_meson_gxl),
+
+};

+ 2 - 0
include/dt-bindings/clock/g12a-clkc.h

@@ -145,5 +145,7 @@
 #define CLKID_CPU3_CLK				255
 #define CLKID_CPU3_CLK				255
 #define CLKID_SPICC0_SCLK			258
 #define CLKID_SPICC0_SCLK			258
 #define CLKID_SPICC1_SCLK			261
 #define CLKID_SPICC1_SCLK			261
+#define CLKID_NNA_AXI_CLK			264
+#define CLKID_NNA_CORE_CLK			267
 
 
 #endif /* __G12A_CLKC_H */
 #endif /* __G12A_CLKC_H */

+ 1 - 1
include/dt-bindings/reset/amlogic,meson-gxbb-reset.h

@@ -69,7 +69,7 @@
 #define RESET_SYS_CPU_L2		58
 #define RESET_SYS_CPU_L2		58
 #define RESET_SYS_CPU_P			59
 #define RESET_SYS_CPU_P			59
 #define RESET_SYS_CPU_MBIST		60
 #define RESET_SYS_CPU_MBIST		60
-/*					61	*/
+#define RESET_ACODEC			61
 /*					62	*/
 /*					62	*/
 /*					63	*/
 /*					63	*/
 /*	RESET2					*/
 /*	RESET2					*/

+ 18 - 0
include/dt-bindings/sound/meson-aiu.h

@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_MESON_AIU_H
+#define __DT_MESON_AIU_H
+
+#define AIU_CPU			0
+#define AIU_HDMI		1
+#define AIU_ACODEC		2
+
+#define CPU_I2S_FIFO		0
+#define CPU_SPDIF_FIFO		1
+#define CPU_I2S_ENCODER		2
+#define CPU_SPDIF_ENCODER	3
+
+#define CTRL_I2S		0
+#define CTRL_PCM		1
+#define CTRL_OUT		2
+
+#endif /* __DT_MESON_AIU_H */

+ 10 - 0
include/dt-bindings/sound/meson-g12a-toacodec.h

@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_MESON_G12A_TOACODEC_H
+#define __DT_MESON_G12A_TOACODEC_H
+
+#define TOACODEC_IN_A	0
+#define TOACODEC_IN_B	1
+#define TOACODEC_IN_C	2
+#define TOACODEC_OUT	3
+
+#endif /* __DT_MESON_G12A_TOACODEC_H */