- 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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPVPGJshWBf4d9CyLd9zb2sjISdEFAl97ReAACgkQd9zb2sjI
 SdHHVA/9HuEAzwuJyJoyQcXARIqMwoi6w4qntlmb+VTnxxlKCzLL1Ir68W2+5Y5S
 l+sVkxYDwTmYRs40FOnMdFM1r1Q7IqWwTemqQAcfmGLV+/+MwoDiludGat7JAp1i
 mo/FBcBMLrf3dIJnhCyl2Rezgu06GLCQMAJOlusTDaruUZUHBxPVpAhfRvtlYq1Q
 bCINZfgMcmv8EfReIOE6xGt0+9TKILqQamMByc2ZWdz5UBioqUdQ82arW1rdV/ze
 ATU7vrxNmNlUQnRsMBOry9chbeuNrAhD8sqVloGPUikhf93y0BG7eINmCYrLoXjN
 mopApyWzo3+50GI6It+P9vX6mWVJhd8gAJsvTkRn8ok3flGlRQPmFmAfkjngN/GH
 wdkZpKi/u/ndm2Id7ekZff/Fm/ZmL/kskrRWaWrnuxHNiSNiJvAl+PU7MzCGrgED
 E0MduY1hFpa7wc47xFtI0WKlcdNVQCTRwuZYVIZYlnhXeVupJyQ0dx1ggonlvvIZ
 3cgS2qzd8z2RxKzhnRDvjSfwy7gWFjqpljocyRP4osoWJybJu88MIUFK2GlPdc7x
 3UD/+R88FsIVsQuxzbwBuFZnP+Zo1JqCmspyX4sCeUBDNK4+MqOqIxBZry+q4qso
 usWrTofg2hfxS3FgUL0pQW5GF8JGm4uXcIjbe7fMi47GJ6Lp/ec=
 =rbAX
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Tom Rini 2020-10-06 08:36:10 -04:00
commit 987ab49366
63 changed files with 2316 additions and 398 deletions

View file

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

View file

@ -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";
};
};

View file

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

View file

@ -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>; <&clkc CLKID_MPLL2>,
clock-names = "stmmaceth", "clkin0", "clkin1"; <&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>;
operating-points-v2 = <&gpu_opp_table>;
/*
* 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 */
#cooling-cells = <2>; #cooling-cells = <2>;
}; };
}; };

View file

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

View file

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

View file

@ -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 { cpu_scp_lpri: scp-sram@0 {
compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem"; compatible = "amlogic,meson-gxbb-scp-shmem";
reg = <0x13000 0x400>; reg = <0x13000 0x400>;
}; };
cpu_scp_hpri: scp-shmem@200 { cpu_scp_hpri: scp-sram@200 {
compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem"; 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 */

View file

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

View file

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

View file

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

View file

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

View file

@ -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";
}; };

View file

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

View file

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

View file

@ -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";
};

View file

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

View file

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

View file

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

View file

@ -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";
};
};

View file

@ -14,29 +14,57 @@
compatible = "amlogic,meson-gxl"; compatible = "amlogic,meson-gxl";
soc { soc {
usb0: usb@c9000000 { usb: usb@d0078080 {
status = "disabled"; compatible = "amlogic,meson-gxl-usb-ctrl";
compatible = "amlogic,meson-gxl-dwc3"; 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>; clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1_DDR_BRIDGE>;
clock-names = "usb_general"; 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 {

View file

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

View file

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

View file

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

View file

@ -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 { &usb {
phys = <&usb3_phy>, <&usb2_phy0>, <&usb2_phy1>, <&usb2_phy2>; compatible = "amlogic,meson-gxm-usb-ctrl";
phy-names = "usb2-phy0", "usb2-phy1", "usb2-phy2";
phys = <&usb2_phy0>, <&usb2_phy1>, <&usb2_phy2>;
}; };
&vdec { &vdec {

View file

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

View file

@ -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";
};

View file

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

View file

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

View file

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

View file

@ -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 fdtdec_phandle_args args;
struct udevice *clk_dev; const void *blob = gd->fdt_blob;
ofnode dwc2_node; int node, dwc2_node;
struct udevice *dev, *clk_dev;
struct clk clk; struct clk clk;
int ret, i; int ret;
u32 val;
/* 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 (!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 */ /* find the dwc2 node */
dwc2_node = ofnode_by_compatible(ofnode_null(), "snps,dwc2"); dwc2_node = fdt_node_offset_by_compatible(blob, node,
if (!ofnode_valid(dwc2_node)) { "amlogic,meson-g12a-usb");
if (dwc2_node < 0) {
debug("Not found dwc2 node\n"); debug("Not found dwc2 node\n");
return -ENODEV; return -ENODEV;
} }
if (!ofnode_is_available(dwc2_node)) { if (!fdtdec_get_is_enabled(blob, dwc2_node)) {
debug("dwc2 is disabled in the device tree\n"); debug("dwc2 is disabled in the device tree\n");
return -ENODEV; return -ENODEV;
} }
/* get the PHYs */ meson_gx_dwc2_data.regs_otg = fdtdec_get_addr(blob, dwc2_node, "reg");
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;
}
}
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;
}
}
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;
}
}
phy_meson_gxl_usb3_set_mode(&usb_phys[0], USB_DR_MODE_PERIPHERAL);
phy_meson_gxl_usb2_set_mode(&usb_phys[1], USB_DR_MODE_PERIPHERAL);
meson_gx_dwc2_data.regs_otg = ofnode_get_addr(dwc2_node);
if (meson_gx_dwc2_data.regs_otg == FDT_ADDR_T_NONE) { 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 = fdtdec_get_int(blob, dwc2_node,
meson_gx_dwc2_data.rx_fifo_sz = val; "g-rx-fifo-size", 0);
ofnode_read_u32(dwc2_node, "g-np-tx-fifo-size", &val); meson_gx_dwc2_data.np_tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
meson_gx_dwc2_data.np_tx_fifo_sz = val; "g-np-tx-fifo-size", 0);
ofnode_read_u32(dwc2_node, "g-tx-fifo-size", &val); meson_gx_dwc2_data.tx_fifo_sz = fdtdec_get_int(blob, dwc2_node,
meson_gx_dwc2_data.tx_fifo_sz = val; "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;
phy_meson_gxl_usb3_set_mode(&usb_phys[0], USB_DR_MODE_HOST); /* find the usb glue node */
phy_meson_gxl_usb2_set_mode(&usb_phys[1], USB_DR_MODE_HOST); 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;
}
}
for (i = 0; i < 2; i++) if (!fdtdec_get_is_enabled(blob, node))
usb_phys[i].dev = NULL; 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; return 0;
} }

View file

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

View file

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

View file

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

View file

@ -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
board/amlogic/vim3/vim3.c Normal file
View file

@ -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
* 0Enable USB3.0Disable PCIE, 1Disable 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;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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),
};

View file

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

View file

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

View file

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

View file

@ -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
drivers/pwm/pwm-meson.c Normal file
View file

@ -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),
};

View file

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

View file

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

View file

@ -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),
};

View file

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

View file

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

View file

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

View file

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