Merge tag 'efi-2024-04-rc1-4' of https://source.denx.de/u-boot/custodians/u-boot-efi
Pull request efi-2024-04-rc1-4
Documentation:
* uefi: remove ".py" suffix for pytest.py command
* correct date in migration plan for CONFIG_DM
UEFI:
* fix conflicting SPDX license in RISC-V EFI linker scripts
* page align EFI binary section in RISC-V EFI binaries
* separate .data and .text sections of RISC-V EFI binaries
* use common function to get EFI configuration table
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index abd7c6c..59e4d4d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1160,14 +1160,14 @@
select SPL_SEPARATE_BSS if SPL
select SPL_STACK_R if SPL
select SPL_SYS_MALLOC_SIMPLE if SPL
- select SPL_SYS_THUMB_BUILD if !ARM64
+ select SPL_SYS_THUMB_BUILD if SPL && !ARM64
select SUNXI_GPIO
select SYS_NS16550
select SYS_THUMB_BUILD if !ARM64
select USB if DISTRO_DEFAULTS
select USB_KEYBOARD if DISTRO_DEFAULTS && USB_HOST
select USB_STORAGE if DISTRO_DEFAULTS && USB_HOST
- select SPL_USE_TINY_PRINTF
+ select SPL_USE_TINY_PRINTF if SPL
select USE_PREBOOT
select SYS_RELOC_GD_ENV_ADDR
imply BOARD_LATE_INIT
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index b5c588c..50f35e3 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -838,6 +838,7 @@
dtb-$(CONFIG_MACH_SUN50I_H616) += \
sun50i-h616-orangepi-zero2.dtb \
sun50i-h618-orangepi-zero3.dtb \
+ sun50i-h618-transpeed-8k618-t.dtb \
sun50i-h616-x96-mate.dtb
dtb-$(CONFIG_MACH_SUN50I) += \
sun50i-a64-amarula-relic.dtb \
diff --git a/arch/arm/dts/sun50i-h616-bigtreetech-cb1-manta.dts b/arch/arm/dts/sun50i-h616-bigtreetech-cb1-manta.dts
new file mode 100644
index 0000000..dbce61b
--- /dev/null
+++ b/arch/arm/dts/sun50i-h616-bigtreetech-cb1-manta.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2023 Martin Botka <martin.botka@somainline.org>.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616-bigtreetech-cb1.dtsi"
+
+/ {
+ model = "BigTreeTech CB1";
+ compatible = "bigtreetech,cb1-manta", "bigtreetech,cb1", "allwinner,sun50i-h616";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h616-bigtreetech-cb1.dtsi b/arch/arm/dts/sun50i-h616-bigtreetech-cb1.dtsi
new file mode 100644
index 0000000..1fed2b4
--- /dev/null
+++ b/arch/arm/dts/sun50i-h616-bigtreetech-cb1.dtsi
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2023 Martin Botka <martin.botka@somainline.org>.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ ethernet0 = &rtl8189ftv;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+ };
+ };
+
+ reg_vcc5v: regulator-vcc5v {
+ /* board wide 5V supply from carrier boards */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_vcc33_wifi: vcc33-wifi {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc33-wifi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ vin-supply = <®_vcc5v>;
+ };
+
+ reg_vcc_wifi_io: vcc-wifi-io {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-wifi-io";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ vin-supply = <®_vcc33_wifi>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rtc 1>;
+ clock-names = "ext_clock";
+ reset-gpios = <&pio 6 18 GPIO_ACTIVE_LOW>; /* PG18 */
+ post-power-on-delay-ms = <200>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <®_dldo1>;
+ /* Card detection pin is not connected */
+ broken-cd;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc1 {
+ vmmc-supply = <®_vcc33_wifi>;
+ vqmmc-supply = <®_vcc_wifi_io>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ mmc-ddr-1_8v;
+ status = "okay";
+
+ rtl8189ftv: wifi@1 {
+ reg = <1>;
+ };
+};
+
+&r_i2c {
+ status = "okay";
+
+ axp313a: pmic@36 {
+ compatible = "x-powers,axp313a";
+ reg = <0x36>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ regulators{
+ reg_dcdc1: dcdc1 {
+ regulator-name = "vdd-gpu-sys";
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <990000>;
+ regulator-always-on;
+ };
+
+ reg_dcdc2: dcdc2 {
+ regulator-name = "vdd-cpu";
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-ramp-delay = <200>;
+ regulator-always-on;
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-name = "vcc-dram";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ };
+
+ reg_aldo1: aldo1 {
+ regulator-name = "vcc-1v8-pll";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ reg_dldo1: dldo1 {
+ regulator-name = "vcc-3v3-io";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&usbphy {
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h616-bigtreetech-pi.dts b/arch/arm/dts/sun50i-h616-bigtreetech-pi.dts
new file mode 100644
index 0000000..832f08b
--- /dev/null
+++ b/arch/arm/dts/sun50i-h616-bigtreetech-pi.dts
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2023 Martin Botka <martin@biqu3d.com>.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616-bigtreetech-cb1.dtsi"
+
+/ {
+ model = "BigTreeTech Pi";
+ compatible = "bigtreetech,pi", "allwinner,sun50i-h616";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&ir {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&ohci3 {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h616.dtsi b/arch/arm/dts/sun50i-h616.dtsi
index 74aed0d..d549d27 100644
--- a/arch/arm/dts/sun50i-h616.dtsi
+++ b/arch/arm/dts/sun50i-h616.dtsi
@@ -133,6 +133,13 @@
#reset-cells = <1>;
};
+ sid: efuse@3006000 {
+ compatible = "allwinner,sun50i-h616-sid", "allwinner,sun50i-a64-sid";
+ reg = <0x03006000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
watchdog: watchdog@30090a0 {
compatible = "allwinner,sun50i-h616-wdt",
"allwinner,sun6i-a31-wdt";
diff --git a/arch/arm/dts/sun50i-h618-orangepi-zero2w.dts b/arch/arm/dts/sun50i-h618-orangepi-zero2w.dts
new file mode 100644
index 0000000..21ca197
--- /dev/null
+++ b/arch/arm/dts/sun50i-h618-orangepi-zero2w.dts
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "OrangePi Zero 2W";
+ compatible = "xunlong,orangepi-zero2w", "allwinner,sun50i-h618";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
+ };
+ };
+
+ reg_vcc5v: vcc5v {
+ /* board wide 5V supply directly from the USB-C socket */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ /* SY8089 DC/DC converter */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <®_vcc5v>;
+ regulator-always-on;
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+/* USB 2 & 3 are on the FPC connector (or the exansion board) */
+
+&mmc0 {
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ vmmc-supply = <®_vcc3v3>;
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ vcc-pc-supply = <®_dldo1>;
+ vcc-pf-supply = <®_dldo1>; /* internally via VCC-IO */
+ vcc-pg-supply = <®_aldo1>;
+ vcc-ph-supply = <®_dldo1>; /* internally via VCC-IO */
+ vcc-pi-supply = <®_dldo1>;
+};
+
+&r_i2c {
+ status = "okay";
+
+ axp313: pmic@36 {
+ compatible = "x-powers,axp313a";
+ reg = <0x36>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ interrupt-parent = <&pio>;
+ interrupts = <2 9 IRQ_TYPE_LEVEL_LOW>; /* PC9 */
+
+ vin1-supply = <®_vcc5v>;
+ vin2-supply = <®_vcc5v>;
+ vin3-supply = <®_vcc5v>;
+
+ regulators {
+ /* Supplies VCC-PLL and DRAM */
+ reg_aldo1: aldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc1v8";
+ };
+
+ /* Supplies VCC-IO, so needs to be always on. */
+ reg_dldo1: dldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc3v3";
+ };
+
+ reg_dcdc1: dcdc1 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <990000>;
+ regulator-name = "vdd-gpu-sys";
+ };
+
+ reg_dcdc2: dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-cpu";
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-dram";
+ };
+ };
+ };
+};
+
+&spi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>;
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&usbotg {
+ /*
+ * PHY0 pins are connected to a USB-C socket, but a role switch
+ * is not implemented: both CC pins are pulled to GND.
+ * The VBUS pins power the device, so a fixed peripheral mode
+ * is the best choice.
+ * The board can be powered via GPIOs, in this case port0 *can*
+ * act as a host (with a cable/adapter ignoring CC), as VBUS is
+ * then provided by the GPIOs. Any user of this setup would
+ * need to adjust the DT accordingly: dr_mode set to "host",
+ * enabling OHCI0 and EHCI0.
+ */
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <®_vcc5v>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h618-transpeed-8k618-t.dts b/arch/arm/dts/sun50i-h618-transpeed-8k618-t.dts
new file mode 100644
index 0000000..8ea1fd4
--- /dev/null
+++ b/arch/arm/dts/sun50i-h618-transpeed-8k618-t.dts
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ model = "Transpeed 8K618-T";
+ compatible = "transpeed,8k618-t", "allwinner,sun50i-h618";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reg_vcc5v: vcc5v {
+ /* board wide 5V supply directly from the DC input */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ /* discrete 3.3V regulator */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ir {
+ status = "okay";
+};
+
+&mmc0 {
+ vmmc-supply = <®_dldo1>;
+ cd-gpios = <&pio 8 16 GPIO_ACTIVE_LOW>; /* PI16 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc2 {
+ vmmc-supply = <®_dldo1>;
+ vqmmc-supply = <®_aldo1>;
+ bus-width = <8>;
+ non-removable;
+ cap-mmc-hw-reset;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&r_i2c {
+ status = "okay";
+
+ axp313: pmic@36 {
+ compatible = "x-powers,axp313a";
+ reg = <0x36>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+
+ vin1-supply = <®_vcc5v>;
+ vin2-supply = <®_vcc5v>;
+ vin3-supply = <®_vcc5v>;
+
+ regulators {
+ reg_aldo1: aldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc-1v8-pll";
+ };
+
+ reg_dldo1: dldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-3v3-io-mmc";
+ };
+
+ reg_dcdc1: dcdc1 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <990000>;
+ regulator-name = "vdd-gpu-sys";
+ };
+
+ reg_dcdc2: dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-cpu";
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <1360000>;
+ regulator-max-microvolt = <1360000>;
+ regulator-name = "vdd-dram";
+ };
+ };
+ };
+};
+
+&pio {
+ vcc-pc-supply = <®_aldo1>;
+ vcc-pg-supply = <®_dldo1>;
+ vcc-ph-supply = <®_dldo1>;
+ vcc-pi-supply = <®_dldo1>;
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usbotg {
+ dr_mode = "host"; /* USB A type receptable */
+ status = "okay";
+};
+
+&usbphy {
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun8i-r40.dtsi b/arch/arm/dts/sun8i-r40.dtsi
index 4ef26d8..a5b1f1e 100644
--- a/arch/arm/dts/sun8i-r40.dtsi
+++ b/arch/arm/dts/sun8i-r40.dtsi
@@ -338,6 +338,8 @@
resets = <&ccu RST_BUS_VE>;
interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
allwinner,sram = <&ve_sram 1>;
+ interconnects = <&mbus 4>;
+ interconnect-names = "dma-mem";
};
mmc0: mmc@1c0f000 {
diff --git a/arch/arm/dts/sun8i-v3s-anbernic-rg-nano.dts b/arch/arm/dts/sun8i-v3s-anbernic-rg-nano.dts
new file mode 100644
index 0000000..f34dfdf
--- /dev/null
+++ b/arch/arm/dts/sun8i-v3s-anbernic-rg-nano.dts
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+#include <dt-bindings/input/linux-event-codes.h>
+#include "sun8i-v3s.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+/ {
+ model = "Anbernic RG Nano";
+ compatible = "anbernic,rg-nano", "allwinner,sun8i-v3s";
+
+ aliases {
+ rtc0 = &pcf8563;
+ rtc1 = &rtc;
+ serial0 = &uart0;
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ brightness-levels = <0 1 2 3 8 14 21 32 46 60 80 100>;
+ default-brightness-level = <11>;
+ power-supply = <®_vcc5v0>;
+ pwms = <&pwm 0 40000 1>;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio_keys: gpio-keys {
+ compatible = "gpio-keys";
+
+ button-a {
+ gpios = <&gpio_expander 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-A";
+ linux,code = <BTN_EAST>;
+ };
+
+ button-b {
+ gpios = <&gpio_expander 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-B";
+ linux,code = <BTN_SOUTH>;
+ };
+
+ button-down {
+ gpios = <&gpio_expander 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-DOWN";
+ linux,code = <BTN_DPAD_DOWN>;
+ };
+
+ button-left {
+ gpios = <&gpio_expander 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-LEFT";
+ linux,code = <BTN_DPAD_LEFT>;
+ };
+
+ button-right {
+ gpios = <&gpio_expander 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-RIGHT";
+ linux,code = <BTN_DPAD_RIGHT>;
+ };
+
+ button-se {
+ gpios = <&gpio_expander 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-SELECT";
+ linux,code = <BTN_SELECT>;
+ };
+
+ button-st {
+ gpios = <&gpio_expander 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-START";
+ linux,code = <BTN_START>;
+ };
+
+ button-tl {
+ gpios = <&gpio_expander 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-L";
+ linux,code = <BTN_TL>;
+ };
+
+ button-tr {
+ gpios = <&gpio_expander 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-R";
+ linux,code = <BTN_TR>;
+ };
+
+ button-up {
+ gpios = <&gpio_expander 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "DPAD-UP";
+ linux,code = <BTN_DPAD_UP>;
+ };
+
+ button-x {
+ gpios = <&gpio_expander 11 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-X";
+ linux,code = <BTN_NORTH>;
+ };
+
+ button-y {
+ gpios = <&gpio_expander 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ label = "BTN-Y";
+ linux,code = <BTN_WEST>;
+ };
+ };
+};
+
+&codec {
+ allwinner,audio-routing = "Speaker", "HP",
+ "MIC1", "Mic",
+ "Mic", "HBIAS";
+ allwinner,pa-gpios = <&pio 5 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PF6 */
+ status = "okay";
+};
+
+&ehci {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ gpio_expander: gpio@20 {
+ compatible = "nxp,pcal6416";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ interrupt-parent = <&pio>;
+ interrupts = <1 3 IRQ_TYPE_EDGE_BOTH>; /* PB3/EINT3 */
+ vcc-supply = <®_vcc3v3>;
+ };
+
+ axp209: pmic@34 {
+ reg = <0x34>;
+ interrupt-parent = <&pio>;
+ interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* PB5/EINT5 */
+ };
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+};
+
+#include "axp209.dtsi"
+
+&battery_power_supply {
+ status = "okay";
+};
+
+&mmc0 {
+ broken-cd;
+ bus-width = <4>;
+ disable-wp;
+ vmmc-supply = <®_vcc3v3>;
+ vqmmc-supply = <®_vcc3v3>;
+ status = "okay";
+};
+
+&ohci {
+ status = "okay";
+};
+
+&pio {
+ vcc-pb-supply = <®_vcc3v3>;
+ vcc-pc-supply = <®_vcc3v3>;
+ vcc-pf-supply = <®_vcc3v3>;
+ vcc-pg-supply = <®_vcc3v3>;
+
+ spi0_no_miso_pins: spi0-no-miso-pins {
+ pins = "PC1", "PC2", "PC3";
+ function = "spi0";
+ };
+};
+
+&pwm {
+ pinctrl-0 = <&pwm0_pin>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+/* DCDC2 wired into vdd-cpu, vdd-sys, and vdd-ephy. */
+®_dcdc2 {
+ regulator-always-on;
+ regulator-max-microvolt = <1250000>;
+ regulator-min-microvolt = <1250000>;
+ regulator-name = "vdd-cpu";
+};
+
+/* DCDC3 wired into every 3.3v input that isn't the RTC. */
+®_dcdc3 {
+ regulator-always-on;
+ regulator-max-microvolt = <3300000>;
+ regulator-min-microvolt = <3300000>;
+ regulator-name = "vcc-io";
+};
+
+/* LDO1 wired into RTC, voltage is hard-wired at 3.3v. */
+®_ldo1 {
+ regulator-always-on;
+ regulator-name = "vcc-rtc";
+};
+
+/* LDO2 wired into VCC-PLL and audio codec. */
+®_ldo2 {
+ regulator-always-on;
+ regulator-max-microvolt = <3000000>;
+ regulator-min-microvolt = <3000000>;
+ regulator-name = "vcc-pll";
+};
+
+/* LDO3, LDO4, and LDO5 unused. */
+®_ldo3 {
+ status = "disabled";
+};
+
+®_ldo4 {
+ status = "disabled";
+};
+
+/* RTC uses internal oscillator */
+&rtc {
+ /delete-property/ clocks;
+};
+
+&spi0 {
+ pinctrl-0 = <&spi0_no_miso_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ display@0 {
+ compatible = "saef,sftc154b", "panel-mipi-dbi-spi";
+ reg = <0>;
+ backlight = <&backlight>;
+ dc-gpios = <&pio 2 0 GPIO_ACTIVE_HIGH>; /* PC0 */
+ reset-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; /* PB2 */
+ spi-max-frequency = <100000000>;
+
+ height-mm = <39>;
+ width-mm = <39>;
+
+ /* Set hb-porch to compensate for non-visible area */
+ panel-timing {
+ hactive = <240>;
+ vactive = <240>;
+ hback-porch = <80>;
+ vback-porch = <0>;
+ clock-frequency = <0>;
+ hfront-porch = <0>;
+ hsync-len = <0>;
+ vfront-porch = <0>;
+ vsync-len = <0>;
+ };
+ };
+};
+
+&uart0 {
+ pinctrl-0 = <&uart0_pb_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usb_power_supply {
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 6 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PG5 */
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun8i-v3s.dtsi b/arch/arm/dts/sun8i-v3s.dtsi
index 3b9a282..e8a0447 100644
--- a/arch/arm/dts/sun8i-v3s.dtsi
+++ b/arch/arm/dts/sun8i-v3s.dtsi
@@ -319,6 +319,29 @@
#phy-cells = <1>;
};
+ ehci: usb@1c1a000 {
+ compatible = "allwinner,sun8i-v3s-ehci", "generic-ehci";
+ reg = <0x01c1a000 0x100>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>;
+ resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci: usb@1c1a400 {
+ compatible = "allwinner,sun8i-v3s-ohci", "generic-ohci";
+ reg = <0x01c1a400 0x100>;
+ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
ccu: clock@1c20000 {
compatible = "allwinner,sun8i-v3s-ccu";
reg = <0x01c20000 0x400>;
@@ -414,6 +437,18 @@
bias-pull-up;
};
+ /omit-if-no-ref/
+ pwm0_pin: pwm0-pin {
+ pins = "PB4";
+ function = "pwm0";
+ };
+
+ /omit-if-no-ref/
+ pwm1_pin: pwm1-pin {
+ pins = "PB5";
+ function = "pwm1";
+ };
+
spi0_pins: spi0-pins {
pins = "PC0", "PC1", "PC2", "PC3";
function = "spi0";
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index a0c8abb..0909a67 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -1,13 +1,9 @@
#include <config.h>
-#ifdef CONFIG_MACH_SUN50I_H6
-#define BL31_ADDR 0x104000
-#define SCP_ADDR 0x114000
-#elif defined(CONFIG_MACH_SUN50I_H616)
-#define BL31_ADDR 0x40000000
+#ifdef CONFIG_ARM64
+#define ARCH "arm64"
#else
-#define BL31_ADDR 0x44000
-#define SCP_ADDR 0x50000
+#define ARCH "arm"
#endif
/ {
@@ -44,47 +40,52 @@
filename = "spl/sunxi-spl.bin";
};
-#ifdef CONFIG_ARM64
+#ifdef CONFIG_SPL_LOAD_FIT
fit {
- description = "Configuration to load ATF before U-Boot";
+ description = "Configuration to load U-Boot and firmware";
#address-cells = <1>;
fit,fdt-list = "of-list";
images {
uboot {
- description = "U-Boot (64-bit)";
+ description = "U-Boot";
type = "standalone";
os = "u-boot";
- arch = "arm64";
+ arch = ARCH;
compression = "none";
load = <CONFIG_TEXT_BASE>;
+#if CONFIG_SUNXI_BL31_BASE == 0
+ entry = <CONFIG_TEXT_BASE>;
+#endif
u-boot-nodtb {
};
};
+#if CONFIG_SUNXI_BL31_BASE
atf {
description = "ARM Trusted Firmware";
type = "firmware";
os = "arm-trusted-firmware";
- arch = "arm64";
+ arch = ARCH;
compression = "none";
- load = <BL31_ADDR>;
- entry = <BL31_ADDR>;
+ load = <CONFIG_SUNXI_BL31_BASE>;
+ entry = <CONFIG_SUNXI_BL31_BASE>;
atf-bl31 {
filename = "bl31.bin";
missing-msg = "atf-bl31-sunxi";
};
};
+#endif
-#ifdef SCP_ADDR
+#if CONFIG_SUNXI_SCP_BASE
scp {
description = "SCP firmware";
type = "firmware";
arch = "or1k";
compression = "none";
- load = <SCP_ADDR>;
+ load = <CONFIG_SUNXI_SCP_BASE>;
scp {
filename = "scp.bin";
@@ -105,11 +106,15 @@
@config-SEQ {
description = "NAME";
+#if CONFIG_SUNXI_BL31_BASE
firmware = "atf";
-#ifndef SCP_ADDR
- loadables = "uboot";
#else
+ firmware = "uboot";
+#endif
+#if CONFIG_SUNXI_SCP_BASE
loadables = "scp", "uboot";
+#else
+ loadables = "uboot";
#endif
fdt = "fdt-SEQ";
};
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index 3daee2f..f023a4c 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -36,58 +36,20 @@
#define SUNXI_SRAMC_BASE 0x01c00000
#define SUNXI_DRAMC_BASE 0x01c01000
-#define SUNXI_DMA_BASE 0x01c02000
#define SUNXI_NFC_BASE 0x01c03000
-#define SUNXI_TS_BASE 0x01c04000
-#define SUNXI_SPI0_BASE 0x01c05000
-#define SUNXI_SPI1_BASE 0x01c06000
-#define SUNXI_MS_BASE 0x01c07000
-#define SUNXI_TVD_BASE 0x01c08000
-#define SUNXI_CSI0_BASE 0x01c09000
#ifndef CONFIG_MACH_SUNXI_H3_H5
#define SUNXI_TVE0_BASE 0x01c0a000
#endif
-#define SUNXI_EMAC_BASE 0x01c0b000
#define SUNXI_LCD0_BASE 0x01c0C000
#define SUNXI_LCD1_BASE 0x01c0d000
-#define SUNXI_VE_BASE 0x01c0e000
#define SUNXI_MMC0_BASE 0x01c0f000
#define SUNXI_MMC1_BASE 0x01c10000
#define SUNXI_MMC2_BASE 0x01c11000
#define SUNXI_MMC3_BASE 0x01c12000
-#ifdef CONFIG_SUNXI_GEN_SUN4I
-#define SUNXI_USB0_BASE 0x01c13000
-#define SUNXI_USB1_BASE 0x01c14000
-#endif
#define SUNXI_SS_BASE 0x01c15000
#if !defined(CONFIG_MACH_SUNXI_H3_H5) && !defined(CONFIG_MACH_SUN50I)
#define SUNXI_HDMI_BASE 0x01c16000
#endif
-#define SUNXI_SPI2_BASE 0x01c17000
-#define SUNXI_SATA_BASE 0x01c18000
-#ifdef CONFIG_SUNXI_GEN_SUN4I
-#define SUNXI_PATA_BASE 0x01c19000
-#define SUNXI_ACE_BASE 0x01c1a000
-#define SUNXI_TVE1_BASE 0x01c1b000
-#define SUNXI_USB2_BASE 0x01c1c000
-#endif
-#ifdef CONFIG_SUNXI_GEN_SUN6I
-#if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I)
-#define SUNXI_USBPHY_BASE 0x01c19000
-#define SUNXI_USB0_BASE SUNXI_USBPHY_BASE
-#define SUNXI_USB1_BASE 0x01c1a000
-#define SUNXI_USB2_BASE 0x01c1b000
-#define SUNXI_USB3_BASE 0x01c1c000
-#define SUNXI_USB4_BASE 0x01c1d000
-#else
-#define SUNXI_USB0_BASE 0x01c19000
-#define SUNXI_USB1_BASE 0x01c1a000
-#define SUNXI_USB2_BASE 0x01c1b000
-#endif
-#endif
-#define SUNXI_CSI1_BASE 0x01c1d000
-#define SUNXI_TZASC_BASE 0x01c1e000
-#define SUNXI_SPI3_BASE 0x01c1f000
#define SUNXI_CCM_BASE 0x01c20000
#define SUNXI_INTC_BASE 0x01c20400
@@ -177,8 +139,6 @@
#else
#define SUNXI_TVE0_BASE 0x01e40000
#endif
-#define SUNXI_MP_BASE 0x01e80000
-#define SUNXI_AVG_BASE 0x01ea0000
#if defined(CONFIG_MACH_SUNXI_H3_H5) || defined(CONFIG_MACH_SUN50I)
#define SUNXI_HDMI_BASE 0x01ee0000
@@ -197,13 +157,6 @@
#define SUN6I_P2WI_BASE 0x01f03400
#define SUNXI_RSB_BASE 0x01f03400
-/* CoreSight Debug Module */
-#define SUNXI_CSDM_BASE 0x3f500000
-
-#define SUNXI_DDRII_DDRIII_BASE 0x40000000 /* 2 GiB */
-
-#define SUNXI_BROM_BASE 0xffff0000 /* 32 kiB */
-
#define SUNXI_CPU_CFG (SUNXI_TIMER_BASE + 0x13c)
/* SS bonding ids used for cpu identification */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index 15ee092..8a3f465 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -7,25 +7,14 @@
#ifndef _SUNXI_CPU_SUN50I_H6_H
#define _SUNXI_CPU_SUN50I_H6_H
-#define SUNXI_SRAM_A1_BASE CONFIG_SUNXI_SRAM_ADDRESS
-#define SUNXI_SRAM_C_BASE 0x00028000
-#define SUNXI_SRAM_A2_BASE 0x00100000
-
-#define SUNXI_DE3_BASE 0x01000000
-#define SUNXI_SS_BASE 0x01904000
-#define SUNXI_EMCE_BASE 0x01905000
-
#define SUNXI_SRAMC_BASE 0x03000000
#define SUNXI_CCM_BASE 0x03001000
-#define SUNXI_DMA_BASE 0x03002000
/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
#define SUNXI_SIDC_BASE 0x03006000
#define SUNXI_SID_BASE 0x03006200
#define SUNXI_TIMER_BASE 0x03009000
-#define SUNXI_PSI_BASE 0x0300C000
#define SUNXI_GIC400_BASE 0x03020000
-#define SUNXI_IOMMU_BASE 0x030F0000
#ifdef CONFIG_MACH_SUN50I_H6
#define SUNXI_DRAM_COM_BASE 0x04002000
@@ -46,18 +35,8 @@
#define SUNXI_TWI1_BASE 0x05002400
#define SUNXI_TWI2_BASE 0x05002800
#define SUNXI_TWI3_BASE 0x05002C00
-#define SUNXI_SPI0_BASE 0x05010000
-#define SUNXI_SPI1_BASE 0x05011000
-#define SUNXI_GMAC_BASE 0x05020000
-#define SUNXI_USB0_BASE 0x05100000
-#define SUNXI_XHCI_BASE 0x05200000
-#define SUNXI_USB3_BASE 0x05311000
-#define SUNXI_PCIE_BASE 0x05400000
#define SUNXI_HDMI_BASE 0x06000000
-#define SUNXI_TCON_TOP_BASE 0x06510000
-#define SUNXI_TCON_LCD0_BASE 0x06511000
-#define SUNXI_TCON_TV0_BASE 0x06515000
#define SUNXI_RTC_BASE 0x07000000
#define SUNXI_R_CPUCFG_BASE 0x07000400
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
index 2bf2675..73de470 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
@@ -20,7 +20,6 @@
/* AHB0 Module */
#define SUNXI_NFC_BASE (REGS_AHB0_BASE + 0x3000)
-#define SUNXI_TSC_BASE (REGS_AHB0_BASE + 0x4000)
#define SUNXI_GTBUS_BASE (REGS_AHB0_BASE + 0x9000)
/* SID address space starts at 0x01ce000, but e-fuse is at offset 0x200 */
@@ -32,14 +31,7 @@
#define SUNXI_MMC3_BASE (REGS_AHB0_BASE + 0x12000)
#define SUNXI_MMC_COMMON_BASE (REGS_AHB0_BASE + 0x13000)
-#define SUNXI_SPI0_BASE (REGS_AHB0_BASE + 0x1A000)
-#define SUNXI_SPI1_BASE (REGS_AHB0_BASE + 0x1B000)
-#define SUNXI_SPI2_BASE (REGS_AHB0_BASE + 0x1C000)
-#define SUNXI_SPI3_BASE (REGS_AHB0_BASE + 0x1D000)
-
#define SUNXI_GIC400_BASE (REGS_AHB0_BASE + 0x40000)
-#define SUNXI_ARMA9_GIC_BASE (REGS_AHB0_BASE + 0x41000)
-#define SUNXI_ARMA9_CPUIF_BASE (REGS_AHB0_BASE + 0x42000)
#define SUNXI_DRAM_COM_BASE (REGS_AHB0_BASE + 0x62000)
#define SUNXI_DRAM_CTL0_BASE (REGS_AHB0_BASE + 0x63000)
@@ -47,59 +39,26 @@
#define SUNXI_DRAM_PHY0_BASE (REGS_AHB0_BASE + 0x65000)
#define SUNXI_DRAM_PHY1_BASE (REGS_AHB0_BASE + 0x66000)
-/* AHB1 Module */
-#define SUNXI_DMA_BASE (REGS_AHB1_BASE + 0x002000)
-#define SUNXI_USBOTG_BASE (REGS_AHB1_BASE + 0x100000)
-#define SUNXI_USBEHCI0_BASE (REGS_AHB1_BASE + 0x200000)
-#define SUNXI_USBEHCI1_BASE (REGS_AHB1_BASE + 0x201000)
-#define SUNXI_USBEHCI2_BASE (REGS_AHB1_BASE + 0x202000)
-
-/* AHB2 Module */
-#define SUNXI_DE_SYS_BASE (REGS_AHB2_BASE + 0x000000)
-#define SUNXI_DISP_SYS_BASE (REGS_AHB2_BASE + 0x010000)
#define SUNXI_DE_FE0_BASE (REGS_AHB2_BASE + 0x100000)
-#define SUNXI_DE_FE1_BASE (REGS_AHB2_BASE + 0x140000)
-#define SUNXI_DE_FE2_BASE (REGS_AHB2_BASE + 0x180000)
-
#define SUNXI_DE_BE0_BASE (REGS_AHB2_BASE + 0x200000)
-#define SUNXI_DE_BE1_BASE (REGS_AHB2_BASE + 0x240000)
-#define SUNXI_DE_BE2_BASE (REGS_AHB2_BASE + 0x280000)
-
-#define SUNXI_DE_DEU0_BASE (REGS_AHB2_BASE + 0x300000)
-#define SUNXI_DE_DEU1_BASE (REGS_AHB2_BASE + 0x340000)
-#define SUNXI_DE_DRC0_BASE (REGS_AHB2_BASE + 0x400000)
-#define SUNXI_DE_DRC1_BASE (REGS_AHB2_BASE + 0x440000)
-
#define SUNXI_LCD0_BASE (REGS_AHB2_BASE + 0xC00000)
#define SUNXI_LCD1_BASE (REGS_AHB2_BASE + 0xC10000)
#define SUNXI_LCD2_BASE (REGS_AHB2_BASE + 0xC20000)
-#define SUNXI_MIPI_DSI0_BASE (REGS_AHB2_BASE + 0xC40000)
-/* Also seen as SUNXI_MIPI_DSI0_DPHY_BASE 0x01ca1000 */
-#define SUNXI_MIPI_DSI0_DPHY_BASE (REGS_AHB2_BASE + 0xC40100)
#define SUNXI_HDMI_BASE (REGS_AHB2_BASE + 0xD00000)
/* APB0 Module */
#define SUNXI_CCM_BASE (REGS_APB0_BASE + 0x0000)
-#define SUNXI_CCMMODULE_BASE (REGS_APB0_BASE + 0x0400)
#define SUNXI_TIMER_BASE (REGS_APB0_BASE + 0x0C00)
#define SUNXI_PWM_BASE (REGS_APB0_BASE + 0x1400)
-#define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800)
/* APB1 Module */
#define SUNXI_TWI0_BASE (REGS_APB1_BASE + 0x2800)
#define SUNXI_TWI1_BASE (REGS_APB1_BASE + 0x2C00)
-#define SUNXI_TWI2_BASE (REGS_APB1_BASE + 0x3000)
-#define SUNXI_TWI3_BASE (REGS_APB1_BASE + 0x3400)
-#define SUNXI_TWI4_BASE (REGS_APB1_BASE + 0x3800)
/* RCPUS Module */
#define SUNXI_PRCM_BASE (REGS_RCPUS_BASE + 0x1400)
#define SUNXI_RSB_BASE (REGS_RCPUS_BASE + 0x3400)
-/* Misc. */
-#define SUNXI_BROM_BASE 0xFFFF0000 /* 32K */
-#define SUNXI_CPU_CFG (SUNXI_TIMER_BASE + 0x13c)
-
#ifndef __ASSEMBLY__
void sunxi_board_init(void);
void sunxi_reset(void);
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index d5db805..f411366 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -525,19 +525,26 @@
void spl_enable_cache(void)
{
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
- phys_addr_t ram_top = CFG_SYS_SDRAM_BASE;
+ gd->ram_top = CFG_SYS_SDRAM_BASE;
+ int ret = 0;
dram_init();
/* reserve TLB table */
gd->arch.tlb_size = PGTABLE_SIZE;
- ram_top += get_effective_memsize();
+ gd->ram_top += get_effective_memsize();
/* keep ram_top in the 32-bit address space */
- if (ram_top >= 0x100000000)
- ram_top = (phys_addr_t) 0x100000000;
+ if (gd->ram_top >= 0x100000000)
+ gd->ram_top = (phys_addr_t)0x100000000;
+
+ gd->relocaddr = gd->ram_top;
+
+ ret = spl_reserve_video_from_ram_top();
+ if (ret)
+ panic("Failed to reserve framebuffer memory (%d)\n", ret);
- gd->arch.tlb_addr = ram_top - gd->arch.tlb_size;
+ gd->arch.tlb_addr = gd->relocaddr - gd->arch.tlb_size;
gd->arch.tlb_addr &= ~(0x10000 - 1);
debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
gd->arch.tlb_addr + gd->arch.tlb_size);
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index a4a8d8e..fe89aec 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -161,6 +161,23 @@
for all other SoCs, so the content of the SRAM_VER_REG becomes
irrelevant there, and we can use the same code.
+config SUNXI_BL31_BASE
+ hex
+ default 0x00044000 if MACH_SUN50I || MACH_SUN50I_H5
+ default 0x00104000 if MACH_SUN50I_H6
+ default 0x40000000 if MACH_SUN50I_H616
+ default 0x0
+ help
+ Address where BL31 (TF-A) is loaded, or zero if BL31 is not used.
+
+config SUNXI_SCP_BASE
+ hex
+ default 0x00050000 if MACH_SUN50I || MACH_SUN50I_H5
+ default 0x00114000 if MACH_SUN50I_H6
+ default 0x0
+ help
+ Address where SCP firmware is loaded, or zero if it is not used.
+
config SUNXI_A64_TIMER_ERRATUM
bool
@@ -182,7 +199,7 @@
config SUN50I_GEN_H6
bool
select FIT
- select SPL_LOAD_FIT
+ select SPL_LOAD_FIT if SPL
select MMC_SUNXI_HAS_NEW_MODE
select SUPPORT_SPL
---help---
@@ -272,7 +289,7 @@
select ARCH_SUPPORT_PSCI
select SPL_ARMV7_SET_CORTEX_SMPEN
select DRAM_SUN6I
- select SPL_I2C
+ select SPL_I2C if SPL
select SUN6I_PRCM
select SUNXI_GEN_SUN6I
select SUPPORT_SPL
@@ -300,7 +317,7 @@
select CPU_V7_HAS_VIRT
select ARCH_SUPPORT_PSCI
select DRAM_SUN8I_A23
- select SPL_I2C
+ select SPL_I2C if SPL
select SUNXI_GEN_SUN6I
select SUPPORT_SPL
select SYS_I2C_SUN8I_RSB
@@ -313,7 +330,7 @@
select CPU_V7_HAS_VIRT
select ARCH_SUPPORT_PSCI
select DRAM_SUN8I_A33
- select SPL_I2C
+ select SPL_I2C if SPL
select SUNXI_GEN_SUN6I
select SUPPORT_SPL
select SYS_I2C_SUN8I_RSB
@@ -323,7 +340,7 @@
bool "sun8i (Allwinner A83T)"
select CPU_V7A
select DRAM_SUN8I_A83T
- select SPL_I2C
+ select SPL_I2C if SPL
select SUNXI_GEN_SUN6I
select MMC_SUNXI_HAS_NEW_MODE
select MMC_SUNXI_HAS_MODE_SWITCH
@@ -382,7 +399,7 @@
select CPU_V7A
select SPL_ARMV7_SET_CORTEX_SMPEN
select DRAM_SUN9I
- select SPL_I2C
+ select SPL_I2C if SPL
select SUN6I_PRCM
select SUNXI_GEN_SUN6I
select SUPPORT_SPL
@@ -398,7 +415,7 @@
select SUNXI_DRAM_DW
select SUNXI_DRAM_DW_32BIT
select FIT
- select SPL_LOAD_FIT
+ select SPL_LOAD_FIT if SPL
select SUNXI_A64_TIMER_ERRATUM
config MACH_SUN50I_H5
@@ -407,7 +424,7 @@
select MACH_SUNXI_H3_H5
select MMC_SUNXI_HAS_NEW_MODE
select FIT
- select SPL_LOAD_FIT
+ select SPL_LOAD_FIT if SPL
config MACH_SUN50I_H6
bool "sun50i (Allwinner H6)"
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 11a4941..f4dbb2a 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -9,7 +9,6 @@
* Some init for sunxi platform.
*/
-#include <common.h>
#include <cpu_func.h>
#include <init.h>
#include <log.h>
diff --git a/arch/arm/mach-sunxi/clock.c b/arch/arm/mach-sunxi/clock.c
index da3a0eb..b6c68c9 100644
--- a/arch/arm/mach-sunxi/clock.c
+++ b/arch/arm/mach-sunxi/clock.c
@@ -7,7 +7,6 @@
* (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
*/
-#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/prcm.h>
diff --git a/arch/arm/mach-sunxi/clock_sun4i.c b/arch/arm/mach-sunxi/clock_sun4i.c
index 4716097..8f1d1b6 100644
--- a/arch/arm/mach-sunxi/clock_sun4i.c
+++ b/arch/arm/mach-sunxi/clock_sun4i.c
@@ -9,7 +9,6 @@
* (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
*/
-#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index bea91c7..dac3663 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -1,4 +1,3 @@
-#include <common.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
index 6bd75a1..aad9df2 100644
--- a/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/arch/arm/mach-sunxi/clock_sun6i.c
@@ -9,7 +9,6 @@
* (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
*/
-#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/prcm.h>
diff --git a/arch/arm/mach-sunxi/clock_sun8i_a83t.c b/arch/arm/mach-sunxi/clock_sun8i_a83t.c
index 31e4281..198fe9d 100644
--- a/arch/arm/mach-sunxi/clock_sun8i_a83t.c
+++ b/arch/arm/mach-sunxi/clock_sun8i_a83t.c
@@ -9,7 +9,6 @@
* (C) Copyright 2015 Vishnu Patekar <vishnupatekar0510@gmail.com>
*/
-#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/prcm.h>
diff --git a/arch/arm/mach-sunxi/clock_sun9i.c b/arch/arm/mach-sunxi/clock_sun9i.c
index 8ba4802..edaff9a 100644
--- a/arch/arm/mach-sunxi/clock_sun9i.c
+++ b/arch/arm/mach-sunxi/clock_sun9i.c
@@ -9,7 +9,6 @@
* Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
*/
-#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/prcm.h>
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index 7fecc3b..310dca0 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -5,7 +5,6 @@
* Tom Cubie <tangliang@allwinnertech.com>
*/
-#include <common.h>
#include <init.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
index cdf2750..4a867df 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -5,8 +5,9 @@
* (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
*/
-#include <common.h>
+#include <config.h>
#include <time.h>
+#include <vsprintf.h>
#include <asm/barriers.h>
#include <asm/io.h>
#include <asm/arch/dram.h>
diff --git a/arch/arm/mach-sunxi/dram_sun4i.c b/arch/arm/mach-sunxi/dram_sun4i.c
index 80a6c4b..2cce381 100644
--- a/arch/arm/mach-sunxi/dram_sun4i.c
+++ b/arch/arm/mach-sunxi/dram_sun4i.c
@@ -20,7 +20,6 @@
* rather undocumented and full of magic.
*/
-#include <common.h>
#include <init.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index 62bc2a0..e7862bd 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -5,7 +5,6 @@
* (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
*
*/
-#include <common.h>
#include <init.h>
#include <log.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index e62d571..37c139e 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -12,7 +12,6 @@
* (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
*
*/
-#include <common.h>
#include <init.h>
#include <log.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/dram_sun6i.c b/arch/arm/mach-sunxi/dram_sun6i.c
index 0590110..c023845 100644
--- a/arch/arm/mach-sunxi/dram_sun6i.c
+++ b/arch/arm/mach-sunxi/dram_sun6i.c
@@ -9,7 +9,6 @@
*
* (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
*/
-#include <common.h>
#include <errno.h>
#include <init.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/dram_sun8i_a23.c b/arch/arm/mach-sunxi/dram_sun8i_a23.c
index 056cb03..1c3c6d8 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_a23.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_a23.c
@@ -19,7 +19,6 @@
* This may be used as a (possible) reference for future work / cleanups.
*/
-#include <common.h>
#include <errno.h>
#include <init.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c
index 367b740..0d08b6a 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_a33.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c
@@ -7,7 +7,6 @@
* (C) Copyright 2015 Vishnu Patekar <vishnupatekar0510@gmail.com>
* (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
*/
-#include <common.h>
#include <errno.h>
#include <init.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/dram_sun8i_a83t.c b/arch/arm/mach-sunxi/dram_sun8i_a83t.c
index a3f833d..ef83332 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_a83t.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_a83t.c
@@ -7,7 +7,6 @@
* (C) Copyright 2015 Vishnu Patekar <vishnupatekar0510@gmail.com>
* (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
*/
-#include <common.h>
#include <errno.h>
#include <init.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/dram_sun9i.c b/arch/arm/mach-sunxi/dram_sun9i.c
index 14be212..002b6df 100644
--- a/arch/arm/mach-sunxi/dram_sun9i.c
+++ b/arch/arm/mach-sunxi/dram_sun9i.c
@@ -10,7 +10,6 @@
* Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
*/
-#include <common.h>
#include <dm.h>
#include <errno.h>
#include <init.h>
diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c
index 9e583e1..640f872 100644
--- a/arch/arm/mach-sunxi/dram_suniv.c
+++ b/arch/arm/mach-sunxi/dram_suniv.c
@@ -9,7 +9,7 @@
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
*/
-#include <common.h>
+#include <config.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/dram.h>
diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c
index daef051..3bfcc63 100644
--- a/arch/arm/mach-sunxi/dram_sunxi_dw.c
+++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c
@@ -8,7 +8,6 @@
* (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
* (C) Copyright 2015 Jens Kuske <jenskuske@gmail.com>
*/
-#include <common.h>
#include <init.h>
#include <log.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-sunxi/gtbus_sun9i.c b/arch/arm/mach-sunxi/gtbus_sun9i.c
index 5624621..a058fea 100644
--- a/arch/arm/mach-sunxi/gtbus_sun9i.c
+++ b/arch/arm/mach-sunxi/gtbus_sun9i.c
@@ -6,7 +6,6 @@
* Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
*/
-#include <common.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/gtbus_sun9i.h>
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
index 8e7625f..87df312 100644
--- a/arch/arm/mach-sunxi/pmic_bus.c
+++ b/arch/arm/mach-sunxi/pmic_bus.c
@@ -9,7 +9,6 @@
*/
#include <axp_pmic.h>
-#include <common.h>
#include <dm.h>
#include <asm/arch/p2wi.h>
#include <asm/arch/rsb.h>
diff --git a/arch/arm/mach-sunxi/prcm.c b/arch/arm/mach-sunxi/prcm.c
index 71a2e44..ef7c46e 100644
--- a/arch/arm/mach-sunxi/prcm.c
+++ b/arch/arm/mach-sunxi/prcm.c
@@ -13,7 +13,6 @@
* Tom Cubie <tangliang@allwinnertech.com>
*/
-#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
index 267cb0b..72faa71 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -3,7 +3,6 @@
* Copyright (C) 2016 Siarhei Siamashka <siarhei.siamashka@gmail.com>
*/
-#include <common.h>
#include <image.h>
#include <log.h>
#include <spl.h>
diff --git a/arch/arm/mach-sunxi/timer.c b/arch/arm/mach-sunxi/timer.c
index 9a6f6c0..1bbfad5 100644
--- a/arch/arm/mach-sunxi/timer.c
+++ b/arch/arm/mach-sunxi/timer.c
@@ -5,7 +5,6 @@
* Tom Cubie <tangliang@allwinnertech.com>
*/
-#include <common.h>
#include <init.h>
#include <time.h>
#include <asm/global_data.h>
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index f556857..a2da6a4 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -348,6 +348,11 @@
S: Maintained
F: configs/libretech_all_h5_cc_h5_defconfig
+NANOPI DUO2 BOARD
+M: Chuanhong Guo <gch981213@gmail.com>
+S: Maintained
+F: configs/nanopi_duo2_defconfig
+
NANOPI-M1 BOARD
M: Mylène Josserand <mylene.josserand@free-electrons.com>
S: Maintained
@@ -550,6 +555,11 @@
S: Maintained
F: configs/tbs_a711_defconfig
+TRANSPEED 8K618-T BOARD
+M: Nick Alilovic <nickalilovic@gmail.com>
+S: Maintained
+F: configs/transpeed-8k618-t_defconfig
+
WEXLER-TAB7200 BOARD
M: Aleksei Mamlin <mamlinav@gmail.com>
S: Maintained
diff --git a/board/ti/am62x/evm.c b/board/ti/am62x/evm.c
index ad93908..88e0215 100644
--- a/board/ti/am62x/evm.c
+++ b/board/ti/am62x/evm.c
@@ -60,27 +60,9 @@
}
#if defined(CONFIG_SPL_BUILD)
-static int video_setup(void)
-{
- if (CONFIG_IS_ENABLED(VIDEO)) {
- ulong addr;
- int ret;
-
- addr = gd->relocaddr;
- ret = video_reserve(&addr);
- if (ret)
- return ret;
- debug("Reserving %luk for video at: %08lx\n",
- ((unsigned long)gd->relocaddr - addr) >> 10, addr);
- gd->relocaddr = addr;
- }
-
- return 0;
-}
void spl_board_init(void)
{
- video_setup();
enable_caches();
if (IS_ENABLED(CONFIG_SPL_SPLASH_SCREEN) && IS_ENABLED(CONFIG_SPL_BMP))
splash_display();
diff --git a/common/board_f.c b/common/board_f.c
index d4d7d01..442b834 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -403,17 +403,47 @@
return 0;
}
-static int reserve_video(void)
+static int reserve_video_from_videoblob(void)
{
if (IS_ENABLED(CONFIG_SPL_VIDEO_HANDOFF) && spl_phase() > PHASE_SPL) {
struct video_handoff *ho;
+ int ret = 0;
ho = bloblist_find(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho));
if (!ho)
- return log_msg_ret("blf", -ENOENT);
- video_reserve_from_bloblist(ho);
- gd->relocaddr = ho->fb;
- } else if (CONFIG_IS_ENABLED(VIDEO)) {
+ return log_msg_ret("Missing video bloblist", -ENOENT);
+
+ ret = video_reserve_from_bloblist(ho);
+ if (ret)
+ return log_msg_ret("Invalid Video handoff info", ret);
+
+ /* Sanity check fb from blob is before current relocaddr */
+ if (likely(gd->relocaddr > (unsigned long)ho->fb))
+ gd->relocaddr = ho->fb;
+ }
+
+ return 0;
+}
+
+/*
+ * Check if any bloblist received specifying reserved areas from previous stage and adjust
+ * gd->relocaddr accordingly, so that we start reserving after pre-reserved areas
+ * from previous stage.
+ *
+ * NOTE:
+ * IT is recommended that all bloblists from previous stage are reserved from ram_top
+ * as next stage will simply start reserving further regions after them.
+ */
+static int setup_relocaddr_from_bloblist(void)
+{
+ reserve_video_from_videoblob();
+
+ return 0;
+}
+
+static int reserve_video(void)
+{
+ if (CONFIG_IS_ENABLED(VIDEO)) {
ulong addr;
int ret;
@@ -923,6 +953,7 @@
reserve_pram,
#endif
reserve_round_4k,
+ setup_relocaddr_from_bloblist,
arch_reserve_mmu,
reserve_video,
reserve_trace,
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index e7b84fc..6a4772e 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -97,8 +97,7 @@
default 0x31000 if ARCH_MX6 && MX6_OCRAM_256KB
default 0x11000 if ARCH_MX7 || (ARCH_MX6 && !MX6_OCRAM_256KB)
default 0x10000 if ARCH_KEYSTONE
- default 0x8000 if ARCH_SUNXI && !MACH_SUN50I_H616
- default 0x0 if ARCH_MTMIPS
+ default 0x0 if ARCH_MTMIPS || ARCH_SUNXI
default TPL_MAX_SIZE if TPL_MAX_SIZE > SPL_MAX_SIZE
default SPL_MAX_SIZE
help
@@ -585,8 +584,7 @@
config SPL_FIT_IMAGE_TINY
bool "Remove functionality from SPL FIT loading to reduce size"
depends on SPL_FIT
- default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6
- default y if ARCH_IMX8M || ARCH_IMX9
+ default y if ARCH_IMX8M || ARCH_IMX9 || ARCH_SUNXI
help
Enable this to reduce the size of the FIT image loading code
in SPL, if space for the SPL binary is very tight.
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 3ce5bfe..b65c439 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -42,6 +42,7 @@
#include <fdt_support.h>
#include <bootcount.h>
#include <wdt.h>
+#include <video.h>
DECLARE_GLOBAL_DATA_PTR;
DECLARE_BINMAN_MAGIC_SYM;
@@ -152,6 +153,24 @@
#endif
}
+int spl_reserve_video_from_ram_top(void)
+{
+ if (CONFIG_IS_ENABLED(VIDEO)) {
+ ulong addr;
+ int ret;
+
+ addr = gd->ram_top;
+ ret = video_reserve(&addr);
+ if (ret)
+ return ret;
+ debug("Reserving %luk for video at: %08lx\n",
+ ((unsigned long)gd->relocaddr - addr) >> 10, addr);
+ gd->relocaddr = addr;
+ }
+
+ return 0;
+}
+
ulong spl_get_image_pos(void)
{
if (!CONFIG_IS_ENABLED(BINMAN_UBOOT_SYMBOLS))
diff --git a/common/splash_source.c b/common/splash_source.c
index 7223a1a..2ce0768 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -216,7 +216,7 @@
}
}
-#ifdef CONFIG_CMD_UBIFS
+#if defined(CONFIG_CMD_UBIFS) && !defined(CONFIG_SPL_BUILD)
static int splash_mount_ubifs(struct splash_location *location)
{
int res;
diff --git a/configs/nanopi_duo2_defconfig b/configs/nanopi_duo2_defconfig
new file mode 100644
index 0000000..beb2f92
--- /dev/null
+++ b/configs/nanopi_duo2_defconfig
@@ -0,0 +1,12 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-duo2"
+CONFIG_SPL=y
+CONFIG_MACH_SUN8I_H3=y
+CONFIG_DRAM_CLK=408
+# CONFIG_VIDEO_DE2 is not set
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_CONSOLE_MUX=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_MUSB_GADGET=y
diff --git a/configs/transpeed-8k618-t_defconfig b/configs/transpeed-8k618-t_defconfig
new file mode 100644
index 0000000..020d397
--- /dev/null
+++ b/configs/transpeed-8k618-t_defconfig
@@ -0,0 +1,27 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-h618-transpeed-8k618-t"
+CONFIG_SPL=y
+CONFIG_DRAM_SUN50I_H616_DX_ODT=0x03030303
+CONFIG_DRAM_SUN50I_H616_DX_DRI=0x0e0e0e0e
+CONFIG_DRAM_SUN50I_H616_CA_DRI=0x1f12
+CONFIG_DRAM_SUN50I_H616_TPR0=0xc0001002
+CONFIG_DRAM_SUN50I_H616_TPR10=0x2f1107
+CONFIG_DRAM_SUN50I_H616_TPR11=0xddddcccc
+CONFIG_DRAM_SUN50I_H616_TPR12=0xeddc7665
+CONFIG_MACH_SUN50I_H616=y
+CONFIG_SUNXI_DRAM_H616_DDR3_1333=y
+CONFIG_DRAM_CLK=648
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_R_I2C_ENABLE=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_I2C=y
+CONFIG_SPL_SYS_I2C_LEGACY=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_SYS_I2C_SLAVE=0x7f
+CONFIG_SYS_I2C_SPEED=400000
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_AXP313_POWER=y
+CONFIG_AXP_DCDC3_VOLT=1360
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
diff --git a/doc/develop/spl.rst b/doc/develop/spl.rst
index 76e87f0..0a3e572 100644
--- a/doc/develop/spl.rst
+++ b/doc/develop/spl.rst
@@ -65,6 +65,15 @@
CONFIG_SPL_SPI_LOAD (drivers/mtd/spi/spi_spl_load.o)
CONFIG_SPL_RAM_DEVICE (common/spl/spl.c)
CONFIG_SPL_WATCHDOG (drivers/watchdog/libwatchdog.o)
+CONFIG_SPL_SYSCON (drivers/core/syscon-uclass.o)
+CONFIG_SPL_GZIP (lib/gzip.o)
+CONFIG_SPL_VIDEO (drivers/video/video-uclass.o drivers/video/vidconsole-uclass.o)
+CONFIG_SPL_SPLASH_SCREEN (common/splash.o)
+CONFIG_SPL_SPLASH_SOURCE (common/splash_source.o)
+CONFIG_SPL_GPIO (drivers/gpio)
+CONFIG_SPL_DM_GPIO (drivers/gpio/gpio-uclass.o)
+CONFIG_SPL_BMP (drivers/video/bmp.o)
+CONFIG_SPL_BLOBLIST (common/bloblist.o)
Adding SPL-specific code
------------------------
@@ -164,3 +173,31 @@
the config files and picks functions based on #ifdef. Parsing the '.i'
files instead introduces another set of headaches. These warnings are
not usually important to understanding the flow, however.
+
+
+Reserving memory in SPL
+-----------------------
+
+If memory needs to be reserved in RAM during SPL stage with the requirement that
+the SPL reserved memory remains preserved across further boot stages too
+then it needs to be reserved mandatorily starting from end of RAM. This is to
+ensure that further stages can simply skip this region before carrying out
+further reservations or updating the relocation address.
+
+Also out of these regions which are to be preserved across further stages of
+boot, video framebuffer memory region must be reserved first starting from
+end of RAM for which helper function spl_reserve_video_from_ram_top is provided
+which makes sure that video memory is placed at top of reservation area with
+further reservations below it.
+
+The corresponding information of reservation for those regions can be passed to
+further boot stages using a bloblist. For e.g. the information for
+framebuffer area reserved by SPL can be passed onto U-boot using
+BLOBLISTT_U_BOOT_VIDEO.
+
+The further boot stages need to parse each of the bloblist passed from SPL stage
+starting from video bloblist and skip this whole SPL reserved memory area from
+end of RAM as per the bloblists received, before carrying out further
+reservations or updating the relocation address. For e.g, U-boot proper uses
+function "setup_relocaddr_from_bloblist" to parse the bloblists passed from
+previous stage and skip the memory reserved from previous stage accordingly.
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 3f5f3c8..f86003c 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -331,18 +331,42 @@
u8 *val)
{
struct spi_mem_op op =
- SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDAR, 1),
- SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1),
- SPI_MEM_OP_DUMMY(dummy / 8, 1),
- SPI_MEM_OP_DATA_IN(1, NULL, 1));
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0),
+ SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 0),
+ SPI_MEM_OP_DUMMY(dummy, 0),
+ SPI_MEM_OP_DATA_IN(1, NULL, 0));
+ u8 buf[2];
+ int ret;
+
+ spi_nor_setup_op(nor, &op, nor->reg_proto);
- return spi_nor_read_write_reg(nor, &op, val);
+ /*
+ * In Octal DTR mode, the number of address bytes is always 4 regardless
+ * of addressing mode setting.
+ */
+ if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR)
+ op.addr.nbytes = 4;
+
+ /*
+ * We don't want to read only one byte in DTR mode. So, read 2 and then
+ * discard the second byte.
+ */
+ if (spi_nor_protocol_is_dtr(nor->reg_proto))
+ op.data.nbytes = 2;
+
+ ret = spi_nor_read_write_reg(nor, &op, buf);
+ if (ret)
+ return ret;
+
+ *val = buf[0];
+
+ return 0;
}
static int spansion_write_any_reg(struct spi_nor *nor, u32 addr, u8 val)
{
struct spi_mem_op op =
- SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRAR, 1),
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
SPI_MEM_OP_ADDR(nor->addr_mode_nbytes, addr, 1),
SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_DATA_OUT(1, NULL, 1));
@@ -714,7 +738,7 @@
*/
static int spansion_sr_ready(struct spi_nor *nor, u32 addr_base, u8 dummy)
{
- u32 reg_addr = addr_base + SPINOR_REG_ADDR_STR1V;
+ u32 reg_addr = addr_base + SPINOR_REG_CYPRESS_STR1V;
u8 sr;
int ret;
@@ -728,7 +752,7 @@
else
dev_dbg(nor->dev, "Programming Error occurred\n");
- nor->write_reg(nor, SPINOR_OP_CLSR, NULL, 0);
+ nor->write_reg(nor, SPINOR_OP_CYPRESS_CLPEF, NULL, 0);
return -EIO;
}
@@ -1856,7 +1880,7 @@
static int spansion_quad_enable_volatile(struct spi_nor *nor, u32 addr_base,
u8 dummy)
{
- u32 addr = addr_base + SPINOR_REG_ADDR_CFR1V;
+ u32 addr = addr_base + SPINOR_REG_CYPRESS_CFR1V;
u8 cr;
int ret;
@@ -3293,11 +3317,11 @@
* Read CR3V to check if uniform sector is selected. If not, assign an
* erase hook that supports non-uniform erase.
*/
- ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V,
+ ret = spansion_read_any_reg(nor, SPINOR_REG_CYPRESS_CFR3V,
S25FS_S_RDAR_DUMMY, &cfr3v);
if (ret)
return ret;
- if (!(cfr3v & CFR3V_UNHYSA))
+ if (!(cfr3v & SPINOR_REG_CYPRESS_CFR3_UNISECT))
nor->erase = s25fs_s_erase_non_uniform;
return spi_nor_default_setup(nor, info, params);
@@ -3346,13 +3370,13 @@
.post_sfdp = s25fs_s_post_sfdp_fixup,
};
-static int s25_mdp_ready(struct spi_nor *nor)
+static int s25_s28_mdp_ready(struct spi_nor *nor)
{
u32 addr;
int ret;
for (addr = 0; addr < nor->mtd.size; addr += SZ_128M) {
- ret = spansion_sr_ready(nor, addr, 0);
+ ret = spansion_sr_ready(nor, addr, nor->rdsr_dummy);
if (!ret)
return ret;
}
@@ -3374,15 +3398,15 @@
return 0;
}
-static int s25_erase_non_uniform(struct spi_nor *nor, loff_t addr)
+static int s25_s28_erase_non_uniform(struct spi_nor *nor, loff_t addr)
{
/* Support 32 x 4KB sectors at bottom */
return spansion_erase_non_uniform(nor, addr, SPINOR_OP_BE_4K_4B, 0,
SZ_128K);
}
-static int s25_setup(struct spi_nor *nor, const struct flash_info *info,
- const struct spi_nor_flash_parameter *params)
+static int s25_s28_setup(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params)
{
int ret;
u8 cr;
@@ -3396,7 +3420,8 @@
* uniform 128KB only due to complexity of non-uniform layout.
*/
if (nor->info->id[4] == S25FS256T_ID4) {
- ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_ARCFN, 8, &cr);
+ ret = spansion_read_any_reg(nor, SPINOR_REG_CYPRESS_ARCFN, 8,
+ &cr);
if (ret)
return ret;
@@ -3410,31 +3435,31 @@
* Read CFR3V to check if uniform sector is selected. If not, assign an
* erase hook that supports non-uniform erase.
*/
- ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V, 0, &cr);
+ ret = spansion_read_any_reg(nor, SPINOR_REG_CYPRESS_CFR3V, 0, &cr);
if (ret)
return ret;
- if (!(cr & CFR3V_UNHYSA))
- nor->erase = s25_erase_non_uniform;
+ if (!(cr & SPINOR_REG_CYPRESS_CFR3_UNISECT))
+ nor->erase = s25_s28_erase_non_uniform;
/*
* For the multi-die package parts, the ready() hook is needed to check
* all dies' status via read any register.
*/
if (nor->mtd.size > SZ_128M)
- nor->ready = s25_mdp_ready;
+ nor->ready = s25_s28_mdp_ready;
return spi_nor_default_setup(nor, info, params);
}
static void s25_default_init(struct spi_nor *nor)
{
- nor->setup = s25_setup;
+ nor->setup = s25_s28_setup;
}
-static int s25_post_bfpt_fixup(struct spi_nor *nor,
- const struct sfdp_parameter_header *header,
- const struct sfdp_bfpt *bfpt,
- struct spi_nor_flash_parameter *params)
+static int s25_s28_post_bfpt_fixup(struct spi_nor *nor,
+ const struct sfdp_parameter_header *header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params)
{
int ret;
u32 addr;
@@ -3474,12 +3499,13 @@
* dies are configured to 512B buffer.
*/
for (addr = 0; addr < params->size; addr += SZ_128M) {
- ret = spansion_read_any_reg(nor, addr + SPINOR_REG_ADDR_CFR3V,
- 0, &cfr3v);
+ ret = spansion_read_any_reg(nor,
+ addr + SPINOR_REG_CYPRESS_CFR3V, 0,
+ &cfr3v);
if (ret)
return ret;
- if (!(cfr3v & CFR3V_PGMBUF)) {
+ if (!(cfr3v & SPINOR_REG_CYPRESS_CFR3_PGSZ)) {
params->page_size = 256;
return 0;
}
@@ -3507,7 +3533,7 @@
static struct spi_nor_fixups s25_fixups = {
.default_init = s25_default_init,
- .post_bfpt = s25_post_bfpt_fixup,
+ .post_bfpt = s25_s28_post_bfpt_fixup,
.post_sfdp = s25_post_sfdp_fixup,
};
@@ -3539,97 +3565,57 @@
*/
static int spi_nor_cypress_octal_dtr_enable(struct spi_nor *nor)
{
- struct spi_mem_op op;
+ u32 addr;
u8 buf;
- u8 addr_width = 3;
int ret;
- /* Use 24 dummy cycles for memory array reads. */
ret = write_enable(nor);
if (ret)
return ret;
- buf = SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24;
- op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
- SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR2V, 1),
- SPI_MEM_OP_NO_DUMMY,
- SPI_MEM_OP_DATA_OUT(1, &buf, 1));
- ret = spi_mem_exec_op(nor->spi, &op);
- if (ret) {
- dev_warn(nor->dev,
- "failed to set default memory latency value: %d\n",
- ret);
- return ret;
- }
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- return ret;
+ /* Use 24 dummy cycles for memory array reads. */
+ for (addr = 0; addr < nor->mtd.size; addr += SZ_128M) {
+ ret = spansion_read_any_reg(nor,
+ addr + SPINOR_REG_CYPRESS_CFR2V, 0,
+ &buf);
+ if (ret)
+ return ret;
+ buf &= ~SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK;
+ buf |= SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24;
+ ret = spansion_write_any_reg(nor,
+ addr + SPINOR_REG_CYPRESS_CFR2V,
+ buf);
+ if (ret) {
+ dev_warn(nor->dev, "failed to set default memory latency value: %d\n", ret);
+ return ret;
+ }
+ }
nor->read_dummy = 24;
- /* Set the octal and DTR enable bits. */
ret = write_enable(nor);
if (ret)
return ret;
+ /* Set the octal and DTR enable bits. */
buf = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN;
- op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
- SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR5V, 1),
- SPI_MEM_OP_NO_DUMMY,
- SPI_MEM_OP_DATA_OUT(1, &buf, 1));
- ret = spi_mem_exec_op(nor->spi, &op);
- if (ret) {
- dev_warn(nor->dev, "Failed to enable octal DTR mode\n");
- return ret;
+ for (addr = 0; addr < nor->mtd.size; addr += SZ_128M) {
+ ret = spansion_write_any_reg(nor,
+ addr + SPINOR_REG_CYPRESS_CFR5V,
+ buf);
+ if (ret) {
+ dev_warn(nor->dev, "Failed to enable octal DTR mode\n");
+ return ret;
+ }
}
return 0;
}
-static int s28hx_t_erase_non_uniform(struct spi_nor *nor, loff_t addr)
-{
- /* Factory default configuration: 32 x 4 KiB sectors at bottom. */
- return spansion_erase_non_uniform(nor, addr, SPINOR_OP_S28_SE_4K,
- 0, SZ_128K);
-}
-
-static int s28hx_t_setup(struct spi_nor *nor, const struct flash_info *info,
- const struct spi_nor_flash_parameter *params)
-{
- struct spi_mem_op op;
- u8 buf;
- u8 addr_width = 3;
- int ret;
-
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- return ret;
-
- /*
- * Check CFR3V to check if non-uniform sector mode is selected. If it
- * is, set the erase hook to the non-uniform erase procedure.
- */
- op = (struct spi_mem_op)
- SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1),
- SPI_MEM_OP_ADDR(addr_width,
- SPINOR_REG_CYPRESS_CFR3V, 1),
- SPI_MEM_OP_NO_DUMMY,
- SPI_MEM_OP_DATA_IN(1, &buf, 1));
-
- ret = spi_mem_exec_op(nor->spi, &op);
- if (ret)
- return ret;
-
- if (!(buf & SPINOR_REG_CYPRESS_CFR3_UNISECT))
- nor->erase = s28hx_t_erase_non_uniform;
-
- return spi_nor_default_setup(nor, info, params);
-}
-
static void s28hx_t_default_init(struct spi_nor *nor)
{
nor->octal_dtr_enable = spi_nor_cypress_octal_dtr_enable;
- nor->setup = s28hx_t_setup;
+ nor->setup = s25_s28_setup;
}
static void s28hx_t_post_sfdp_fixup(struct spi_nor *nor,
@@ -3663,50 +3649,10 @@
params->rdsr_addr_nbytes = 4;
}
-static int s28hx_t_post_bfpt_fixup(struct spi_nor *nor,
- const struct sfdp_parameter_header *bfpt_header,
- const struct sfdp_bfpt *bfpt,
- struct spi_nor_flash_parameter *params)
-{
- struct spi_mem_op op;
- u8 buf;
- u8 addr_width = 3;
- int ret;
-
- /*
- * The BFPT table advertises a 512B page size but the page size is
- * actually configurable (with the default being 256B). Read from
- * CFR3V[4] and set the correct size.
- */
- op = (struct spi_mem_op)
- SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1),
- SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR3V, 1),
- SPI_MEM_OP_NO_DUMMY,
- SPI_MEM_OP_DATA_IN(1, &buf, 1));
- ret = spi_mem_exec_op(nor->spi, &op);
- if (ret)
- return ret;
-
- if (buf & SPINOR_REG_CYPRESS_CFR3_PGSZ)
- params->page_size = 512;
- else
- params->page_size = 256;
-
- /*
- * The BFPT advertises that it supports 4k erases, and the datasheet
- * says the same. But 4k erases did not work when testing. So, use 256k
- * erases for now.
- */
- nor->erase_opcode = SPINOR_OP_SE_4B;
- nor->mtd.erasesize = 0x40000;
-
- return 0;
-}
-
static struct spi_nor_fixups s28hx_t_fixups = {
.default_init = s28hx_t_default_init,
.post_sfdp = s28hx_t_post_sfdp_fixup,
- .post_bfpt = s28hx_t_post_bfpt_fixup,
+ .post_bfpt = s25_s28_post_bfpt_fixup,
};
#endif /* CONFIG_SPI_FLASH_S28HX_T */
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 8db522f..38a2874 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -239,6 +239,8 @@
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ INFO("is25wx256", 0x9d5b19, 0, 128 * 1024, 256,
SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("is25lx512", 0x9d5a1a, 0, 64 * 1024, 1024,
+ SECT_4K | USE_FSR | SPI_NOR_4B_OPCODES | SPI_NOR_HAS_TB) },
#endif
#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
/* Macronix */
@@ -381,6 +383,7 @@
{ INFO("s28hl01gt", 0x345a1b, 0, 256 * 1024, 512, SPI_NOR_OCTAL_DTR_READ) },
{ INFO("s28hs512t", 0x345b1a, 0, 256 * 1024, 256, SPI_NOR_OCTAL_DTR_READ) },
{ INFO("s28hs01gt", 0x345b1b, 0, 256 * 1024, 512, SPI_NOR_OCTAL_DTR_READ) },
+ { INFO("s28hs02gt", 0x345b1c, 0, 256 * 1024, 1024, SPI_NOR_OCTAL_DTR_READ) },
#endif
#endif
#ifdef CONFIG_SPI_FLASH_SST /* SST */
@@ -554,6 +557,10 @@
{ INFO("XM25QH64C", 0x204017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ INFO("XM25QH128A", 0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ INFO("XM25QU128C", 0x204118, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { INFO("XM25QH256C", 0x204019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("XM25QU256C", 0x204119, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("XM25QH512C", 0x204020, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("XM25QU512C", 0x204120, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
#endif
#ifdef CONFIG_SPI_FLASH_XTX
/* XTX Technology Limited */
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index a12f7e3..8bff4fe 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -833,11 +833,8 @@
priv->use_internal_phy = false;
offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
- if (offset < 0) {
- debug("%s: Cannot find PHY address\n", __func__);
- return -EINVAL;
- }
- priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
+ if (offset >= 0)
+ priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
pdata->phy_interface = dev_read_phy_mode(dev);
debug("phy interface %d\n", pdata->phy_interface);
diff --git a/drivers/spi/cadence_ospi_versal.c b/drivers/spi/cadence_ospi_versal.c
index e02a3b3..c2be307 100644
--- a/drivers/spi/cadence_ospi_versal.c
+++ b/drivers/spi/cadence_ospi_versal.c
@@ -18,9 +18,6 @@
#include "cadence_qspi.h"
#include <dt-bindings/power/xlnx-versal-power.h>
-#define CMD_4BYTE_READ 0x13
-#define CMD_4BYTE_FAST_READ 0x0C
-
int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
const struct spi_mem_op *op)
{
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 12825f8..693474a 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -33,6 +33,10 @@
#define CQSPI_DUMMY_BYTES_MAX 4
#define CQSPI_DUMMY_CLKS_MAX 31
+#define CMD_4BYTE_FAST_READ 0x0C
+#define CMD_4BYTE_OCTAL_READ 0x7c
+#define CMD_4BYTE_READ 0x13
+
/****************************************************************************
* Controller's configuration and status register (offset from QSPI_BASE)
****************************************************************************/
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index d033184..fb90532 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -469,6 +469,9 @@
else
opcode = op->cmd.opcode;
+ if (opcode == CMD_4BYTE_OCTAL_READ && !priv->dtr)
+ opcode = CMD_4BYTE_FAST_READ;
+
reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
/* Set up dummy cycles. */
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 1c7d0ca..98908c5 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -111,6 +111,9 @@
#define SR_TX_ERR BIT(5)
#define SR_DCOL BIT(6)
+/* Bit field in RISR */
+#define RISR_INT_RXOI BIT(3)
+
#define RX_TIMEOUT 1000 /* timeout in ms */
struct dw_spi_plat {
@@ -588,7 +591,7 @@
struct dw_spi_priv *priv = dev_get_priv(bus);
u8 op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
u8 op_buf[op_len];
- u32 cr0;
+ u32 cr0, sts;
if (read)
priv->tmode = CTRLR0_TMOD_EPROMREAD;
@@ -632,12 +635,21 @@
* them to fail because we are not reading/writing the fifo fast enough.
*/
if (read) {
- priv->rx = op->data.buf.in;
+ void *prev_rx = priv->rx = op->data.buf.in;
priv->rx_end = priv->rx + op->data.nbytes;
dw_write(priv, DW_SPI_SER, 1 << spi_chip_select(slave->dev));
- while (priv->rx != priv->rx_end)
+ while (priv->rx != priv->rx_end) {
dw_reader(priv);
+ if (prev_rx == priv->rx) {
+ sts = dw_read(priv, DW_SPI_RISR);
+ if (sts & RISR_INT_RXOI) {
+ dev_err(bus, "FIFO overflow on Rx\n");
+ return -EIO;
+ }
+ }
+ prev_rx = priv->rx;
+ }
} else {
u32 val;
diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c
index d17764d..9393636 100644
--- a/drivers/video/console_core.c
+++ b/drivers/video/console_core.c
@@ -225,7 +225,7 @@
{
info->name = fonts[seq].name;
- return 0;
+ return info->name ? 0 : -ENOENT;
}
int console_simple_select_font(struct udevice *dev, const char *name, uint size)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 14fb81e..547e5a8 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -397,7 +397,10 @@
if (vid_priv->colour_bg)
val = 255 - val;
- out = val | val << 8 | val << 16;
+ if (vid_priv->format == VIDEO_X2R10G10B10)
+ out = val << 2 | val << 12 | val << 22;
+ else
+ out = val | val << 8 | val << 16;
if (vid_priv->colour_fg)
*dst++ |= out;
else
@@ -911,7 +914,10 @@
for (i = 0; i < width; i++) {
int out;
- out = val | val << 8 | val << 16;
+ if (vid_priv->format == VIDEO_X2R10G10B10)
+ out = val << 2 | val << 12 | val << 22;
+ else
+ out = val | val << 8 | val << 16;
if (vid_priv->colour_fg)
*dst++ |= out;
else
diff --git a/drivers/video/tidss/tidss_drv.c b/drivers/video/tidss/tidss_drv.c
index e285f25..1380c6b 100644
--- a/drivers/video/tidss/tidss_drv.c
+++ b/drivers/video/tidss/tidss_drv.c
@@ -107,7 +107,7 @@
.num_planes = 2,
/* note: vid is plane_id 0 and vidl1 is plane_id 1 */
- .vid_name = { "vidl1", "vid1" },
+ .vid_name = { "vidl1", "vid" },
.vid_lite = { true, false },
.vid_order = { 1, 0 },
};
@@ -814,13 +814,13 @@
priv->bus_format = &dss_bus_formats[8];
/* Common address */
- priv->base_common = dev_remap_addr_index(dev, 0);
+ priv->base_common = dev_remap_addr_name(dev, priv->feat->common);
if (!priv->base_common)
return -EINVAL;
/* plane address setup and enable */
for (i = 0; i < priv->feat->num_planes; i++) {
- priv->base_vid[i] = dev_remap_addr_index(dev, i + 2);
+ priv->base_vid[i] = dev_remap_addr_name(dev, priv->feat->vid_name[i]);
if (!priv->base_vid[i])
return -EINVAL;
}
@@ -841,8 +841,8 @@
/* video port address clocks and enable */
for (i = 0; i < priv->feat->num_vps; i++) {
- priv->base_ovr[i] = dev_remap_addr_index(dev, i + 4);
- priv->base_vp[i] = dev_remap_addr_index(dev, i + 6);
+ priv->base_ovr[i] = dev_remap_addr_name(dev, priv->feat->ovr_name[i]);
+ priv->base_vp[i] = dev_remap_addr_name(dev, priv->feat->vp_name[i]);
}
ret = clk_get_by_name(dev, "vp1", &priv->vp_clk[0]);
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index f743ed7..3571e62 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -123,6 +123,9 @@
struct udevice *dev;
ulong size;
+ if (IS_ENABLED(CONFIG_SPL_VIDEO_HANDOFF) && spl_phase() == PHASE_BOARD_F)
+ return 0;
+
gd->video_top = *addrp;
for (uclass_find_first_device(UCLASS_VIDEO, &dev);
dev;
@@ -141,16 +144,6 @@
debug("Video frame buffers from %lx to %lx\n", gd->video_bottom,
gd->video_top);
- if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(VIDEO_HANDOFF)) {
- struct video_handoff *ho;
-
- ho = bloblist_add(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho), 0);
- if (!ho)
- return log_msg_ret("blf", -ENOENT);
- ho->fb = *addrp;
- ho->size = size;
- }
-
return 0;
}
@@ -208,11 +201,14 @@
int video_reserve_from_bloblist(struct video_handoff *ho)
{
+ if (!ho->fb || ho->size == 0)
+ return -ENOENT;
+
gd->video_bottom = ho->fb;
gd->fb_base = ho->fb;
gd->video_top = ho->fb + ho->size;
- debug("Reserving %luk for video using blob at: %08x\n",
- ((unsigned long)ho->size) >> 10, (u32)ho->fb);
+ debug("%s: Reserving %lx bytes at %08x as per bloblist received\n",
+ __func__, (unsigned long)ho->size, (u32)ho->fb);
return 0;
}
@@ -546,6 +542,26 @@
priv->fb_size = priv->line_length * priv->ysize;
+ /*
+ * Set up video handoff fields for passing video blob to next stage
+ * NOTE:
+ * This assumes that reserved video memory only uses a single framebuffer
+ */
+ if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(BLOBLIST)) {
+ struct video_handoff *ho;
+
+ ho = bloblist_add(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho), 0);
+ if (!ho)
+ return log_msg_ret("blf", -ENOENT);
+ ho->fb = gd->video_bottom;
+ /* Fill aligned size here as calculated in video_reserve() */
+ ho->size = gd->video_top - gd->video_bottom;
+ ho->xsize = priv->xsize;
+ ho->ysize = priv->ysize;
+ ho->line_length = priv->line_length;
+ ho->bpix = priv->bpix;
+ }
+
if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base)
priv->copy_fb = map_sysmem(plat->copy_base, plat->size);
diff --git a/env/sf.c b/env/sf.c
index a425ecc..8f5c03b 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -210,8 +210,10 @@
saved_size = sect_size - CONFIG_ENV_SIZE;
saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
saved_buffer = malloc(saved_size);
- if (!saved_buffer)
+ if (!saved_buffer) {
+ ret = -ENOMEM;
goto done;
+ }
ret = spi_flash_read(env_flash, saved_offset,
saved_size, saved_buffer);
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index b8ca77d..b29a25d 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -14,8 +14,9 @@
#include <linux/stringify.h>
-/* Serial & console */
-/* ns16550 reg in the low bits of cpu reg */
+/****************************************************************************
+ * base addresses for the SPL UART driver *
+ ****************************************************************************/
#ifdef CONFIG_MACH_SUNIV
/* suniv doesn't have apb2 and uart is connected to apb1 */
#define CFG_SYS_NS16550_CLK 100000000
@@ -31,8 +32,9 @@
# define CFG_SYS_NS16550_COM5 SUNXI_R_UART_BASE
#endif
-/* CPU */
-
+/****************************************************************************
+ * DRAM base address *
+ ****************************************************************************/
/*
* The DRAM Base differs between some models. We cannot use macros for the
* CONFIG_FOO defines which contain the DRAM base address since they end
@@ -52,16 +54,6 @@
/* V3s do not have enough memory to place code at 0x4a000000 */
#endif
-/*
- * The A80's A1 sram starts at 0x00010000 rather then at 0x00000000 and is
- * slightly bigger. Note that it is possible to map the first 32 KiB of the
- * A1 at 0x00000000 like with older SoCs by writing 0x16aa0001 to the
- * undocumented 0x008000e0 SYS_CTRL register. Where the 16aa is a key and
- * the 1 actually activates the mapping of the first 32 KiB to 0x00000000.
- * A64 and H5 also has SRAM A1 at 0x00010000, but no magic remap register
- * is known yet.
- * H6 has SRAM A1 at 0x00020000.
- */
#define CFG_SYS_INIT_RAM_ADDR CONFIG_SUNXI_SRAM_ADDRESS
/* FIXME: this may be larger on some SoCs */
#define CFG_SYS_INIT_RAM_SIZE 0x8000 /* 32 KiB */
@@ -69,36 +61,13 @@
#define PHYS_SDRAM_0 CFG_SYS_SDRAM_BASE
#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GiB */
-/*
- * Miscellaneous configurable options
- */
-
-/* FLASH and environment organization */
-
+/****************************************************************************
+ * environment variables holding default load addresses *
+ ****************************************************************************/
/*
* We cannot use expressions here, because expressions won't be evaluated in
* autoconf.mk.
*/
-#if CONFIG_SUNXI_SRAM_ADDRESS == 0x10000
-#ifdef CONFIG_ARM64
-/* end of SRAM A2 for now, as SRAM A1 is pretty tight for an ARM64 build */
-#define LOW_LEVEL_SRAM_STACK 0x00054000
-#else
-#define LOW_LEVEL_SRAM_STACK 0x00018000
-#endif /* !CONFIG_ARM64 */
-#elif CONFIG_SUNXI_SRAM_ADDRESS == 0x20000
-#ifdef CONFIG_MACH_SUN50I_H616
-#define LOW_LEVEL_SRAM_STACK 0x52a00 /* below FEL buffers */
-#else
-/* end of SRAM A2 on H6 for now */
-#define LOW_LEVEL_SRAM_STACK 0x00118000
-#endif
-#else
-#define LOW_LEVEL_SRAM_STACK 0x00008000 /* End of sram */
-#endif
-
-/* Ethernet support */
-
#ifdef CONFIG_ARM64
/*
* Boards seem to come with at least 512MB of DRAM.
@@ -174,15 +143,11 @@
"ramdisk_addr_r=" RAMDISK_ADDR_R "\0"
#ifdef CONFIG_ARM64
-
#define MEM_LAYOUT_ENV_EXTRA_SETTINGS \
"kernel_comp_addr_r=" KERNEL_COMP_ADDR_R "\0" \
"kernel_comp_size=" KERNEL_COMP_SIZE "\0"
-
#else
-
#define MEM_LAYOUT_ENV_EXTRA_SETTINGS ""
-
#endif
#define DFU_ALT_INFO_RAM \
@@ -191,6 +156,9 @@
"fdt ram " FDT_ADDR_R " 0x100000;" \
"ramdisk ram " RAMDISK_ADDR_R " 0x4000000\0"
+/****************************************************************************
+ * definitions for the distro boot system *
+ ****************************************************************************/
#ifdef CONFIG_MMC
#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
#define BOOTENV_DEV_MMC_AUTO(devtypeu, devtypel, instance) \
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 2861b73..d1dbf3e 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -136,14 +136,6 @@
#define SPINOR_OP_BRRD 0x16 /* Bank register read */
#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
#define SPINOR_OP_EX4B_CYPRESS 0xB8 /* Exit 4-byte mode */
-#define SPINOR_OP_RDAR 0x65 /* Read any register */
-#define SPINOR_OP_WRAR 0x71 /* Write any register */
-#define SPINOR_REG_ADDR_STR1V 0x00800000
-#define SPINOR_REG_ADDR_CFR1V 0x00800002
-#define SPINOR_REG_ADDR_CFR3V 0x00800004
-#define SPINOR_REG_ADDR_ARCFN 0x00000006
-#define CFR3V_UNHYSA BIT(3) /* Uniform sectors or not */
-#define CFR3V_PGMBUF BIT(4) /* Program buffer size */
/* Used for Micron flashes only. */
#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
@@ -188,8 +180,12 @@
/* For Cypress flash. */
#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */
#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */
-#define SPINOR_OP_S28_SE_4K 0x21
+#define SPINOR_OP_CYPRESS_CLPEF 0x82 /* Clear P/E err flag */
+#define SPINOR_REG_CYPRESS_ARCFN 0x00000006
+#define SPINOR_REG_CYPRESS_STR1V 0x00800000
+#define SPINOR_REG_CYPRESS_CFR1V 0x00800002
#define SPINOR_REG_CYPRESS_CFR2V 0x00800003
+#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_MASK GENMASK(3, 0)
#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb
#define SPINOR_REG_CYPRESS_CFR3V 0x00800004
#define SPINOR_REG_CYPRESS_CFR3_PGSZ BIT(4) /* Page size. */
diff --git a/include/spl.h b/include/spl.h
index 0952188..043875f 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -889,6 +889,16 @@
int spl_ymodem_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev);
+/**
+ * spl_reserve_video_from_ram_top() - Reserve framebuffer memory from end of RAM
+ *
+ * This enforces framebuffer reservation at SPL stage from end of RAM so that
+ * next stage can directly skip this pre-reserved area before carrying out
+ * further reservations. The allocation address is stored in struct video_uc_plat.
+ *
+ * Return: 0 on success, otherwise error code
+ */
+int spl_reserve_video_from_ram_top(void);
/**
* spl_invoke_atf - boot using an ARM trusted firmware image
diff --git a/test/py/requirements.txt b/test/py/requirements.txt
index c3cc916..0f67c3c 100644
--- a/test/py/requirements.txt
+++ b/test/py/requirements.txt
@@ -11,10 +11,10 @@
packaging==23.2
pbr==5.4.3
pluggy==0.13.0
-py==1.10.0
+py==1.11.0
pycryptodomex==3.19.1
pyelftools==0.27
-pygit2==1.9.2
+pygit2==1.13.3
pyparsing==3.0.7
pytest==6.2.5
pytest-xdist==2.5.0
diff --git a/test/py/tests/test_gpio.py b/test/py/tests/test_gpio.py
index 0af186f..3e16e63 100644
--- a/test/py/tests/test_gpio.py
+++ b/test/py/tests/test_gpio.py
@@ -85,6 +85,13 @@
'gpio_ip_pin_clear':'66',
'gpio_clear_value': 'value is 0',
'gpio_set_value': 'value is 1',
+ # GPIO pin list to test gpio functionality for each pins, pin should be
+ # pin names (str)
+ 'gpio_pin_list': ['gpio@1000031', 'gpio@1000032', 'gpio@20000033'],
+ # GPIO input output list for shorted gpio pins to test gpio
+ # functionality for each of pairs, where the first element is
+ # configured as input and second as output
+ 'gpio_ip_op_list': [['gpio0', 'gpio1'], ['gpio2', 'gpio3']],
}
"""
@@ -223,3 +230,86 @@
response = u_boot_console.run_command(cmd)
good_response = gpio_set_value
assert good_response in response
+
+@pytest.mark.buildconfigspec('cmd_gpio')
+def test_gpio_pins_generic(u_boot_console):
+ """Test various gpio related functionality, such as the input, set, clear,
+ and toggle for the set of gpio pin list.
+
+ Specific set of gpio pins (by mentioning gpio pin name) configured as
+ input (mentioned as 'gpio_pin_list') to be tested for multiple gpio
+ commands.
+ """
+
+ f = u_boot_console.config.env.get('env__gpio_dev_config', False)
+ if not f:
+ pytest.skip('gpio not configured')
+
+ gpio_pins = f.get('gpio_pin_list', None)
+ if not gpio_pins:
+ pytest.skip('gpio pin list are not configured')
+
+ for gpin in gpio_pins:
+ # gpio input
+ u_boot_console.run_command(f'gpio input {gpin}')
+ expected_response = f'{gpin}: input:'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+ # gpio set
+ u_boot_console.run_command(f'gpio set {gpin}')
+ expected_response = f'{gpin}: output: 1'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+ # gpio clear
+ u_boot_console.run_command(f'gpio clear {gpin}')
+ expected_response = f'{gpin}: output: 0'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+ # gpio toggle
+ u_boot_console.run_command(f'gpio toggle {gpin}')
+ expected_response = f'{gpin}: output: 1'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+@pytest.mark.buildconfigspec('cmd_gpio')
+def test_gpio_pins_input_output_generic(u_boot_console):
+ """Test gpio related functionality such as input and output for the list of
+ shorted gpio pins provided as a pair of input and output pins. This test
+ will fail, if the gpio pins are not shorted properly.
+
+ Specific set of shorted gpio pins (by mentioning gpio pin name)
+ configured as input and output (mentioned as 'gpio_ip_op_list') as a
+ pair to be tested for gpio input output case.
+ """
+
+ f = u_boot_console.config.env.get('env__gpio_dev_config', False)
+ if not f:
+ pytest.skip('gpio not configured')
+
+ gpio_pins = f.get('gpio_ip_op_list', None)
+ if not gpio_pins:
+ pytest.skip('gpio pin list for input and output are not configured')
+
+ for gpins in gpio_pins:
+ u_boot_console.run_command(f'gpio input {gpins[0]}')
+ expected_response = f'{gpins[0]}: input:'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
+ assert expected_response in response
+
+ u_boot_console.run_command(f'gpio set {gpins[1]}')
+ expected_response = f'{gpins[1]}: output:'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[1]}')
+ assert expected_response in response
+
+ u_boot_console.run_command(f'gpio clear {gpins[1]}')
+ expected_response = f'{gpins[0]}: input: 0'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
+ assert expected_response in response
+
+ u_boot_console.run_command(f'gpio set {gpins[1]}')
+ expected_response = f'{gpins[0]}: input: 1'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
+ assert expected_response in response
diff --git a/test/py/tests/test_mmc.py b/test/py/tests/test_mmc.py
new file mode 100644
index 0000000..a96c4e8
--- /dev/null
+++ b/test/py/tests/test_mmc.py
@@ -0,0 +1,671 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import random
+import re
+import u_boot_utils
+
+"""
+Note: This test doesn't rely on boardenv_* configuration values but it can
+change the test behavior. To test MMC file system cases (fat32, ext2, ext4),
+MMC device should be formatted and valid partitions should be created for
+different file system, otherwise it may leads to failure. This test will be
+skipped if the MMC device is not detected.
+
+For example:
+
+# Setup env__mmc_device_test_skip to not skipping the test. By default, its
+# value is set to True. Set it to False to run all tests for MMC device.
+env__mmc_device_test_skip = False
+"""
+
+mmc_set_up = False
+controllers = 0
+devices = {}
+
+def setup_mmc(u_boot_console):
+ if u_boot_console.config.env.get('env__mmc_device_test_skip', True):
+ pytest.skip('MMC device test is not enabled')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_list(u_boot_console):
+ setup_mmc(u_boot_console)
+ output = u_boot_console.run_command('mmc list')
+ if 'No MMC device available' in output:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if 'Card did not respond to voltage select' in output:
+ pytest.skip('No SD/MMC card present')
+
+ array = output.split()
+ global devices
+ global controllers
+ controllers = int(len(array) / 2)
+ for x in range(0, controllers):
+ y = x * 2
+ devices[x] = {}
+ devices[x]['name'] = array[y]
+
+ global mmc_set_up
+ mmc_set_up = True
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_dev(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ fail = 0
+ for x in range(0, controllers):
+ devices[x]['detected'] = 'yes'
+ output = u_boot_console.run_command('mmc dev %d' % x)
+
+ # Some sort of switch here
+ if 'Card did not respond to voltage select' in output:
+ fail = 1
+ devices[x]['detected'] = 'no'
+
+ if 'no mmc device at slot' in output:
+ devices[x]['detected'] = 'no'
+
+ if 'MMC: no card present' in output:
+ devices[x]['detected'] = 'no'
+
+ if fail:
+ pytest.fail('Card not present')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmcinfo(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ output = u_boot_console.run_command('mmcinfo')
+ if 'busy timeout' in output:
+ pytest.skip('No SD/MMC/eMMC device present')
+
+ obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output)
+ try:
+ capacity = float(obj.groups()[0])
+ print(capacity)
+ devices[x]['capacity'] = capacity
+ print('Capacity of dev %d is: %g GiB' % (x, capacity))
+ except ValueError:
+ pytest.fail('MMC capacity not recognized')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_info(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+
+ output = u_boot_console.run_command('mmc info')
+
+ obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output)
+ try:
+ capacity = float(obj.groups()[0])
+ print(capacity)
+ if devices[x]['capacity'] != capacity:
+ pytest.fail("MMC capacity doesn't match mmcinfo")
+
+ except ValueError:
+ pytest.fail('MMC capacity not recognized')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_rescan(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ output = u_boot_console.run_command('mmc rescan')
+ if output:
+ pytest.fail('mmc rescan has something to check')
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_part(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ output = u_boot_console.run_command('mmc part')
+
+ lines = output.split('\n')
+ part_fat = []
+ part_ext = []
+ for line in lines:
+ obj = re.search(
+ r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line)
+ if obj:
+ part_id = int(obj.groups()[0])
+ part_type = obj.groups()[1]
+ print('part_id:%d, part_type:%s' % (part_id, part_type))
+
+ if part_type in ['0c', '0b', '0e']:
+ print('Fat detected')
+ part_fat.append(part_id)
+ elif part_type == '83':
+ print('ext detected')
+ part_ext.append(part_id)
+ else:
+ pytest.fail('Unsupported Filesystem on device %d' % x)
+ devices[x]['ext4'] = part_ext
+ devices[x]['ext2'] = part_ext
+ devices[x]['fat'] = part_fat
+
+ if not part_ext and not part_fat:
+ pytest.fail('No partition detected on device %d' % x)
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fat')
+def test_mmc_fatls_fatinfo(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ output = u_boot_console.run_command(
+ 'fatls mmc %d:%s' % (x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+
+ if not re.search(r'\d file\(s\), \d dir\(s\)', output):
+ pytest.fail('%s read failed on device %d' % (fs.upper, x))
+ output = u_boot_console.run_command(
+ 'fatinfo mmc %d:%s' % (x, part))
+ string = 'Filesystem: %s' % fs.upper
+ if re.search(string, output):
+ pytest.fail('%s FS failed on device %d' % (fs.upper(), x))
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fat')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_fatload_fatwrite(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ devices[x]['addr_%d' % part] = addr
+ size = random.randint(4, 1 * 1024 * 1024)
+ devices[x]['size_%d' % part] = size
+ # count CRC32
+ output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ expected_crc32 = m.group(1)
+ devices[x]['expected_crc32_%d' % part] = expected_crc32
+ # do write
+ file = '%s_%d' % ('uboot_test', size)
+ devices[x]['file_%d' % part] = file
+ output = u_boot_console.run_command(
+ '%swrite mmc %d:%s %x %s %x' % (fs, x, part, addr, file, size)
+ )
+ assert 'Unable to write' not in output
+ assert 'Error' not in output
+ assert 'overflow' not in output
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ alignment = int(
+ u_boot_console.config.buildconfig.get(
+ 'config_sys_cacheline_size', 128
+ )
+ )
+ offset = random.randrange(alignment, 1024, alignment)
+ output = u_boot_console.run_command(
+ '%sload mmc %d:%s %x %s' % (fs, x, part, addr + offset, file)
+ )
+ assert 'Invalid FAT entry' not in output
+ assert 'Unable to read file' not in output
+ assert 'Misaligned buffer address' not in output
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext4')
+def test_mmc_ext4ls(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ u_boot_console.run_command('mmc dev %d' % x)
+ for part in partitions:
+ output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('ext4_write')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_ext4load_ext4write(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ devices[x]['addr_%d' % part] = addr
+ size = random.randint(4, 1 * 1024 * 1024)
+ devices[x]['size_%d' % part] = size
+ # count CRC32
+ output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ expected_crc32 = m.group(1)
+ devices[x]['expected_crc32_%d' % part] = expected_crc32
+ # do write
+
+ file = '%s_%d' % ('uboot_test', size)
+ devices[x]['file_%d' % part] = file
+ output = u_boot_console.run_command(
+ '%swrite mmc %d:%s %x /%s %x' % (fs, x, part, addr, file, size)
+ )
+ assert 'Unable to write' not in output
+ assert 'Error' not in output
+ assert 'overflow' not in output
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ '%sload mmc %d:%s %x /%s' % (fs, x, part, addr + offset, file)
+ )
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext2')
+def test_mmc_ext2ls(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext2')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('ext4_write')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_ext2load(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = devices[x]['addr_%d' % part]
+ size = devices[x]['size_%d' % part]
+ expected_crc32 = devices[x]['expected_crc32_%d' % part]
+ file = devices[x]['file_%d' % part]
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ '%sload mmc %d:%s %x /%s' % (fs, x, part, addr + offset, file)
+ )
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_mmc_ls(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('ls mmc %d:%s' % (x, part))
+ if re.search(r'No \w+ table on this device', output):
+ pytest.fail(
+ '%s: Partition table not found %d' % (fs.upper(), x)
+ )
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_mmc_load(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = devices[x]['addr_%d' % part]
+ size = devices[x]['size_%d' % part]
+ expected_crc32 = devices[x]['expected_crc32_%d' % part]
+ file = devices[x]['file_%d' % part]
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'load mmc %d:%s %x /%s' % (x, part, addr + offset, file)
+ )
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_mmc_save(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = devices[x]['addr_%d' % part]
+ size = 0
+ file = devices[x]['file_%d' % part]
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'save mmc %d:%s %x /%s %d'
+ % (x, part, addr + offset, file, size)
+ )
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fat')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_fat_read_write_files(u_boot_console):
+ test_mmc_list(u_boot_console)
+ test_mmc_dev(u_boot_console)
+ test_mmcinfo(u_boot_console)
+ test_mmc_part(u_boot_console)
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+
+ # Number of files to be written/read in MMC card
+ num_files = 100
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ count_f = 0
+ addr_l = []
+ size_l = []
+ file_l = []
+ crc32_l = []
+ offset_l = []
+ addr_l.append(addr)
+
+ while count_f < num_files:
+ size_l.append(random.randint(4, 1 * 1024 * 1024))
+
+ # CRC32 count
+ output = u_boot_console.run_command(
+ 'crc32 %x %x' % (addr_l[count_f], size_l[count_f])
+ )
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ crc32_l.append(m.group(1))
+
+ # Write operation
+ file_l.append('%s_%d_%d' % ('uboot_test', count_f, size_l[count_f]))
+ output = u_boot_console.run_command(
+ '%swrite mmc %d:%s %x %s %x'
+ % (
+ fs,
+ x,
+ part,
+ addr_l[count_f],
+ file_l[count_f],
+ size_l[count_f],
+ )
+ )
+ assert 'Unable to write' not in output
+ assert 'Error' not in output
+ assert 'overflow' not in output
+ expected_text = '%d bytes written' % size_l[count_f]
+ assert expected_text in output
+
+ addr_l.append(addr_l[count_f] + size_l[count_f] + 1048576)
+ count_f += 1
+
+ count_f = 0
+ while count_f < num_files:
+ alignment = int(
+ u_boot_console.config.buildconfig.get(
+ 'config_sys_cacheline_size', 128
+ )
+ )
+ offset_l.append(random.randrange(alignment, 1024, alignment))
+
+ # Read operation
+ output = u_boot_console.run_command(
+ '%sload mmc %d:%s %x %s'
+ % (
+ fs,
+ x,
+ part,
+ addr_l[count_f] + offset_l[count_f],
+ file_l[count_f],
+ )
+ )
+ assert 'Invalid FAT entry' not in output
+ assert 'Unable to read file' not in output
+ assert 'Misaligned buffer address' not in output
+ expected_text = '%d bytes read' % size_l[count_f]
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr_l[count_f] + offset_l[count_f])
+ )
+ assert crc32_l[count_f] in output
+
+ count_f += 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
diff --git a/test/py/tests/test_scsi.py b/test/py/tests/test_scsi.py
new file mode 100644
index 0000000..be2e283
--- /dev/null
+++ b/test/py/tests/test_scsi.py
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+the SCSI device number, type and capacity. This test will be automatically
+skipped without this.
+
+For example:
+
+# Setup env__scsi_device_test to set the SCSI device number/slot, the type of
+device, and the device capacity in MB.
+env__scsi_device_test = {
+ 'dev_num': 0,
+ 'device_type': 'Hard Disk',
+ 'device_capacity': '476940.0 MB',
+}
+"""
+
+def scsi_setup(u_boot_console):
+ f = u_boot_console.config.env.get('env__scsi_device_test', None)
+ if not f:
+ pytest.skip('No SCSI device to test')
+
+ dev_num = f.get('dev_num', None)
+ if not isinstance(dev_num, int):
+ pytest.skip('No device number specified in env file to read')
+
+ dev_type = f.get('device_type')
+ if not dev_type:
+ pytest.skip('No device type specified in env file to read')
+
+ dev_size = f.get('device_capacity')
+ if not dev_size:
+ pytest.skip('No device capacity specified in env file to read')
+
+ return dev_num, dev_type, dev_size
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_reset(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi reset')
+ assert f'Device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_info(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi info')
+ assert f'Device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_scan(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi scan')
+ assert f'Device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_dev(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi device')
+ assert 'no scsi devices available' not in output
+ assert f'device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ output = u_boot_console.run_command('scsi device %d' % dev_num)
+ assert 'is now current device' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_part(u_boot_console):
+ test_scsi_dev(u_boot_console)
+ output = u_boot_console.run_command('scsi part')
+ assert 'Partition Map for SCSI device' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
diff --git a/test/py/tests/test_usb.py b/test/py/tests/test_usb.py
new file mode 100644
index 0000000..fb3d20f
--- /dev/null
+++ b/test/py/tests/test_usb.py
@@ -0,0 +1,626 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import random
+import re
+import u_boot_utils
+
+"""
+Note: This test doesn't rely on boardenv_* configuration values but it can
+change the test behavior. To test USB file system cases (fat32, ext2, ext4),
+USB device should be formatted and valid partitions should be created for
+different file system, otherwise it may leads to failure. This test will be
+skipped if the USB device is not detected.
+
+For example:
+
+# Setup env__usb_device_test_skip to not skipping the test. By default, its
+# value is set to True. Set it to False to run all tests for USB device.
+env__usb_device_test_skip = False
+"""
+
+def setup_usb(u_boot_console):
+ if u_boot_console.config.env.get('env__usb_device_test_skip', True):
+ pytest.skip('USB device test is not enabled')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_start(u_boot_console):
+ setup_usb(u_boot_console)
+ output = u_boot_console.run_command('usb start')
+
+ # if output is empty, usb start may already run as part of preboot command
+ # re-start the usb, in that case
+ if not output:
+ u_boot_console.run_command('usb stop')
+ output = u_boot_console.run_command('usb start')
+
+ if 'No USB device found' in output:
+ pytest.skip('No USB controller available')
+
+ if 'Card did not respond to voltage select' in output:
+ pytest.skip('No USB device present')
+
+ controllers = 0
+ storage_device = 0
+ obj = re.search(r'\d USB Device\(s\) found', output)
+ controllers = int(obj.group()[0])
+
+ if not controllers:
+ pytest.skip('No USB device present')
+
+ obj = re.search(r'\d Storage Device\(s\) found', output)
+ storage_device = int(obj.group()[0])
+
+ if not storage_device:
+ pytest.skip('No USB storage device present')
+
+ assert 'USB init failed' not in output
+ assert 'starting USB...' in output
+
+ if 'Starting the controller' in output:
+ assert 'USB XHCI' in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ return controllers, storage_device
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_stop(u_boot_console):
+ setup_usb(u_boot_console)
+ output = u_boot_console.run_command('usb stop')
+ assert 'stopping USB..' in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ output = u_boot_console.run_command('usb dev')
+ assert "USB is stopped. Please issue 'usb start' first." in output
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_reset(u_boot_console):
+ setup_usb(u_boot_console)
+ output = u_boot_console.run_command('usb reset')
+
+ if 'No USB device found' in output:
+ pytest.skip('No USB controller available')
+
+ if 'Card did not respond to voltage select' in output:
+ pytest.skip('No USB device present')
+
+ obj = re.search(r'\d USB Device\(s\) found', output)
+ usb_dev_num = int(obj.group()[0])
+
+ if not usb_dev_num:
+ pytest.skip('No USB device present')
+
+ obj = re.search(r'\d Storage Device\(s\) found', output)
+ usb_stor_num = int(obj.group()[0])
+
+ if not usb_stor_num:
+ pytest.skip('No USB storage device present')
+
+ assert 'BUG' not in output
+ assert 'USB init failed' not in output
+ assert 'resetting USB...' in output
+
+ if 'Starting the controller' in output:
+ assert 'USB XHCI' in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_info(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb info')
+
+ num_controller = len(re.findall(': Hub,', output))
+ num_mass_storage = len(re.findall(': Mass Storage,', output))
+
+ assert num_controller == controllers - 1
+ assert num_mass_storage == storage_device
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ for i in range(0, storage_device + controllers - 1):
+ output = u_boot_console.run_command('usb info %d' % i)
+ num_controller = len(re.findall(': Hub,', output))
+ num_mass_storage = len(re.findall(': Mass Storage,', output))
+ assert num_controller + num_mass_storage == 1
+ assert 'No device available' not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_tree(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb tree')
+
+ num_controller = len(re.findall('Hub', output))
+ num_mass_storage = len(re.findall('Mass Storage', output))
+
+ assert num_controller == controllers - 1
+ assert num_mass_storage == storage_device
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('usb_storage')
+def test_usb_storage(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb storage')
+
+ obj = re.findall(r'Capacity: (\d+|\d+[\.]?\d)', output)
+ devices = {}
+
+ for key in range(int(storage_device)):
+ devices[key] = {}
+
+ for x in range(int(storage_device)):
+ try:
+ capacity = float(obj[x].split()[0])
+ devices[x]['capacity'] = capacity
+ print('USB storage device %d capacity is: %g MB' % (x, capacity))
+ except ValueError:
+ pytest.fail('USB storage device capacity not recognized')
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_dev(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb dev')
+
+ assert 'no usb devices available' not in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ devices = {}
+
+ for key in range(int(storage_device)):
+ devices[key] = {}
+
+ fail = 0
+ for x in range(0, storage_device):
+ devices[x]['detected'] = 'yes'
+ output = u_boot_console.run_command('usb dev %d' % x)
+
+ if 'Card did not respond to voltage select' in output:
+ fail = 1
+ devices[x]['detected'] = 'no'
+
+ if 'No USB device found' in output:
+ devices[x]['detected'] = 'no'
+
+ if 'unknown device' in output:
+ devices[x]['detected'] = 'no'
+
+ assert 'is now current device' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ if fail:
+ pytest.fail('USB device not present')
+
+ return devices, controllers, storage_device
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_part(u_boot_console):
+ devices, controllers, storage_device = test_usb_dev(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ u_boot_console.run_command('usb part')
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ for i in range(0, storage_device):
+ if devices[i]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % i)
+ output = u_boot_console.run_command('usb part')
+
+ lines = output.split('\n')
+ part_fat = []
+ part_ext = []
+ for line in lines:
+ obj = re.search(r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line)
+ if obj:
+ part_id = int(obj.groups()[0])
+ part_type = obj.groups()[1]
+ print('part_id:%d, part_type:%s' % (part_id, part_type))
+
+ if part_type == '0c' or part_type == '0b' or part_type == '0e':
+ print('Fat detected')
+ part_fat.append(part_id)
+ elif part_type == '83':
+ print('ext detected')
+ part_ext.append(part_id)
+ else:
+ pytest.fail('Unsupported Filesystem on device %d' % i)
+ devices[i]['ext4'] = part_ext
+ devices[i]['ext2'] = part_ext
+ devices[i]['fat'] = part_fat
+
+ if not part_ext and not part_fat:
+ pytest.fail('No partition detected on device %d' % i)
+
+ return devices, controllers, storage_device
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fat')
+def test_usb_fatls_fatinfo(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ output = u_boot_console.run_command('fatls usb %d:%s' % (x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+
+ if not re.search(r'\d file\(s\), \d dir\(s\)', output):
+ pytest.fail('%s read failed on device %d' % (fs.upper, x))
+
+ output = u_boot_console.run_command('fatinfo usb %d:%s' % (x, part))
+ string = 'Filesystem: %s' % fs.upper
+ if re.search(string, output):
+ pytest.fail('%s FS failed on device %d' % (fs.upper(), x))
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fat')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_usb_fatload_fatwrite(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ size = random.randint(4, 1 * 1024 * 1024)
+ output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ expected_crc32 = m.group(1)
+
+ file = '%s_%d' % ('uboot_test', size)
+ output = u_boot_console.run_command(
+ '%swrite usb %d:%s %x %s %x' % (fs, x, part, addr, file, size)
+ )
+ assert 'Unable to write' not in output
+ assert 'Error' not in output
+ assert 'overflow' not in output
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ alignment = int(
+ u_boot_console.config.buildconfig.get(
+ 'config_sys_cacheline_size', 128
+ )
+ )
+ offset = random.randrange(alignment, 1024, alignment)
+ output = u_boot_console.run_command(
+ '%sload usb %d:%s %x %s' % (fs, x, part, addr + offset, file)
+ )
+ assert 'Invalid FAT entry' not in output
+ assert 'Unable to read file' not in output
+ assert 'Misaligned buffer address' not in output
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+ return file, size
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_ext4')
+def test_usb_ext4ls(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ u_boot_console.run_command('usb dev %d' % x)
+ for part in partitions:
+ output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('ext4_write')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_usb_ext4load_ext4write(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ size = random.randint(4, 1 * 1024 * 1024)
+ output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ expected_crc32 = m.group(1)
+ file = '%s_%d' % ('uboot_test', size)
+
+ output = u_boot_console.run_command(
+ '%swrite usb %d:%s %x /%s %x' % (fs, x, part, addr, file, size)
+ )
+ assert 'Unable to write' not in output
+ assert 'Error' not in output
+ assert 'overflow' not in output
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ '%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file)
+ )
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+ return file, size
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_ext2')
+def test_usb_ext2ls(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_ext2')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('ext4_write')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_usb_ext2load(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ file, size = test_usb_ext4load_ext4write(u_boot_console)
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ expected_crc32 = m.group(1)
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ '%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file)
+ )
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_usb_ls(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('ls usb %d:%s' % (x, part))
+ if re.search(r'No \w+ table on this device', output):
+ pytest.fail(
+ '%s: Partition table not found %d' % (fs.upper(), x)
+ )
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_usb_load(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ if fs == 'fat':
+ file, size = test_usb_fatload_fatwrite(u_boot_console)
+ elif fs == 'ext4':
+ file, size = test_usb_ext4load_ext4write(u_boot_console)
+
+ output = u_boot_console.run_command('crc32 %x %x' % (addr, size))
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ expected_crc32 = m.group(1)
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'load usb %d:%s %x /%s' % (x, part, addr + offset, file)
+ )
+ expected_text = '%d bytes read' % size
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr + offset)
+ )
+ assert expected_crc32 in output
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_usb_save(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ size = random.randint(4, 1 * 1024 * 1024)
+ file = '%s_%d' % ('uboot_test', size)
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'save usb %d:%s %x /%s %x'
+ % (x, part, addr + offset, file, size)
+ )
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ if not part_detect:
+ pytest.skip('No partition detected')
diff --git a/test/py/tests/test_zynq_secure.py b/test/py/tests/test_zynq_secure.py
new file mode 100644
index 0000000..0ee5aeb
--- /dev/null
+++ b/test/py/tests/test_zynq_secure.py
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import re
+import u_boot_utils
+import test_net
+
+"""
+This test verifies different type of secure boot images to authentication and
+decryption using AES and RSA features for AMD's Zynq SoC.
+
+Note: This test relies on boardenv_* containing configuration values to define
+the network available and files to be used for testing. Without this, this test
+will be automatically skipped. It also relies on dhcp or setup_static net test
+to support tftp to load files from a TFTP server.
+
+For example:
+
+# Details regarding the files that may be read from a TFTP server and addresses
+# and size for aes and rsa cases respectively. This variable may be omitted or
+# set to None if zynqmp secure testing is not possible or desired.
+env__zynq_aes_readable_file = {
+ 'fn': 'zynq_aes_image.bin',
+ 'fnbit': 'zynq_aes_bit.bin',
+ 'fnpbit': 'zynq_aes_par_bit.bin',
+ 'srcaddr': 0x1000000,
+ 'dstaddr': 0x2000000,
+ 'dstlen': 0x1000000,
+}
+
+env__zynq_rsa_readable_file = {
+ 'fn': 'zynq_rsa_image.bin',
+ 'fninvalid': 'zynq_rsa_image_invalid.bin',
+ 'srcaddr': 0x1000000,
+}
+"""
+
+def zynq_secure_pre_commands(u_boot_console):
+ output = u_boot_console.run_command('print modeboot')
+ if not 'modeboot=' in output:
+ pytest.skip('bootmode cannnot be determined')
+ m = re.search('modeboot=(.+?)boot', output)
+ if not m:
+ pytest.skip('bootmode cannnot be determined')
+ bootmode = m.group(1)
+ if bootmode == 'jtag':
+ pytest.skip('skipping due to jtag bootmode')
+
+@pytest.mark.buildconfigspec('cmd_zynq_aes')
+def test_zynq_aes_image(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure aes case to read')
+
+ dstaddr = f.get('dstaddr', None)
+ if not dstaddr:
+ pytest.skip('No dstaddr specified in env file to read')
+
+ dstsize = f.get('dstlen', None)
+ if not dstsize:
+ pytest.skip('No dstlen specified in env file to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq aes [operation type] <srcaddr>'
+ output = u_boot_console.run_command(
+ 'zynq aes %x $filesize %x %x' % (srcaddr, dstaddr, dstsize)
+ )
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_aes')
+def test_zynq_aes_bitstream(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure aes case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fnbit']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq aes [operation type] <srcaddr>'
+ output = u_boot_console.run_command(
+ 'zynq aes load %x $filesize' % (srcaddr)
+ )
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_aes')
+def test_zynq_aes_partial_bitstream(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure aes case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fnpbit']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq aes [operation type] <srcaddr>'
+ output = u_boot_console.run_command('zynq aes loadp %x $filesize' % (srcaddr))
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_rsa')
+def test_zynq_rsa_image(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_rsa_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure rsa case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq rsa <baseaddr>'
+ output = u_boot_console.run_command('zynq rsa %x ' % (srcaddr))
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_rsa')
+def test_zynq_rsa_image_invalid(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_rsa_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure rsa case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fninvalid = f['fninvalid']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fninvalid))
+ assert expected_tftp in output
+
+ expected_op = 'zynq rsa <baseaddr>'
+ output = u_boot_console.run_command('zynq rsa %x ' % (srcaddr))
+ assert expected_op in output
+ output = u_boot_console.run_command('echo $?')
+ assert not output.endswith('0')
diff --git a/test/py/tests/test_zynqmp_rpu.py b/test/py/tests/test_zynqmp_rpu.py
new file mode 100644
index 0000000..479a612
--- /dev/null
+++ b/test/py/tests/test_zynqmp_rpu.py
@@ -0,0 +1,208 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import random
+import string
+import test_net
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+RPU applications information for AMD's ZynqMP SoC which contains, application
+names, processors, address where it is built, expected output and the tftp load
+addresses. This test will be automatically skipped without this.
+
+It also relies on dhcp or setup_static net test to support tftp to load
+application on DDR. All the environment parameters are stored sequentially.
+The length of all parameters values should be same. For example, if 2 app_names
+are defined in a list as a value of parameter 'app_name' then the other
+parameters value also should have a list with 2 items.
+It will run RPU cases for all the applications defined in boardenv_*
+configuration file.
+
+Example:
+env__zynqmp_rpu_apps = {
+ 'app_name': ['hello_world_r5_0_ddr.elf', 'hello_world_r5_1_ddr.elf'],
+ 'proc': ['rpu0', 'rpu1'],
+ 'cpu_num': [4, 5],
+ 'addr': [0xA00000, 0xB00000],
+ 'output': ['Successfully ran Hello World application on DDR from RPU0',
+ 'Successfully ran Hello World application on DDR from RPU1'],
+ 'tftp_addr': [0x100000, 0x200000],
+}
+"""
+
+# Get rpu apps params from env
+def get_rpu_apps_env(u_boot_console):
+ rpu_apps = u_boot_console.config.env.get('env__zynqmp_rpu_apps', False)
+ if not rpu_apps:
+ pytest.skip('ZynqMP RPU application info not defined!')
+
+ apps = rpu_apps.get('app_name', None)
+ if not apps:
+ pytest.skip('No RPU application found!')
+
+ procs = rpu_apps.get('proc', None)
+ if not procs:
+ pytest.skip('No RPU application processor provided!')
+
+ cpu_nums = rpu_apps.get('cpu_num', None)
+ if not cpu_nums:
+ pytest.skip('No CPU number for respective processor provided!')
+
+ addrs = rpu_apps.get('addr', None)
+ if not addrs:
+ pytest.skip('No RPU application build address found!')
+
+ outputs = rpu_apps.get('output', None)
+ if not outputs:
+ pytest.skip('Expected output not found!')
+
+ tftp_addrs = rpu_apps.get('tftp_addr', None)
+ if not tftp_addrs:
+ pytest.skip('TFTP address to load application not found!')
+
+ return apps, procs, cpu_nums, addrs, outputs, tftp_addrs
+
+# Check return code
+def ret_code(u_boot_console):
+ return u_boot_console.run_command('echo $?')
+
+# Initialize tcm
+def tcminit(u_boot_console, rpu_mode):
+ output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
+ assert 'Initializing TCM overwrites TCM content' in output
+ return ret_code(u_boot_console)
+
+# Load application in DDR
+def load_app_ddr(u_boot_console, tftp_addr, app):
+ output = u_boot_console.run_command('tftpboot %x %s' % (tftp_addr, app))
+ assert 'TIMEOUT' not in output
+ assert 'Bytes transferred = ' in output
+
+ # Load elf
+ u_boot_console.run_command('bootelf -p %x' % tftp_addr)
+ assert ret_code(u_boot_console).endswith('0')
+
+# Disable cpus
+def disable_cpus(u_boot_console, cpu_nums):
+ for num in cpu_nums:
+ u_boot_console.run_command(f'cpu {num} disable')
+
+# Load apps on RPU cores
+def rpu_apps_load(u_boot_console, rpu_mode):
+ apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
+ u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ try:
+ assert tcminit(u_boot_console, rpu_mode).endswith('0')
+
+ for i in range(len(apps)):
+ if rpu_mode == 'lockstep' and procs[i] != 'rpu0':
+ continue
+
+ load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
+ rel_addr = int(addrs[i] + 0x3C)
+
+ # Release cpu at app load address
+ cpu_num = cpu_nums[i]
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
+ output = u_boot_console.run_command(cmd)
+ exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
+ assert exp_op in output
+ assert f'R5 {rpu_mode} mode' in output
+ u_boot_console.wait_for(outputs[i])
+ assert ret_code(u_boot_console).endswith('0')
+ finally:
+ disable_cpus(u_boot_console, cpu_nums)
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_rpu_app_load_split(u_boot_console):
+ rpu_apps_load(u_boot_console, 'split')
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_rpu_app_load_lockstep(u_boot_console):
+ rpu_apps_load(u_boot_console, 'lockstep')
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_rpu_app_load_negative(u_boot_console):
+ apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
+ u_boot_console)
+
+ # Invalid commands
+ u_boot_console.run_command('zynqmp tcminit mode')
+ assert ret_code(u_boot_console).endswith('1')
+
+ rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
+ u_boot_console.run_command('zynqmp tcminit %s' % rand_str)
+ assert ret_code(u_boot_console).endswith('1')
+
+ rand_num = random.randint(2, 100)
+ u_boot_console.run_command('zynqmp tcminit %d' % rand_num)
+ assert ret_code(u_boot_console).endswith('1')
+
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ try:
+ rpu_mode = 'split'
+ assert tcminit(u_boot_console, rpu_mode).endswith('0')
+
+ for i in range(len(apps)):
+ load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
+
+ # Run in split mode at different load address
+ rel_addr = int(addrs[i]) + random.randint(200, 1000)
+ cpu_num = cpu_nums[i]
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
+ output = u_boot_console.run_command(cmd)
+ exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
+ assert exp_op in output
+ assert f'R5 {rpu_mode} mode' in output
+ assert not outputs[i] in output
+
+ # Invalid rpu mode
+ rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rand_str)
+ output = u_boot_console.run_command(cmd)
+ assert exp_op in output
+ assert f'Unsupported mode' in output
+ assert not ret_code(u_boot_console).endswith('0')
+
+ # Switch to lockstep mode, without disabling CPUs
+ rpu_mode = 'lockstep'
+ u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
+ assert not ret_code(u_boot_console).endswith('0')
+
+ # Disable cpus
+ disable_cpus(u_boot_console, cpu_nums)
+
+ # Switch to lockstep mode, after disabling CPUs
+ output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
+ assert 'Initializing TCM overwrites TCM content' in output
+ assert ret_code(u_boot_console).endswith('0')
+
+ # Run lockstep mode for RPU1
+ for i in range(len(apps)):
+ if procs[i] == 'rpu0':
+ continue
+
+ load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
+ rel_addr = int(addrs[i] + 0x3C)
+ cpu_num = cpu_nums[i]
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
+ output = u_boot_console.run_command(cmd)
+ exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
+ assert exp_op in output
+ assert f'R5 {rpu_mode} mode' in output
+ assert u_boot_console.p.expect([outputs[i]])
+ finally:
+ disable_cpus(u_boot_console, cpu_nums)
+ # This forces the console object to be shutdown, so any subsequent test
+ # will reset the board back into U-Boot.
+ u_boot_console.drain_console()
+ u_boot_console.cleanup_spawn()
diff --git a/test/py/tests/test_zynqmp_secure.py b/test/py/tests/test_zynqmp_secure.py
new file mode 100644
index 0000000..570bd24
--- /dev/null
+++ b/test/py/tests/test_zynqmp_secure.py
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import re
+import u_boot_utils
+import test_net
+
+"""
+This test verifies different type of secure boot images loaded at the DDR for
+AMD's ZynqMP SoC.
+
+Note: This test relies on boardenv_* containing configuration values to define
+the files to be used for testing. Without this, this test will be automatically
+skipped. It also relies on dhcp or setup_static net test to support tftp to
+load files from a TFTP server.
+
+For example:
+
+# Details regarding the files that may be read from a TFTP server. This
+# variable may be omitted or set to None if zynqmp secure testing is not
+# possible or desired.
+env__zynqmp_secure_readable_file = {
+ 'fn': 'auth_bhdr_ppk1.bin',
+ 'enckupfn': 'auth_bhdr_enc_kup_load.bin',
+ 'addr': 0x1000000,
+ 'keyaddr': 0x100000,
+ 'keyfn': 'aes.txt',
+}
+"""
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_secure_boot_image(u_boot_console):
+ """This test verifies secure boot image at the DDR address for
+ authentication only case.
+ """
+
+ f = u_boot_console.config.env.get('env__zynqmp_secure_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynqmp secure cases to read')
+
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ addr = f.get('addr', None)
+ if not addr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
+ assert expected_tftp in output
+
+ output = u_boot_console.run_command('zynqmp secure %x $filesize' % (addr))
+ assert 'Verified image at' in output
+ ver_addr = re.search(r'Verified image at 0x(.+)', output).group(1)
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ output = u_boot_console.run_command('print zynqmp_verified_img_addr')
+ assert f'zynqmp_verified_img_addr={ver_addr}' in output
+ assert 'Error' not in output
+
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_secure_boot_img_kup(u_boot_console):
+ """This test verifies secure boot image at the DDR address for encryption
+ with kup key case.
+ """
+
+ f = u_boot_console.config.env.get('env__zynqmp_secure_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynqmp secure cases to read')
+
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ keyaddr = f.get('keyaddr', None)
+ if not keyaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ expected_tftp = 'Bytes transferred = '
+ keyfn = f['keyfn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (keyaddr, keyfn))
+ assert expected_tftp in output
+
+ addr = f.get('addr', None)
+ if not addr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ expected_tftp = 'Bytes transferred = '
+ fn = f['enckupfn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
+ assert expected_tftp in output
+
+ output = u_boot_console.run_command(
+ 'zynqmp secure %x $filesize %x' % (addr, keyaddr)
+ )
+ assert 'Verified image at' in output
+ ver_addr = re.search(r'Verified image at 0x(.+)', output).group(1)
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ output = u_boot_console.run_command('print zynqmp_verified_img_addr')
+ assert f'zynqmp_verified_img_addr={ver_addr}' in output
+ assert 'Error' not in output
diff --git a/tools/buildman/bsettings.py b/tools/buildman/bsettings.py
index f7f8276..e225ac2 100644
--- a/tools/buildman/bsettings.py
+++ b/tools/buildman/bsettings.py
@@ -16,7 +16,7 @@
global settings
global config_fname
- settings = configparser.SafeConfigParser()
+ settings = configparser.ConfigParser()
if fname is not None:
config_fname = fname
if config_fname == '':