aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-04-02 15:28:43 -0400
committerTom Rini <trini@konsulko.com>2022-04-02 15:28:43 -0400
commit10d615f2fcc0d2ef1d611844eb6032fe0fca8afd (patch)
treefc64ed7fef66e55214c75b98a90531645a203294
parent5b160c3a13f80708b4a720119cd2a1ef161e57f0 (diff)
parent7a763471894feb58d5a1bdf78ea7014c7a952264 (diff)
downloadu-boot-10d615f2fcc0d2ef1d611844eb6032fe0fca8afd.zip
u-boot-10d615f2fcc0d2ef1d611844eb6032fe0fca8afd.tar.gz
u-boot-10d615f2fcc0d2ef1d611844eb6032fe0fca8afd.tar.bz2
Merge branch '2022-04-01-arm-semihosting-cleanups-and-new-features' into next
This brings in two related series. The first from Andre: This series is the continuation of last year's effort to support the new Armv8-R64 application profile. This led to a significant rework of the existing fastmodel (FVP) support, to both upgrade it to newest U-Boot standards (OF_CONTROL and distro_boot support), but also to generalise the code, so that plugging in the v8-R64 support in the last patch gets much easier. This is because apart from the twisted memory map between the two profiles there is actually little difference, when it comes to U-Boot relevant parts of the hardware. I kept the legacy semihosting support (which picks up magic files from the current directory), but if that fails, we go and try virtio-blk (.iso installer images work), then virtio-net. Please have a look, and give it a try, if possible. Both the v8-R and v8-A FVP models are available for free on the Arm website[1]. Patch 01/11 fixes a regression introduced in December, it should be applied now. The rest of the patches are for the next merge window. [1] https://developer.arm.com/tools-and-software/simulation-models/fast-models And the second from Sean (where we exclude 27, 28 and 29 for now): This cleans up the semihosting code and adds the following new features: - hostfs support (like sandbox) - support for being used as a SPL boot device - serial device support - falling back to normal drivers if semihosting is disabled The main device affected by these changes is vexpress64, so I'd appreciate if Andre (or anyone else) could try booting. These changes are motivated by bringup for ls1046a. When forcing JTAG boot, this device disables most communication peripherals, including serial and ethernet devices. This appears to be fixed in later generation devices, but we are stuck with it for now. Semihosting provides an easy way to run a few console commands. The patches in this series are organized as follows: 0-4: rST conversions and other documentation updates 5-9: Semihosting cleanups 10-14: Filesystem support (including SPL boot device) 15-16: Serial support 16: Documentation update 17: JTAG boot support for LS1046A 19-25: Semihosting fallback 26-29: DM puts support The last two groups of patches are "bonus;" the first 17 patches stand on their own. The last two groups could be broken out as separate series, but I have kept them in this one to help with my sanity (and not have to deal with too many outstanding series). Patch 14 depends on [1] to apply cleanly. Patch 17 depends on [2] for correctness. This series should be applied to u-boot/next (in particular, the EROFS series must have been applied). [1] https://lore.kernel.org/u-boot/CACRpkdZ+9fmNjC_mvrbPa9-iuTQVd8UkJ7Zpe7cL0c5vZygsVw@mail.gmail.com/T/ [2] https://lore.kernel.org/u-boot/20220222183840.1355337-2-sean.anderson@seco.com/
-rw-r--r--MAINTAINERS5
-rw-r--r--arch/arm/Kconfig78
-rw-r--r--arch/arm/cpu/armv8/exceptions.S9
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/spl.c3
-rw-r--r--arch/arm/dts/Makefile2
-rw-r--r--arch/arm/dts/arm_fvp.dts11
-rw-r--r--arch/arm/dts/fvp-base-revc.dts246
-rw-r--r--arch/arm/dts/rtsm_ve-motherboard-rs2.dtsi27
-rw-r--r--arch/arm/dts/rtsm_ve-motherboard.dtsi258
-rw-r--r--arch/arm/include/asm/esr.h343
-rw-r--r--arch/arm/include/asm/proc-armv/ptrace.h75
-rw-r--r--arch/arm/include/asm/spl.h1
-rw-r--r--arch/arm/include/asm/u-boot-arm.h7
-rw-r--r--arch/arm/lib/Makefile2
-rw-r--r--arch/arm/lib/interrupts_64.c80
-rw-r--r--arch/arm/lib/semihosting.c232
-rw-r--r--arch/arm/mach-imx/imx8m/soc.c4
-rw-r--r--board/armltd/vexpress64/Kconfig71
-rw-r--r--board/armltd/vexpress64/MAINTAINERS5
-rw-r--r--board/armltd/vexpress64/vexpress64.c44
-rw-r--r--board/freescale/ls1046ardb/MAINTAINERS1
-rw-r--r--board/freescale/ls1046ardb/README76
-rw-r--r--board/freescale/ls1046ardb/ls1046ardb.c11
-rw-r--r--cmd/fdt.c6
-rw-r--r--common/spl/Makefile1
-rw-r--r--common/spl/spl_semihosting.c71
-rw-r--r--configs/vexpress_aemv8a_juno_defconfig33
-rw-r--r--configs/vexpress_aemv8a_semi_defconfig30
-rw-r--r--configs/vexpress_aemv8r_defconfig14
-rw-r--r--disk/part.c4
-rw-r--r--doc/README.semihosting38
-rw-r--r--doc/arch/arm64.rst3
-rw-r--r--doc/board/armltd/vexpress64.rst1
-rw-r--r--doc/board/nxp/index.rst1
-rw-r--r--doc/board/nxp/ls1046ardb.rst193
-rw-r--r--doc/usage/index.rst1
-rw-r--r--doc/usage/semihosting.rst107
-rw-r--r--drivers/serial/Kconfig35
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial-uclass.c26
-rw-r--r--drivers/serial/serial.c2
-rw-r--r--drivers/serial/serial_semihosting.c156
-rw-r--r--fs/Makefile1
-rw-r--r--fs/fs.c20
-rw-r--r--fs/semihostingfs.c115
-rw-r--r--include/configs/ls1046ardb.h2
-rw-r--r--include/configs/vexpress_aemv8.h159
-rw-r--r--include/fs.h1
-rw-r--r--include/semihosting.h149
-rw-r--r--include/semihostingfs.h21
-rw-r--r--include/serial.h19
51 files changed, 2390 insertions, 411 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 74d5263..d36e649 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1173,6 +1173,11 @@ F: arch/sandbox/
F: doc/arch/sandbox.rst
F: include/dt-bindings/*/sandbox*.h
+SEMIHOSTING
+R: Sean Anderson <sean.anderson@seco.com>
+S: Orphaned
+N: semihosting
+
SETEXPR
M: Roland Gaudig <roland.gaudig@weidmueller.com>
S: Maintained
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b5ca14f..f277929 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -403,11 +403,50 @@ config ARM_SMCCC
firmware (for example, PSCI) according to SMCCC.
config SEMIHOSTING
- bool "support boot from semihosting"
+ bool "Support ARM semihosting"
help
- In emulated environments, semihosting is a way for
- the hosted environment to call out to the emulator to
- retrieve files from the host machine.
+ Semihosting is a method for a target to communicate with a host
+ debugger. It uses special instructions which the debugger will trap
+ on and interpret. This allows U-Boot to read/write files, print to
+ the console, and execute arbitrary commands on the host system.
+
+ Enabling this option will add support for reading and writing files
+ on the host system. If you don't have a debugger attached then trying
+ to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
+
+config SEMIHOSTING_FALLBACK
+ bool "Recover gracefully when semihosting fails"
+ depends on SEMIHOSTING && ARM64
+ default y
+ help
+ Normally, if U-Boot makes a semihosting call and no debugger is
+ attached, then it will panic due to a synchronous abort
+ exception. This config adds an exception handler which will allow
+ U-Boot to recover. Say 'y' if unsure.
+
+config SPL_SEMIHOSTING
+ bool "Support ARM semihosting in SPL"
+ depends on SPL
+ help
+ Semihosting is a method for a target to communicate with a host
+ debugger. It uses special instructions which the debugger will trap
+ on and interpret. This allows U-Boot to read/write files, print to
+ the console, and execute arbitrary commands on the host system.
+
+ Enabling this option will add support for reading and writing files
+ on the host system. If you don't have a debugger attached then trying
+ to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
+
+config SPL_SEMIHOSTING_FALLBACK
+ bool "Recover gracefully when semihosting fails in SPL"
+ depends on SPL_SEMIHOSTING && ARM64
+ select ARMV8_SPL_EXCEPTION_VECTORS
+ default y
+ help
+ Normally, if U-Boot makes a semihosting call and no debugger is
+ attached, then it will panic due to a synchronous abort
+ exception. This config adds an exception handler which will allow
+ U-Boot to recover. Say 'y' if unsure.
config SYS_THUMB_BUILD
bool "Build U-Boot using the Thumb instruction set"
@@ -1250,34 +1289,19 @@ config ARCH_TEGRA
imply DISTRO_DEFAULTS
imply FAT_WRITE
-config TARGET_VEXPRESS64_AEMV8A
- bool "Support vexpress_aemv8a"
- select ARM64
- select GPIO_EXTRA_HEADER
- select PL01X_SERIAL
-
-config TARGET_VEXPRESS64_BASE_FVP
- bool "Support Versatile Express ARMv8a FVP BASE model"
+config ARCH_VEXPRESS64
+ bool "Support ARMv8 Arm Ltd. VExpress based boards and models"
select ARM64
- select GPIO_EXTRA_HEADER
- select PL01X_SERIAL
- select SEMIHOSTING
-
-config TARGET_VEXPRESS64_JUNO
- bool "Support Versatile Express Juno Development Platform"
- select ARM64
- select GPIO_EXTRA_HEADER
- select PL01X_SERIAL
select DM
+ select DM_SERIAL
+ select PL01X_SERIAL
select OF_CONTROL
select CLK
- select DM_SERIAL
- select ARM_PSCI_FW
- select PSCI_RESET
- select DM_ETH
select BLK
- select USB
- imply OF_HAS_PRIOR_STAGE
+ select MTD_NOR_FLASH if MTD
+ select FLASH_CFI_DRIVER if MTD
+ select ENV_IS_IN_FLASH if MTD
+ imply DISTRO_DEFAULTS
config TARGET_TOTAL_COMPUTE
bool "Support Total Compute Platform"
diff --git a/arch/arm/cpu/armv8/exceptions.S b/arch/arm/cpu/armv8/exceptions.S
index a15af72..504d566 100644
--- a/arch/arm/cpu/armv8/exceptions.S
+++ b/arch/arm/cpu/armv8/exceptions.S
@@ -77,14 +77,18 @@ _save_el_regs:
switch_el x11, 3f, 2f, 1f
3: mrs x1, esr_el3
mrs x2, elr_el3
+ mrs x3, spsr_el3
b 0f
2: mrs x1, esr_el2
mrs x2, elr_el2
+ mrs x3, spsr_el2
b 0f
1: mrs x1, esr_el1
mrs x2, elr_el1
+ mrs x3, spsr_el1
0:
- stp x2, x0, [sp, #-16]!
+ stp x1, x0, [sp, #-16]!
+ stp x3, x2, [sp, #-16]!
mov x0, sp
ret
@@ -98,7 +102,7 @@ _save_el_regs:
* This is the first part of the shared routine called into from all entries.
*/
exception_exit:
- ldp x2, x0, [sp],#16
+ ldp xzr, x2, [sp],#16
switch_el x11, 3f, 2f, 1f
3: msr elr_el3, x2
b _restore_regs
@@ -118,6 +122,7 @@ exception_exit:
* This is the second part of the shared routine called into from all entries.
*/
_restore_regs:
+ ldp xzr, x0, [sp],#16
ldp x1, x2, [sp],#16
ldp x3, x4, [sp],#16
ldp x5, x6, [sp],#16
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
index 564cc27..5f09ef0 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/spl.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c
@@ -12,6 +12,7 @@
#include <image.h>
#include <init.h>
#include <log.h>
+#include <semihosting.h>
#include <spl.h>
#include <asm/cache.h>
#include <asm/global_data.h>
@@ -27,6 +28,8 @@ DECLARE_GLOBAL_DATA_PTR;
u32 spl_boot_device(void)
{
+ if (semihosting_enabled())
+ return BOOT_DEVICE_SMH;
#ifdef CONFIG_SPL_MMC
return BOOT_DEVICE_MMC1;
#endif
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index beaaf15..99dc7bc 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1185,6 +1185,8 @@ dtb-$(CONFIG_TARGET_MX53PPD) += imx53-ppd.dtb
# TODO(Linus Walleij <linus.walleij@linaro.org>): Should us a single vexpress
# Kconfig option to build all of these. See examples above.
dtb-$(CONFIG_TARGET_VEXPRESS_CA9X4) += vexpress-v2p-ca9.dtb
+dtb-$(CONFIG_TARGET_VEXPRESS64_BASE_FVP) += fvp-base-revc.dtb
+dtb-$(CONFIG_TARGET_VEXPRESS64_BASER_FVP) += arm_fvp.dtb
dtb-$(CONFIG_TARGET_VEXPRESS64_JUNO) += juno-r2.dtb
dtb-$(CONFIG_TARGET_TOTAL_COMPUTE) += total_compute.dtb
diff --git a/arch/arm/dts/arm_fvp.dts b/arch/arm/dts/arm_fvp.dts
new file mode 100644
index 0000000..3a4ad5d
--- /dev/null
+++ b/arch/arm/dts/arm_fvp.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Empty device tree for the Arm Ltd FVP platform model
+
+ * Copyright 2022 Arm Ltd.
+ */
+
+/dts-v1/;
+
+/ {
+};
diff --git a/arch/arm/dts/fvp-base-revc.dts b/arch/arm/dts/fvp-base-revc.dts
new file mode 100644
index 0000000..269b649
--- /dev/null
+++ b/arch/arm/dts/fvp-base-revc.dts
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM Ltd. Fast Models
+ *
+ * Architecture Envelope Model (AEM) ARMv8-A
+ * ARMAEMv8AMPCT
+ *
+ * FVP Base RevC
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/memreserve/ 0x80000000 0x00010000;
+
+#include "rtsm_ve-motherboard.dtsi"
+#include "rtsm_ve-motherboard-rs2.dtsi"
+
+/ {
+ model = "FVP Base RevC";
+ compatible = "arm,fvp-base-revc", "arm,vexpress";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ aliases {
+ serial0 = &v2m_serial0;
+ serial1 = &v2m_serial1;
+ serial2 = &v2m_serial2;
+ serial3 = &v2m_serial3;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x000>;
+ enable-method = "psci";
+ };
+ cpu1: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ };
+ cpu2: cpu@200 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ };
+ cpu3: cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ };
+ cpu4: cpu@10000 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x10000>;
+ enable-method = "psci";
+ };
+ cpu5: cpu@10100 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x10100>;
+ enable-method = "psci";
+ };
+ cpu6: cpu@10200 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x10200>;
+ enable-method = "psci";
+ };
+ cpu7: cpu@10300 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x10300>;
+ enable-method = "psci";
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x00000000 0x80000000 0 0x80000000>,
+ <0x00000008 0x80000000 0 0x80000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* Chipselect 2,00000000 is physically at 0x18000000 */
+ vram: vram@18000000 {
+ /* 8 MB of designated video RAM */
+ compatible = "shared-dma-pool";
+ reg = <0x00000000 0x18000000 0 0x00800000>;
+ no-map;
+ };
+ };
+
+ gic: interrupt-controller@2f000000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ interrupt-controller;
+ reg = <0x0 0x2f000000 0 0x10000>, // GICD
+ <0x0 0x2f100000 0 0x200000>, // GICR
+ <0x0 0x2c000000 0 0x2000>, // GICC
+ <0x0 0x2c010000 0 0x2000>, // GICH
+ <0x0 0x2c02f000 0 0x2000>; // GICV
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+ its: msi-controller@2f020000 {
+ #msi-cells = <1>;
+ compatible = "arm,gic-v3-its";
+ reg = <0x0 0x2f020000 0x0 0x20000>; // GITS
+ msi-controller;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ spe-pmu {
+ compatible = "arm,statistical-profiling-extension-v1";
+ interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pci: pci@40000000 {
+ #address-cells = <0x3>;
+ #size-cells = <0x2>;
+ #interrupt-cells = <0x1>;
+ compatible = "pci-host-ecam-generic";
+ device_type = "pci";
+ bus-range = <0x0 0x1>;
+ reg = <0x0 0x40000000 0x0 0x10000000>;
+ ranges = <0x2000000 0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>;
+ interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic 0 0 GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic 0 0 GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic 0 0 GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ msi-map = <0x0 &its 0x0 0x10000>;
+ iommu-map = <0x0 &smmu 0x0 0x10000>;
+
+ dma-coherent;
+ };
+
+ smmu: iommu@2b400000 {
+ compatible = "arm,smmu-v3";
+ reg = <0x0 0x2b400000 0x0 0x100000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
+ dma-coherent;
+ #iommu-cells = <1>;
+ msi-parent = <&its 0x10000>;
+ };
+
+ panel {
+ compatible = "arm,rtsm-display", "panel-dpi";
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&clcd_pads>;
+ };
+ };
+ };
+
+ bus@8000000 {
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 63>;
+ interrupt-map = <0 0 0 &gic 0 0 GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 1 &gic 0 0 GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 2 &gic 0 0 GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 3 &gic 0 0 GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 4 &gic 0 0 GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 5 &gic 0 0 GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 6 &gic 0 0 GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 7 &gic 0 0 GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 8 &gic 0 0 GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 9 &gic 0 0 GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 10 &gic 0 0 GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 11 &gic 0 0 GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 12 &gic 0 0 GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 13 &gic 0 0 GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 14 &gic 0 0 GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 15 &gic 0 0 GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 16 &gic 0 0 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 17 &gic 0 0 GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 18 &gic 0 0 GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 19 &gic 0 0 GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 20 &gic 0 0 GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 21 &gic 0 0 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 22 &gic 0 0 GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 23 &gic 0 0 GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 24 &gic 0 0 GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 25 &gic 0 0 GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 26 &gic 0 0 GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 27 &gic 0 0 GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 28 &gic 0 0 GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 29 &gic 0 0 GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 30 &gic 0 0 GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 31 &gic 0 0 GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 32 &gic 0 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 33 &gic 0 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 34 &gic 0 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 35 &gic 0 0 GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 36 &gic 0 0 GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 37 &gic 0 0 GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 38 &gic 0 0 GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 39 &gic 0 0 GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 40 &gic 0 0 GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 41 &gic 0 0 GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 42 &gic 0 0 GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 43 &gic 0 0 GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 44 &gic 0 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
diff --git a/arch/arm/dts/rtsm_ve-motherboard-rs2.dtsi b/arch/arm/dts/rtsm_ve-motherboard-rs2.dtsi
new file mode 100644
index 0000000..33182d9
--- /dev/null
+++ b/arch/arm/dts/rtsm_ve-motherboard-rs2.dtsi
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM Ltd. Fast Models
+ *
+ * "rs2" extension for the v2m motherboard
+ */
+/ {
+ bus@8000000 {
+ motherboard-bus@8000000 {
+ arm,v2m-memory-map = "rs2";
+
+ iofpga-bus@300000000 {
+ virtio-p9@140000 {
+ compatible = "virtio,mmio";
+ reg = <0x140000 0x200>;
+ interrupts = <43>;
+ };
+
+ virtio-net@150000 {
+ compatible = "virtio,mmio";
+ reg = <0x150000 0x200>;
+ interrupts = <44>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/dts/rtsm_ve-motherboard.dtsi b/arch/arm/dts/rtsm_ve-motherboard.dtsi
new file mode 100644
index 0000000..5f6cab6
--- /dev/null
+++ b/arch/arm/dts/rtsm_ve-motherboard.dtsi
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM Ltd. Fast Models
+ *
+ * Versatile Express (VE) system model
+ * Motherboard component
+ *
+ * VEMotherBoard.lisa
+ */
+/ {
+ v2m_clk24mhz: clk24mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "v2m:clk24mhz";
+ };
+
+ v2m_refclk1mhz: refclk1mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000>;
+ clock-output-names = "v2m:refclk1mhz";
+ };
+
+ v2m_refclk32khz: refclk32khz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "v2m:refclk32khz";
+ };
+
+ v2m_fixed_3v3: v2m-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ mcc {
+ compatible = "arm,vexpress,config-bus";
+ arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+ v2m_oscclk1: oscclk1 {
+ /* CLCD clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 1>;
+ freq-range = <23750000 63500000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk1";
+ };
+
+ reset {
+ compatible = "arm,vexpress-reset";
+ arm,vexpress-sysreg,func = <5 0>;
+ };
+
+ muxfpga {
+ compatible = "arm,vexpress-muxfpga";
+ arm,vexpress-sysreg,func = <7 0>;
+ };
+
+ shutdown {
+ compatible = "arm,vexpress-shutdown";
+ arm,vexpress-sysreg,func = <8 0>;
+ };
+
+ reboot {
+ compatible = "arm,vexpress-reboot";
+ arm,vexpress-sysreg,func = <9 0>;
+ };
+
+ dvimode {
+ compatible = "arm,vexpress-dvimode";
+ arm,vexpress-sysreg,func = <11 0>;
+ };
+ };
+
+ bus@8000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0x8000000 0 0x8000000 0x18000000>;
+
+ motherboard-bus@8000000 {
+ compatible = "arm,vexpress,v2m-p1", "simple-bus";
+ #address-cells = <2>; /* SMB chipselect number and offset */
+ #size-cells = <1>;
+ ranges = <0 0 0 0x08000000 0x04000000>,
+ <1 0 0 0x14000000 0x04000000>,
+ <2 0 0 0x18000000 0x04000000>,
+ <3 0 0 0x1c000000 0x04000000>,
+ <4 0 0 0x0c000000 0x04000000>,
+ <5 0 0 0x10000000 0x04000000>;
+
+ flash@0 {
+ compatible = "arm,vexpress-flash", "cfi-flash";
+ reg = <0 0x00000000 0x04000000>,
+ <4 0x00000000 0x04000000>;
+ bank-width = <4>;
+ };
+
+ ethernet@202000000 {
+ compatible = "smsc,lan91c111";
+ reg = <2 0x02000000 0x10000>;
+ interrupts = <15>;
+ };
+
+ iofpga-bus@300000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 3 0 0x200000>;
+
+ v2m_sysreg: sysreg@10000 {
+ compatible = "arm,vexpress-sysreg";
+ reg = <0x010000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ v2m_sysctl: sysctl@20000 {
+ compatible = "arm,sp810", "arm,primecell";
+ reg = <0x020000 0x1000>;
+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
+ clock-names = "refclk", "timclk", "apb_pclk";
+ #clock-cells = <1>;
+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+ assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
+ assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
+ };
+
+ aaci@40000 {
+ compatible = "arm,pl041", "arm,primecell";
+ reg = <0x040000 0x1000>;
+ interrupts = <11>;
+ clocks = <&v2m_clk24mhz>;
+ clock-names = "apb_pclk";
+ };
+
+ mmc@50000 {
+ compatible = "arm,pl180", "arm,primecell";
+ reg = <0x050000 0x1000>;
+ interrupts = <9>, <10>;
+ cd-gpios = <&v2m_sysreg 0 0>;
+ wp-gpios = <&v2m_sysreg 1 0>;
+ max-frequency = <12000000>;
+ vmmc-supply = <&v2m_fixed_3v3>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "mclk", "apb_pclk";
+ };
+
+ kmi@60000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x060000 0x1000>;
+ interrupts = <12>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
+
+ kmi@70000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x070000 0x1000>;
+ interrupts = <13>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
+
+ v2m_serial0: serial@90000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x090000 0x1000>;
+ interrupts = <5>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ };
+
+ v2m_serial1: serial@a0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0a0000 0x1000>;
+ interrupts = <6>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ };
+
+ v2m_serial2: serial@b0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0b0000 0x1000>;
+ interrupts = <7>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ };
+
+ v2m_serial3: serial@c0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0c0000 0x1000>;
+ interrupts = <8>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ };
+
+ watchdog@f0000 {
+ compatible = "arm,sp805", "arm,primecell";
+ reg = <0x0f0000 0x1000>;
+ interrupts = <0>;
+ clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
+ clock-names = "wdog_clk", "apb_pclk";
+ };
+
+ v2m_timer01: timer@110000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x110000 0x1000>;
+ interrupts = <2>;
+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
+
+ v2m_timer23: timer@120000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x120000 0x1000>;
+ interrupts = <3>;
+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
+
+ virtio-block@130000 {
+ compatible = "virtio,mmio";
+ reg = <0x130000 0x200>;
+ interrupts = <42>;
+ };
+
+ rtc@170000 {
+ compatible = "arm,pl031", "arm,primecell";
+ reg = <0x170000 0x1000>;
+ interrupts = <4>;
+ clocks = <&v2m_clk24mhz>;
+ clock-names = "apb_pclk";
+ };
+
+ clcd@1f0000 {
+ compatible = "arm,pl111", "arm,primecell";
+ reg = <0x1f0000 0x1000>;
+ interrupt-names = "combined";
+ interrupts = <14>;
+ clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
+ clock-names = "clcdclk", "apb_pclk";
+ memory-region = <&vram>;
+
+ port {
+ clcd_pads: endpoint {
+ remote-endpoint = <&panel_in>;
+ arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+ };
+ };
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/include/asm/esr.h b/arch/arm/include/asm/esr.h
new file mode 100644
index 0000000..f19e4e7
--- /dev/null
+++ b/arch/arm/include/asm/esr.h
@@ -0,0 +1,343 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ */
+
+#ifndef __ASM_ESR_H
+#define __ASM_ESR_H
+
+#include <asm/memory.h>
+#include <linux/const.h>
+
+#define ESR_ELx_EC_UNKNOWN (0x00)
+#define ESR_ELx_EC_WFx (0x01)
+/* Unallocated EC: 0x02 */
+#define ESR_ELx_EC_CP15_32 (0x03)
+#define ESR_ELx_EC_CP15_64 (0x04)
+#define ESR_ELx_EC_CP14_MR (0x05)
+#define ESR_ELx_EC_CP14_LS (0x06)
+#define ESR_ELx_EC_FP_ASIMD (0x07)
+#define ESR_ELx_EC_CP10_ID (0x08) /* EL2 only */
+#define ESR_ELx_EC_PAC (0x09) /* EL2 and above */
+/* Unallocated EC: 0x0A - 0x0B */
+#define ESR_ELx_EC_CP14_64 (0x0C)
+#define ESR_ELx_EC_BTI (0x0D)
+#define ESR_ELx_EC_ILL (0x0E)
+/* Unallocated EC: 0x0F - 0x10 */
+#define ESR_ELx_EC_SVC32 (0x11)
+#define ESR_ELx_EC_HVC32 (0x12) /* EL2 only */
+#define ESR_ELx_EC_SMC32 (0x13) /* EL2 and above */
+/* Unallocated EC: 0x14 */
+#define ESR_ELx_EC_SVC64 (0x15)
+#define ESR_ELx_EC_HVC64 (0x16) /* EL2 and above */
+#define ESR_ELx_EC_SMC64 (0x17) /* EL2 and above */
+#define ESR_ELx_EC_SYS64 (0x18)
+#define ESR_ELx_EC_SVE (0x19)
+#define ESR_ELx_EC_ERET (0x1a) /* EL2 only */
+/* Unallocated EC: 0x1B */
+#define ESR_ELx_EC_FPAC (0x1C) /* EL1 and above */
+/* Unallocated EC: 0x1D - 0x1E */
+#define ESR_ELx_EC_IMP_DEF (0x1f) /* EL3 only */
+#define ESR_ELx_EC_IABT_LOW (0x20)
+#define ESR_ELx_EC_IABT_CUR (0x21)
+#define ESR_ELx_EC_PC_ALIGN (0x22)
+/* Unallocated EC: 0x23 */
+#define ESR_ELx_EC_DABT_LOW (0x24)
+#define ESR_ELx_EC_DABT_CUR (0x25)
+#define ESR_ELx_EC_SP_ALIGN (0x26)
+/* Unallocated EC: 0x27 */
+#define ESR_ELx_EC_FP_EXC32 (0x28)
+/* Unallocated EC: 0x29 - 0x2B */
+#define ESR_ELx_EC_FP_EXC64 (0x2C)
+/* Unallocated EC: 0x2D - 0x2E */
+#define ESR_ELx_EC_SERROR (0x2F)
+#define ESR_ELx_EC_BREAKPT_LOW (0x30)
+#define ESR_ELx_EC_BREAKPT_CUR (0x31)
+#define ESR_ELx_EC_SOFTSTP_LOW (0x32)
+#define ESR_ELx_EC_SOFTSTP_CUR (0x33)
+#define ESR_ELx_EC_WATCHPT_LOW (0x34)
+#define ESR_ELx_EC_WATCHPT_CUR (0x35)
+/* Unallocated EC: 0x36 - 0x37 */
+#define ESR_ELx_EC_BKPT32 (0x38)
+/* Unallocated EC: 0x39 */
+#define ESR_ELx_EC_VECTOR32 (0x3A) /* EL2 only */
+/* Unallocated EC: 0x3B */
+#define ESR_ELx_EC_BRK64 (0x3C)
+/* Unallocated EC: 0x3D - 0x3F */
+#define ESR_ELx_EC_MAX (0x3F)
+
+#define ESR_ELx_EC_SHIFT (26)
+#define ESR_ELx_EC_WIDTH (6)
+#define ESR_ELx_EC_MASK (UL(0x3F) << ESR_ELx_EC_SHIFT)
+#define ESR_ELx_EC(esr) (((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT)
+
+#define ESR_ELx_IL_SHIFT (25)
+#define ESR_ELx_IL (UL(1) << ESR_ELx_IL_SHIFT)
+#define ESR_ELx_ISS_MASK (ESR_ELx_IL - 1)
+
+/* ISS field definitions shared by different classes */
+#define ESR_ELx_WNR_SHIFT (6)
+#define ESR_ELx_WNR (UL(1) << ESR_ELx_WNR_SHIFT)
+
+/* Asynchronous Error Type */
+#define ESR_ELx_IDS_SHIFT (24)
+#define ESR_ELx_IDS (UL(1) << ESR_ELx_IDS_SHIFT)
+#define ESR_ELx_AET_SHIFT (10)
+#define ESR_ELx_AET (UL(0x7) << ESR_ELx_AET_SHIFT)
+
+#define ESR_ELx_AET_UC (UL(0) << ESR_ELx_AET_SHIFT)
+#define ESR_ELx_AET_UEU (UL(1) << ESR_ELx_AET_SHIFT)
+#define ESR_ELx_AET_UEO (UL(2) << ESR_ELx_AET_SHIFT)
+#define ESR_ELx_AET_UER (UL(3) << ESR_ELx_AET_SHIFT)
+#define ESR_ELx_AET_CE (UL(6) << ESR_ELx_AET_SHIFT)
+
+/* Shared ISS field definitions for Data/Instruction aborts */
+#define ESR_ELx_SET_SHIFT (11)
+#define ESR_ELx_SET_MASK (UL(3) << ESR_ELx_SET_SHIFT)
+#define ESR_ELx_FnV_SHIFT (10)
+#define ESR_ELx_FnV (UL(1) << ESR_ELx_FnV_SHIFT)
+#define ESR_ELx_EA_SHIFT (9)
+#define ESR_ELx_EA (UL(1) << ESR_ELx_EA_SHIFT)
+#define ESR_ELx_S1PTW_SHIFT (7)
+#define ESR_ELx_S1PTW (UL(1) << ESR_ELx_S1PTW_SHIFT)
+
+/* Shared ISS fault status code(IFSC/DFSC) for Data/Instruction aborts */
+#define ESR_ELx_FSC (0x3F)
+#define ESR_ELx_FSC_TYPE (0x3C)
+#define ESR_ELx_FSC_LEVEL (0x03)
+#define ESR_ELx_FSC_EXTABT (0x10)
+#define ESR_ELx_FSC_MTE (0x11)
+#define ESR_ELx_FSC_SERROR (0x11)
+#define ESR_ELx_FSC_ACCESS (0x08)
+#define ESR_ELx_FSC_FAULT (0x04)
+#define ESR_ELx_FSC_PERM (0x0C)
+
+/* ISS field definitions for Data Aborts */
+#define ESR_ELx_ISV_SHIFT (24)
+#define ESR_ELx_ISV (UL(1) << ESR_ELx_ISV_SHIFT)
+#define ESR_ELx_SAS_SHIFT (22)
+#define ESR_ELx_SAS (UL(3) << ESR_ELx_SAS_SHIFT)
+#define ESR_ELx_SSE_SHIFT (21)
+#define ESR_ELx_SSE (UL(1) << ESR_ELx_SSE_SHIFT)
+#define ESR_ELx_SRT_SHIFT (16)
+#define ESR_ELx_SRT_MASK (UL(0x1F) << ESR_ELx_SRT_SHIFT)
+#define ESR_ELx_SF_SHIFT (15)
+#define ESR_ELx_SF (UL(1) << ESR_ELx_SF_SHIFT)
+#define ESR_ELx_AR_SHIFT (14)
+#define ESR_ELx_AR (UL(1) << ESR_ELx_AR_SHIFT)
+#define ESR_ELx_CM_SHIFT (8)
+#define ESR_ELx_CM (UL(1) << ESR_ELx_CM_SHIFT)
+
+/* ISS field definitions for exceptions taken in to Hyp */
+#define ESR_ELx_CV (UL(1) << 24)
+#define ESR_ELx_COND_SHIFT (20)
+#define ESR_ELx_COND_MASK (UL(0xF) << ESR_ELx_COND_SHIFT)
+#define ESR_ELx_WFx_ISS_TI (UL(1) << 0)
+#define ESR_ELx_WFx_ISS_WFI (UL(0) << 0)
+#define ESR_ELx_WFx_ISS_WFE (UL(1) << 0)
+#define ESR_ELx_xVC_IMM_MASK ((1UL << 16) - 1)
+
+#define DISR_EL1_IDS (UL(1) << 24)
+/*
+ * DISR_EL1 and ESR_ELx share the bottom 13 bits, but the RES0 bits may mean
+ * different things in the future...
+ */
+#define DISR_EL1_ESR_MASK (ESR_ELx_AET | ESR_ELx_EA | ESR_ELx_FSC)
+
+/* ESR value templates for specific events */
+#define ESR_ELx_WFx_MASK (ESR_ELx_EC_MASK | ESR_ELx_WFx_ISS_TI)
+#define ESR_ELx_WFx_WFI_VAL ((ESR_ELx_EC_WFx << ESR_ELx_EC_SHIFT) | \
+ ESR_ELx_WFx_ISS_WFI)
+
+/* BRK instruction trap from AArch64 state */
+#define ESR_ELx_BRK64_ISS_COMMENT_MASK 0xffff
+
+/* ISS field definitions for System instruction traps */
+#define ESR_ELx_SYS64_ISS_RES0_SHIFT 22
+#define ESR_ELx_SYS64_ISS_RES0_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_RES0_SHIFT)
+#define ESR_ELx_SYS64_ISS_DIR_MASK 0x1
+#define ESR_ELx_SYS64_ISS_DIR_READ 0x1
+#define ESR_ELx_SYS64_ISS_DIR_WRITE 0x0
+
+#define ESR_ELx_SYS64_ISS_RT_SHIFT 5
+#define ESR_ELx_SYS64_ISS_RT_MASK (UL(0x1f) << ESR_ELx_SYS64_ISS_RT_SHIFT)
+#define ESR_ELx_SYS64_ISS_CRM_SHIFT 1
+#define ESR_ELx_SYS64_ISS_CRM_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRM_SHIFT)
+#define ESR_ELx_SYS64_ISS_CRN_SHIFT 10
+#define ESR_ELx_SYS64_ISS_CRN_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRN_SHIFT)
+#define ESR_ELx_SYS64_ISS_OP1_SHIFT 14
+#define ESR_ELx_SYS64_ISS_OP1_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP1_SHIFT)
+#define ESR_ELx_SYS64_ISS_OP2_SHIFT 17
+#define ESR_ELx_SYS64_ISS_OP2_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP2_SHIFT)
+#define ESR_ELx_SYS64_ISS_OP0_SHIFT 20
+#define ESR_ELx_SYS64_ISS_OP0_MASK (UL(0x3) << ESR_ELx_SYS64_ISS_OP0_SHIFT)
+#define ESR_ELx_SYS64_ISS_SYS_MASK (ESR_ELx_SYS64_ISS_OP0_MASK | \
+ ESR_ELx_SYS64_ISS_OP1_MASK | \
+ ESR_ELx_SYS64_ISS_OP2_MASK | \
+ ESR_ELx_SYS64_ISS_CRN_MASK | \
+ ESR_ELx_SYS64_ISS_CRM_MASK)
+#define ESR_ELx_SYS64_ISS_SYS_VAL(op0, op1, op2, crn, crm) \
+ (((op0) << ESR_ELx_SYS64_ISS_OP0_SHIFT) | \
+ ((op1) << ESR_ELx_SYS64_ISS_OP1_SHIFT) | \
+ ((op2) << ESR_ELx_SYS64_ISS_OP2_SHIFT) | \
+ ((crn) << ESR_ELx_SYS64_ISS_CRN_SHIFT) | \
+ ((crm) << ESR_ELx_SYS64_ISS_CRM_SHIFT))
+
+#define ESR_ELx_SYS64_ISS_SYS_OP_MASK (ESR_ELx_SYS64_ISS_SYS_MASK | \
+ ESR_ELx_SYS64_ISS_DIR_MASK)
+#define ESR_ELx_SYS64_ISS_RT(esr) \
+ (((esr) & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT)
+/*
+ * User space cache operations have the following sysreg encoding
+ * in System instructions.
+ * op0=1, op1=3, op2=1, crn=7, crm={ 5, 10, 11, 12, 13, 14 }, WRITE (L=0)
+ */
+#define ESR_ELx_SYS64_ISS_CRM_DC_CIVAC 14
+#define ESR_ELx_SYS64_ISS_CRM_DC_CVADP 13
+#define ESR_ELx_SYS64_ISS_CRM_DC_CVAP 12
+#define ESR_ELx_SYS64_ISS_CRM_DC_CVAU 11
+#define ESR_ELx_SYS64_ISS_CRM_DC_CVAC 10
+#define ESR_ELx_SYS64_ISS_CRM_IC_IVAU 5
+
+#define ESR_ELx_SYS64_ISS_EL0_CACHE_OP_MASK (ESR_ELx_SYS64_ISS_OP0_MASK | \
+ ESR_ELx_SYS64_ISS_OP1_MASK | \
+ ESR_ELx_SYS64_ISS_OP2_MASK | \
+ ESR_ELx_SYS64_ISS_CRN_MASK | \
+ ESR_ELx_SYS64_ISS_DIR_MASK)
+#define ESR_ELx_SYS64_ISS_EL0_CACHE_OP_VAL \
+ (ESR_ELx_SYS64_ISS_SYS_VAL(1, 3, 1, 7, 0) | \
+ ESR_ELx_SYS64_ISS_DIR_WRITE)
+/*
+ * User space MRS operations which are supported for emulation
+ * have the following sysreg encoding in System instructions.
+ * op0 = 3, op1= 0, crn = 0, {crm = 0, 4-7}, READ (L = 1)
+ */
+#define ESR_ELx_SYS64_ISS_SYS_MRS_OP_MASK (ESR_ELx_SYS64_ISS_OP0_MASK | \
+ ESR_ELx_SYS64_ISS_OP1_MASK | \
+ ESR_ELx_SYS64_ISS_CRN_MASK | \
+ ESR_ELx_SYS64_ISS_DIR_MASK)
+#define ESR_ELx_SYS64_ISS_SYS_MRS_OP_VAL \
+ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 0, 0, 0, 0) | \
+ ESR_ELx_SYS64_ISS_DIR_READ)
+
+#define ESR_ELx_SYS64_ISS_SYS_CTR ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 1, 0, 0)
+#define ESR_ELx_SYS64_ISS_SYS_CTR_READ (ESR_ELx_SYS64_ISS_SYS_CTR | \
+ ESR_ELx_SYS64_ISS_DIR_READ)
+
+#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
+ ESR_ELx_SYS64_ISS_DIR_READ)
+
+#define ESR_ELx_SYS64_ISS_SYS_CNTVCTSS (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 6, 14, 0) | \
+ ESR_ELx_SYS64_ISS_DIR_READ)
+
+#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \
+ ESR_ELx_SYS64_ISS_DIR_READ)
+
+#define esr_sys64_to_sysreg(e) \
+ sys_reg((((e) & ESR_ELx_SYS64_ISS_OP0_MASK) >> \
+ ESR_ELx_SYS64_ISS_OP0_SHIFT), \
+ (((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >> \
+ ESR_ELx_SYS64_ISS_OP1_SHIFT), \
+ (((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >> \
+ ESR_ELx_SYS64_ISS_CRN_SHIFT), \
+ (((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >> \
+ ESR_ELx_SYS64_ISS_CRM_SHIFT), \
+ (((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >> \
+ ESR_ELx_SYS64_ISS_OP2_SHIFT))
+
+#define esr_cp15_to_sysreg(e) \
+ sys_reg(3, \
+ (((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >> \
+ ESR_ELx_SYS64_ISS_OP1_SHIFT), \
+ (((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >> \
+ ESR_ELx_SYS64_ISS_CRN_SHIFT), \
+ (((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >> \
+ ESR_ELx_SYS64_ISS_CRM_SHIFT), \
+ (((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >> \
+ ESR_ELx_SYS64_ISS_OP2_SHIFT))
+
+/*
+ * ISS field definitions for floating-point exception traps
+ * (FP_EXC_32/FP_EXC_64).
+ *
+ * (The FPEXC_* constants are used instead for common bits.)
+ */
+
+#define ESR_ELx_FP_EXC_TFV (UL(1) << 23)
+
+/*
+ * ISS field definitions for CP15 accesses
+ */
+#define ESR_ELx_CP15_32_ISS_DIR_MASK 0x1
+#define ESR_ELx_CP15_32_ISS_DIR_READ 0x1
+#define ESR_ELx_CP15_32_ISS_DIR_WRITE 0x0
+
+#define ESR_ELx_CP15_32_ISS_RT_SHIFT 5
+#define ESR_ELx_CP15_32_ISS_RT_MASK (UL(0x1f) << ESR_ELx_CP15_32_ISS_RT_SHIFT)
+#define ESR_ELx_CP15_32_ISS_CRM_SHIFT 1
+#define ESR_ELx_CP15_32_ISS_CRM_MASK (UL(0xf) << ESR_ELx_CP15_32_ISS_CRM_SHIFT)
+#define ESR_ELx_CP15_32_ISS_CRN_SHIFT 10
+#define ESR_ELx_CP15_32_ISS_CRN_MASK (UL(0xf) << ESR_ELx_CP15_32_ISS_CRN_SHIFT)
+#define ESR_ELx_CP15_32_ISS_OP1_SHIFT 14
+#define ESR_ELx_CP15_32_ISS_OP1_MASK (UL(0x7) << ESR_ELx_CP15_32_ISS_OP1_SHIFT)
+#define ESR_ELx_CP15_32_ISS_OP2_SHIFT 17
+#define ESR_ELx_CP15_32_ISS_OP2_MASK (UL(0x7) << ESR_ELx_CP15_32_ISS_OP2_SHIFT)
+
+#define ESR_ELx_CP15_32_ISS_SYS_MASK (ESR_ELx_CP15_32_ISS_OP1_MASK | \
+ ESR_ELx_CP15_32_ISS_OP2_MASK | \
+ ESR_ELx_CP15_32_ISS_CRN_MASK | \
+ ESR_ELx_CP15_32_ISS_CRM_MASK | \
+ ESR_ELx_CP15_32_ISS_DIR_MASK)
+#define ESR_ELx_CP15_32_ISS_SYS_VAL(op1, op2, crn, crm) \
+ (((op1) << ESR_ELx_CP15_32_ISS_OP1_SHIFT) | \
+ ((op2) << ESR_ELx_CP15_32_ISS_OP2_SHIFT) | \
+ ((crn) << ESR_ELx_CP15_32_ISS_CRN_SHIFT) | \
+ ((crm) << ESR_ELx_CP15_32_ISS_CRM_SHIFT))
+
+#define ESR_ELx_CP15_64_ISS_DIR_MASK 0x1
+#define ESR_ELx_CP15_64_ISS_DIR_READ 0x1
+#define ESR_ELx_CP15_64_ISS_DIR_WRITE 0x0
+
+#define ESR_ELx_CP15_64_ISS_RT_SHIFT 5
+#define ESR_ELx_CP15_64_ISS_RT_MASK (UL(0x1f) << ESR_ELx_CP15_64_ISS_RT_SHIFT)
+
+#define ESR_ELx_CP15_64_ISS_RT2_SHIFT 10
+#define ESR_ELx_CP15_64_ISS_RT2_MASK (UL(0x1f) << ESR_ELx_CP15_64_ISS_RT2_SHIFT)
+
+#define ESR_ELx_CP15_64_ISS_OP1_SHIFT 16
+#define ESR_ELx_CP15_64_ISS_OP1_MASK (UL(0xf) << ESR_ELx_CP15_64_ISS_OP1_SHIFT)
+#define ESR_ELx_CP15_64_ISS_CRM_SHIFT 1
+#define ESR_ELx_CP15_64_ISS_CRM_MASK (UL(0xf) << ESR_ELx_CP15_64_ISS_CRM_SHIFT)
+
+#define ESR_ELx_CP15_64_ISS_SYS_VAL(op1, crm) \
+ (((op1) << ESR_ELx_CP15_64_ISS_OP1_SHIFT) | \
+ ((crm) << ESR_ELx_CP15_64_ISS_CRM_SHIFT))
+
+#define ESR_ELx_CP15_64_ISS_SYS_MASK (ESR_ELx_CP15_64_ISS_OP1_MASK | \
+ ESR_ELx_CP15_64_ISS_CRM_MASK | \
+ ESR_ELx_CP15_64_ISS_DIR_MASK)
+
+#define ESR_ELx_CP15_64_ISS_SYS_CNTVCT (ESR_ELx_CP15_64_ISS_SYS_VAL(1, 14) | \
+ ESR_ELx_CP15_64_ISS_DIR_READ)
+
+#define ESR_ELx_CP15_64_ISS_SYS_CNTVCTSS (ESR_ELx_CP15_64_ISS_SYS_VAL(9, 14) | \
+ ESR_ELx_CP15_64_ISS_DIR_READ)
+
+#define ESR_ELx_CP15_32_ISS_SYS_CNTFRQ (ESR_ELx_CP15_32_ISS_SYS_VAL(0, 0, 14, 0) |\
+ ESR_ELx_CP15_32_ISS_DIR_READ)
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+
+static inline bool esr_is_data_abort(u32 esr)
+{
+ const u32 ec = ESR_ELx_EC(esr);
+
+ return ec == ESR_ELx_EC_DABT_LOW || ec == ESR_ELx_EC_DABT_CUR;
+}
+
+const char *esr_get_class_string(u32 esr);
+#endif /* __ASSEMBLY */
+
+#endif /* __ASM_ESR_H */
diff --git a/arch/arm/include/asm/proc-armv/ptrace.h b/arch/arm/include/asm/proc-armv/ptrace.h
index e37ad8f..2db60d5 100644
--- a/arch/arm/include/asm/proc-armv/ptrace.h
+++ b/arch/arm/include/asm/proc-armv/ptrace.h
@@ -14,6 +14,79 @@
#define PCMASK 0
+/*
+ * PSR bits
+ */
+#define PSR_MODE_EL0t 0x00000000
+#define PSR_MODE_EL1t 0x00000004
+#define PSR_MODE_EL1h 0x00000005
+#define PSR_MODE_EL2t 0x00000008
+#define PSR_MODE_EL2h 0x00000009
+#define PSR_MODE_EL3t 0x0000000c
+#define PSR_MODE_EL3h 0x0000000d
+#define PSR_MODE_MASK 0x0000000f
+
+/* AArch32 CPSR bits */
+#define PSR_MODE32_BIT 0x00000010
+
+/* AArch64 SPSR bits */
+#define PSR_F_BIT 0x00000040
+#define PSR_I_BIT 0x00000080
+#define PSR_A_BIT 0x00000100
+#define PSR_D_BIT 0x00000200
+#define PSR_BTYPE_MASK 0x00000c00
+#define PSR_SSBS_BIT 0x00001000
+#define PSR_PAN_BIT 0x00400000
+#define PSR_UAO_BIT 0x00800000
+#define PSR_DIT_BIT 0x01000000
+#define PSR_TCO_BIT 0x02000000
+#define PSR_V_BIT 0x10000000
+#define PSR_C_BIT 0x20000000
+#define PSR_Z_BIT 0x40000000
+#define PSR_N_BIT 0x80000000
+
+#define PSR_BTYPE_SHIFT 10
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f 0xff000000 /* Flags */
+#define PSR_s 0x00ff0000 /* Status */
+#define PSR_x 0x0000ff00 /* Extension */
+#define PSR_c 0x000000ff /* Control */
+
+/* Convenience names for the values of PSTATE.BTYPE */
+#define PSR_BTYPE_NONE (0b00 << PSR_BTYPE_SHIFT)
+#define PSR_BTYPE_JC (0b01 << PSR_BTYPE_SHIFT)
+#define PSR_BTYPE_C (0b10 << PSR_BTYPE_SHIFT)
+#define PSR_BTYPE_J (0b11 << PSR_BTYPE_SHIFT)
+
+/* SPSR_ELx bits for exceptions taken from AArch32 */
+#define PSR_AA32_MODE_MASK 0x0000001f
+#define PSR_AA32_MODE_USR 0x00000010
+#define PSR_AA32_MODE_FIQ 0x00000011
+#define PSR_AA32_MODE_IRQ 0x00000012
+#define PSR_AA32_MODE_SVC 0x00000013
+#define PSR_AA32_MODE_ABT 0x00000017
+#define PSR_AA32_MODE_HYP 0x0000001a
+#define PSR_AA32_MODE_UND 0x0000001b
+#define PSR_AA32_MODE_SYS 0x0000001f
+#define PSR_AA32_T_BIT 0x00000020
+#define PSR_AA32_F_BIT 0x00000040
+#define PSR_AA32_I_BIT 0x00000080
+#define PSR_AA32_A_BIT 0x00000100
+#define PSR_AA32_E_BIT 0x00000200
+#define PSR_AA32_PAN_BIT 0x00400000
+#define PSR_AA32_SSBS_BIT 0x00800000
+#define PSR_AA32_DIT_BIT 0x01000000
+#define PSR_AA32_Q_BIT 0x08000000
+#define PSR_AA32_V_BIT 0x10000000
+#define PSR_AA32_C_BIT 0x20000000
+#define PSR_AA32_Z_BIT 0x40000000
+#define PSR_AA32_N_BIT 0x80000000
+#define PSR_AA32_IT_MASK 0x0600fc00 /* If-Then execution state mask */
+#define PSR_AA32_GE_MASK 0x000f0000
+
#ifndef __ASSEMBLY__
/*
@@ -21,7 +94,9 @@
* on the stack during an exception.
*/
struct pt_regs {
+ unsigned long spsr;
unsigned long elr;
+ unsigned long esr;
unsigned long regs[31];
};
diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h
index e568af2..b5790bd 100644
--- a/arch/arm/include/asm/spl.h
+++ b/arch/arm/include/asm/spl.h
@@ -30,6 +30,7 @@ enum {
BOOT_DEVICE_DFU,
BOOT_DEVICE_XIP,
BOOT_DEVICE_BOOTROM,
+ BOOT_DEVICE_SMH,
BOOT_DEVICE_NONE
};
#endif
diff --git a/arch/arm/include/asm/u-boot-arm.h b/arch/arm/include/asm/u-boot-arm.h
index 0b93cc4..aef0487 100644
--- a/arch/arm/include/asm/u-boot-arm.h
+++ b/arch/arm/include/asm/u-boot-arm.h
@@ -46,13 +46,8 @@ void do_software_interrupt(struct pt_regs *pt_regs);
void do_prefetch_abort(struct pt_regs *pt_regs);
void do_data_abort(struct pt_regs *pt_regs);
void do_not_used(struct pt_regs *pt_regs);
-#ifdef CONFIG_ARM64
-void do_fiq(struct pt_regs *pt_regs, unsigned int esr);
-void do_irq(struct pt_regs *pt_regs, unsigned int esr);
-#else
void do_fiq(struct pt_regs *pt_regs);
-void do_irq(struct pt_regs *pt_regswq);
-#endif
+void do_irq(struct pt_regs *pt_regs);
void reset_misc(void);
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index c48e1f6..594fc12 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -46,7 +46,7 @@ else
obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o
obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o
endif
-obj-$(CONFIG_SEMIHOSTING) += semihosting.o
+obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
obj-y += bdinfo.o
obj-y += sections.o
diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c
index c653e67..2e09141 100644
--- a/arch/arm/lib/interrupts_64.c
+++ b/arch/arm/lib/interrupts_64.c
@@ -5,11 +5,13 @@
*/
#include <common.h>
+#include <asm/esr.h>
#include <asm/global_data.h>
#include <asm/ptrace.h>
#include <irq_func.h>
#include <linux/compiler.h>
#include <efi_loader.h>
+#include <semihosting.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -64,12 +66,55 @@ void show_regs(struct pt_regs *regs)
}
/*
+ * Try to "emulate" a semihosting call in the event that we don't have a
+ * debugger attached.
+ */
+static bool smh_emulate_trap(struct pt_regs *regs)
+{
+ int size;
+
+ if (ESR_ELx_EC(regs->esr) != ESR_ELx_EC_UNKNOWN)
+ return false;
+
+ if (regs->spsr & PSR_MODE32_BIT) {
+ if (regs->spsr & PSR_AA32_T_BIT) {
+ u16 *insn = (u16 *)ALIGN_DOWN(regs->elr, 2);
+
+ if (*insn != SMH_T32_SVC && *insn != SMH_T32_HLT)
+ return false;
+ size = 2;
+ } else {
+ u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
+
+ if (*insn != SMH_A32_SVC && *insn != SMH_A32_HLT)
+ return false;
+ size = 4;
+ }
+ } else {
+ u32 *insn = (u32 *)ALIGN_DOWN(regs->elr, 4);
+
+ if (*insn != SMH_A64_HLT)
+ return false;
+ size = 4;
+ }
+
+ /* Avoid future semihosting calls */
+ disable_semihosting();
+
+ /* Just pretend the call failed */
+ regs->regs[0] = -1;
+ regs->elr += size;
+ return true;
+}
+
+/*
* do_bad_sync handles the impossible case in the Synchronous Abort vector.
*/
-void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
+void do_bad_sync(struct pt_regs *pt_regs)
{
efi_restore_gd();
- printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
+ printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08lx\n",
+ pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
@@ -78,10 +123,10 @@ void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
/*
* do_bad_irq handles the impossible case in the Irq vector.
*/
-void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
+void do_bad_irq(struct pt_regs *pt_regs)
{
efi_restore_gd();
- printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
+ printf("Bad mode in \"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
@@ -90,10 +135,10 @@ void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
/*
* do_bad_fiq handles the impossible case in the Fiq vector.
*/
-void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
+void do_bad_fiq(struct pt_regs *pt_regs)
{
efi_restore_gd();
- printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
+ printf("Bad mode in \"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
@@ -102,10 +147,10 @@ void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
/*
* do_bad_error handles the impossible case in the Error vector.
*/
-void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
+void do_bad_error(struct pt_regs *pt_regs)
{
efi_restore_gd();
- printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
+ printf("Bad mode in \"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
@@ -114,10 +159,13 @@ void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
/*
* do_sync handles the Synchronous Abort exception.
*/
-void do_sync(struct pt_regs *pt_regs, unsigned int esr)
+void do_sync(struct pt_regs *pt_regs)
{
+ if (CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK) &&
+ smh_emulate_trap(pt_regs))
+ return;
efi_restore_gd();
- printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
+ printf("\"Synchronous Abort\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
@@ -126,10 +174,10 @@ void do_sync(struct pt_regs *pt_regs, unsigned int esr)
/*
* do_irq handles the Irq exception.
*/
-void do_irq(struct pt_regs *pt_regs, unsigned int esr)
+void do_irq(struct pt_regs *pt_regs)
{
efi_restore_gd();
- printf("\"Irq\" handler, esr 0x%08x\n", esr);
+ printf("\"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
@@ -138,10 +186,10 @@ void do_irq(struct pt_regs *pt_regs, unsigned int esr)
/*
* do_fiq handles the Fiq exception.
*/
-void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
+void do_fiq(struct pt_regs *pt_regs)
{
efi_restore_gd();
- printf("\"Fiq\" handler, esr 0x%08x\n", esr);
+ printf("\"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
@@ -153,10 +201,10 @@ void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
* it is defined with weak attribute and can be redefined
* in processor specific code.
*/
-void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
+void __weak do_error(struct pt_regs *pt_regs)
{
efi_restore_gd();
- printf("\"Error\" handler, esr 0x%08x\n", esr);
+ printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
show_efi_loaded_images(pt_regs);
panic("Resetting CPU ...\n");
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c
index 9fd8245..dbea2b0 100644
--- a/arch/arm/lib/semihosting.c
+++ b/arch/arm/lib/semihosting.c
@@ -1,28 +1,29 @@
// SPDX-License-Identifier: GPL-2.0+
/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
* Copyright 2014 Broadcom Corporation
*/
/*
- * Minimal semihosting implementation for reading files into memory. If more
- * features like writing files or console output are required they can be
- * added later. This code has been tested on arm64/aarch64 fastmodel only.
- * An untested placeholder exists for armv7 architectures, but since they
- * are commonly available in silicon now, fastmodel usage makes less sense
- * for them.
+ * This code has been tested on arm64/aarch64 fastmodel only. An untested
+ * placeholder exists for armv7 architectures, but since they are commonly
+ * available in silicon now, fastmodel usage makes less sense for them.
*/
#include <common.h>
-#include <command.h>
-#include <env.h>
#include <log.h>
+#include <semihosting.h>
#define SYSOPEN 0x01
#define SYSCLOSE 0x02
+#define SYSWRITEC 0x03
+#define SYSWRITE0 0x04
+#define SYSWRITE 0x05
#define SYSREAD 0x06
+#define SYSREADC 0x07
+#define SYSISERROR 0x08
+#define SYSSEEK 0x0A
#define SYSFLEN 0x0C
-
-#define MODE_READ 0x0
-#define MODE_READBIN 0x1
+#define SYSERRNO 0x13
/*
* Call the handler
@@ -41,32 +42,54 @@ static noinline long smh_trap(unsigned int sysnum, void *addr)
return result;
}
-/*
- * Open a file on the host. Mode is "r" or "rb" currently. Returns a file
- * descriptor or -1 on error.
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+static bool _semihosting_enabled = true;
+static bool try_semihosting = true;
+
+bool semihosting_enabled(void)
+{
+ if (try_semihosting) {
+ smh_trap(SYSERRNO, NULL);
+ try_semihosting = false;
+ }
+
+ return _semihosting_enabled;
+}
+
+void disable_semihosting(void)
+{
+ _semihosting_enabled = false;
+}
+#endif
+
+/**
+ * smh_errno() - Read the host's errno
+ *
+ * This gets the value of the host's errno and negates it. The host's errno may
+ * or may not be set, so only call this function if a previous semihosting call
+ * has failed.
+ *
+ * Return: a negative error value
*/
-static long smh_open(const char *fname, char *modestr)
+static int smh_errno(void)
+{
+ long ret = smh_trap(SYSERRNO, NULL);
+
+ if (ret > 0 && ret < INT_MAX)
+ return -ret;
+ return -EIO;
+}
+
+long smh_open(const char *fname, enum smh_open_mode mode)
{
long fd;
- unsigned long mode;
struct smh_open_s {
const char *fname;
unsigned long mode;
size_t len;
} open;
- debug("%s: file \'%s\', mode \'%s\'\n", __func__, fname, modestr);
-
- /* Check the file mode */
- if (!(strcmp(modestr, "r"))) {
- mode = MODE_READ;
- } else if (!(strcmp(modestr, "rb"))) {
- mode = MODE_READBIN;
- } else {
- printf("%s: ERROR mode \'%s\' not supported\n", __func__,
- modestr);
- return -1;
- }
+ debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
open.fname = fname;
open.len = strlen(fname);
@@ -75,23 +98,26 @@ static long smh_open(const char *fname, char *modestr)
/* Open the file on the host */
fd = smh_trap(SYSOPEN, &open);
if (fd == -1)
- printf("%s: ERROR fd %ld for file \'%s\'\n", __func__, fd,
- fname);
-
+ return smh_errno();
return fd;
}
-/*
- * Read 'len' bytes of file into 'memp'. Returns 0 on success, else failure
+/**
+ * struct smg_rdwr_s - Arguments for read and write
+ * @fd: A file descriptor returned from smh_open()
+ * @memp: Pointer to a buffer of memory of at least @len bytes
+ * @len: The number of bytes to read or write
*/
-static long smh_read(long fd, void *memp, size_t len)
+struct smh_rdwr_s {
+ long fd;
+ void *memp;
+ size_t len;
+};
+
+long smh_read(long fd, void *memp, size_t len)
{
long ret;
- struct smh_read_s {
- long fd;
- void *memp;
- size_t len;
- } read;
+ struct smh_rdwr_s read;
debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
@@ -100,25 +126,30 @@ static long smh_read(long fd, void *memp, size_t len)
read.len = len;
ret = smh_trap(SYSREAD, &read);
- if (ret < 0) {
- /*
- * The ARM handler allows for returning partial lengths,
- * but in practice this never happens so rather than create
- * hard to maintain partial read loops and such, just fail
- * with an error message.
- */
- printf("%s: ERROR ret %ld, fd %ld, len %zu memp %p\n",
- __func__, ret, fd, len, memp);
- return -1;
- }
+ if (ret < 0)
+ return smh_errno();
+ return len - ret;
+}
+
+long smh_write(long fd, const void *memp, size_t len, ulong *written)
+{
+ long ret;
+ struct smh_rdwr_s write;
+
+ debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
+ write.fd = fd;
+ write.memp = (void *)memp;
+ write.len = len;
+
+ ret = smh_trap(SYSWRITE, &write);
+ *written = len - ret;
+ if (ret)
+ return smh_errno();
return 0;
}
-/*
- * Close the file using the file descriptor
- */
-static long smh_close(long fd)
+long smh_close(long fd)
{
long ret;
@@ -126,15 +157,11 @@ static long smh_close(long fd)
ret = smh_trap(SYSCLOSE, &fd);
if (ret == -1)
- printf("%s: ERROR fd %ld\n", __func__, fd);
-
- return ret;
+ return smh_errno();
+ return 0;
}
-/*
- * Get the file length from the file descriptor
- */
-static long smh_len_fd(long fd)
+long smh_flen(long fd)
{
long ret;
@@ -142,77 +169,40 @@ static long smh_len_fd(long fd)
ret = smh_trap(SYSFLEN, &fd);
if (ret == -1)
- printf("%s: ERROR ret %ld, fd %ld\n", __func__, ret, fd);
-
+ return smh_errno();
return ret;
}
-static int smh_load_file(const char * const name, ulong load_addr,
- ulong *end_addr)
+long smh_seek(long fd, long pos)
{
- long fd;
- long len;
long ret;
+ struct smh_seek_s {
+ long fd;
+ long pos;
+ } seek;
- fd = smh_open(name, "rb");
- if (fd == -1)
- return -1;
+ debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
- len = smh_len_fd(fd);
- if (len < 0) {
- smh_close(fd);
- return -1;
- }
-
- ret = smh_read(fd, (void *)load_addr, len);
- smh_close(fd);
-
- if (ret == 0) {
- *end_addr = load_addr + len - 1;
- printf("loaded file %s from %08lX to %08lX, %08lX bytes\n",
- name,
- load_addr,
- *end_addr,
- len);
- } else {
- printf("read failed\n");
- return 0;
- }
+ seek.fd = fd;
+ seek.pos = pos;
+ ret = smh_trap(SYSSEEK, &seek);
+ if (ret)
+ return smh_errno();
return 0;
}
-static int do_smhload(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
+int smh_getc(void)
{
- if (argc == 3 || argc == 4) {
- ulong load_addr;
- ulong end_addr = 0;
- int ret;
- char end_str[64];
-
- load_addr = hextoul(argv[2], NULL);
- if (!load_addr)
- return -1;
-
- ret = smh_load_file(argv[1], load_addr, &end_addr);
- if (ret < 0)
- return CMD_RET_FAILURE;
-
- /* Optionally save returned end to the environment */
- if (argc == 4) {
- sprintf(end_str, "0x%08lx", end_addr);
- env_set(argv[3], end_str);
- }
- } else {
- return CMD_RET_USAGE;
- }
- return 0;
+ return smh_trap(SYSREADC, NULL);
+}
+
+void smh_putc(char ch)
+{
+ smh_trap(SYSWRITEC, &ch);
}
-U_BOOT_CMD(smhload, 4, 0, do_smhload, "load a file using semihosting",
- "<file> 0x<address> [end var]\n"
- " - load a semihosted file to the address specified\n"
- " if the optional [end var] is specified, the end\n"
- " address of the file will be stored in this environment\n"
- " variable.\n");
+void smh_puts(const char *s)
+{
+ smh_trap(SYSWRITE0, (char *)s);
+}
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index 838f0a3..7397b99 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -1295,7 +1295,7 @@ void imx_tmu_arch_init(void *reg_base)
#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
bool serror_need_skip = true;
-void do_error(struct pt_regs *pt_regs, unsigned int esr)
+void do_error(struct pt_regs *pt_regs)
{
/*
* If stack is still in ROM reserved OCRAM not switch to SPL,
@@ -1320,7 +1320,7 @@ void do_error(struct pt_regs *pt_regs, unsigned int esr)
}
efi_restore_gd();
- printf("\"Error\" handler, esr 0x%08x\n", esr);
+ printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
show_regs(pt_regs);
panic("Resetting CPU ...\n");
}
diff --git a/board/armltd/vexpress64/Kconfig b/board/armltd/vexpress64/Kconfig
index 4aab3f0..a0314c6 100644
--- a/board/armltd/vexpress64/Kconfig
+++ b/board/armltd/vexpress64/Kconfig
@@ -1,4 +1,4 @@
-if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO
+if ARCH_VEXPRESS64
config SYS_BOARD
default "vexpress64"
@@ -9,6 +9,43 @@ config SYS_VENDOR
config SYS_CONFIG_NAME
default "vexpress_aemv8"
+config VEXPRESS64_BASE_MODEL
+ bool
+ select SEMIHOSTING
+ select VIRTIO_BLK if VIRTIO_MMIO
+ select VIRTIO_NET if VIRTIO_MMIO
+ select DM_ETH if VIRTIO_NET
+ select LINUX_KERNEL_IMAGE_HEADER
+ select POSITION_INDEPENDENT
+
+choice
+ prompt "VExpress64 board variant"
+
+config TARGET_VEXPRESS64_BASE_FVP
+ bool "Support Versatile Express ARMv8a FVP BASE model"
+ select VEXPRESS64_BASE_MODEL
+ select OF_BOARD
+
+config TARGET_VEXPRESS64_BASER_FVP
+ bool "Support Versatile Express ARMv8r64 FVP BASE model"
+ select VEXPRESS64_BASE_MODEL
+ imply OF_HAS_PRIOR_STAGE
+
+config TARGET_VEXPRESS64_JUNO
+ bool "Support Versatile Express Juno Development Platform"
+ select PCIE_ECAM_GENERIC if PCI
+ select SATA_SIL
+ select SMC911X if DM_ETH
+ select SMC911X_32_BIT if SMC911X
+ select CMD_USB if USB
+ select USB_EHCI_HCD if USB
+ select USB_EHCI_GENERIC if USB
+ select USB_OHCI_HCD if USB
+ select USB_OHCI_GENERIC if USB
+ imply OF_HAS_PRIOR_STAGE
+
+endchoice
+
config JUNO_DTB_PART
string "NOR flash partition holding DTB"
default "board.dtb"
@@ -16,4 +53,36 @@ config JUNO_DTB_PART
The ARM partition name in the NOR flash memory holding the
device tree blob to configure U-Boot.
+config LNX_KRNL_IMG_TEXT_OFFSET_BASE
+ default SYS_TEXT_BASE
+
+config SYS_TEXT_BASE
+ default 0x88000000 if TARGET_VEXPRESS64_BASE_FVP
+ default 0xe0000000 if TARGET_VEXPRESS64_JUNO
+ default 0x00001000 if TARGET_VEXPRESS64_BASER_FVP
+
+config SYS_MALLOC_LEN
+ default 0x810000 if TARGET_VEXPRESS64_JUNO
+ default 0x840000 if TARGET_VEXPRESS64_BASE_FVP
+
+config SYS_MALLOC_F_LEN
+ default 0x2000
+
+config SYS_LOAD_ADDR
+ default 0x10000000 if TARGET_VEXPRESS64_BASER_FVP
+ default 0x90000000
+
+config ENV_ADDR
+ default 0x0BFC0000 if TARGET_VEXPRESS64_JUNO
+ default 0x0FFC0000 if TARGET_VEXPRESS64_BASE_FVP
+ default 0x8FFC0000 if TARGET_VEXPRESS64_BASER_FVP
+
+config ENV_SIZE
+ default 0x10000 if TARGET_VEXPRESS64_JUNO
+ default 0x40000
+
+config ENV_SECT_SIZE
+ default 0x10000 if TARGET_VEXPRESS64_JUNO
+ default 0x40000
+
endif
diff --git a/board/armltd/vexpress64/MAINTAINERS b/board/armltd/vexpress64/MAINTAINERS
index 0ba044d..b3ecc9b 100644
--- a/board/armltd/vexpress64/MAINTAINERS
+++ b/board/armltd/vexpress64/MAINTAINERS
@@ -14,3 +14,8 @@ JUNO DEVELOPMENT PLATFORM BOARD
M: Linus Walleij <linus.walleij@linaro.org>
S: Maintained
F: configs/vexpress_aemv8a_juno_defconfig
+
+VEXPRESS64 ARMV8R-64
+M: Peter Hoyes <Peter.Hoyes@arm.com>
+S: Maintained
+F: configs/vexpress_aemv8r_defconfig
diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
index 5e22e89..709ebf3 100644
--- a/board/armltd/vexpress64/vexpress64.c
+++ b/board/armltd/vexpress64/vexpress64.c
@@ -15,6 +15,7 @@
#include <asm/global_data.h>
#include <asm/io.h>
#include <linux/compiler.h>
+#include <linux/sizes.h>
#include <dm/platform_data/serial_pl01x.h>
#include "pcie.h"
#include <asm/armv8/mmu.h>
@@ -38,16 +39,27 @@ U_BOOT_DRVINFO(vexpress_serials) = {
static struct mm_region vexpress64_mem_map[] = {
{
- .virt = 0x0UL,
- .phys = 0x0UL,
- .size = 0x80000000UL,
+ .virt = V2M_PA_BASE,
+ .phys = V2M_PA_BASE,
+ .size = SZ_2G,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
- .virt = 0x80000000UL,
- .phys = 0x80000000UL,
- .size = 0xff80000000UL,
+ .virt = V2M_DRAM_BASE,
+ .phys = V2M_DRAM_BASE,
+ .size = SZ_2G,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ /*
+ * DRAM beyond 2 GiB is located high. Let's map just some
+ * of it, although U-Boot won't realistically use it, and
+ * the actual available amount might be smaller on the model.
+ */
+ .virt = 0x880000000UL, /* 32 + 2 GiB */
+ .phys = 0x880000000UL,
+ .size = 6UL * SZ_1G,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
@@ -76,20 +88,12 @@ int board_init(void)
int dram_init(void)
{
- gd->ram_size = PHYS_SDRAM_1_SIZE;
- return 0;
+ return fdtdec_setup_mem_size_base();
}
int dram_init_banksize(void)
{
- gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
- gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
-#ifdef PHYS_SDRAM_2
- gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
- gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
-#endif
-
- return 0;
+ return fdtdec_setup_memory_banksize();
}
/* Assigned in lowlevel_init.S
@@ -168,11 +172,17 @@ void *board_fdt_blob_setup(int *err)
}
#endif
- if (fdt_magic(prior_stage_fdt_address) == FDT_MAGIC) {
+ if (fdt_magic(prior_stage_fdt_address) == FDT_MAGIC &&
+ fdt_totalsize(prior_stage_fdt_address) > 0x100) {
*err = 0;
return (void *)prior_stage_fdt_address;
}
+ if (fdt_magic(gd->fdt_blob) == FDT_MAGIC) {
+ *err = 0;
+ return (void *)gd->fdt_blob;
+ }
+
*err = -ENXIO;
return NULL;
}
diff --git a/board/freescale/ls1046ardb/MAINTAINERS b/board/freescale/ls1046ardb/MAINTAINERS
index efdea22..3c8cfe7 100644
--- a/board/freescale/ls1046ardb/MAINTAINERS
+++ b/board/freescale/ls1046ardb/MAINTAINERS
@@ -14,3 +14,4 @@ F: configs/ls1046ardb_tfa_SECURE_BOOT_defconfig
F: configs/ls1046ardb_SECURE_BOOT_defconfig
F: configs/ls1046ardb_sdcard_SECURE_BOOT_defconfig
F: configs/ls1046ardb_qspi_SECURE_BOOT_defconfig
+F: doc/board/nxp/ls1046ardb.rst
diff --git a/board/freescale/ls1046ardb/README b/board/freescale/ls1046ardb/README
deleted file mode 100644
index 90c44f4..0000000
--- a/board/freescale/ls1046ardb/README
+++ /dev/null
@@ -1,76 +0,0 @@
-Overview
---------
-The LS1046A Reference Design Board (RDB) is a high-performance computing,
-evaluation, and development platform that supports the QorIQ LS1046A
-LayerScape Architecture processor. The LS1046ARDB provides SW development
-platform for the Freescale LS1046A processor series, with a complete
-debugging environment. The LS1046A RDB is lead-free and RoHS-compliant.
-
-LS1046A SoC Overview
---------------------
-Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1046A
-SoC overview.
-
- LS1046ARDB board Overview
- -----------------------
- - SERDES1 Connections, 4 lanes supporting:
- - Lane0: 10GBase-R with x1 RJ45 connector
- - Lane1: 10GBase-R Cage
- - Lane2: SGMII.5
- - Lane3: SGMII.6
- - SERDES2 Connections, 4 lanes supporting:
- - Lane0: PCIe1 with miniPCIe slot
- - Lane1: PCIe2 with PCIe x2 slot
- - Lane2: PCIe3 with PCIe x4 slot
- - Lane3: SATA
- - DDR Controller
- - 8GB 64bits DDR4 SDRAM. Support rates of up to 2133MT/s
- -IFC/Local Bus
- - One 512 MB NAND flash with ECC support
- - CPLD connection
- - USB 3.0
- - one Type A port, one Micro-AB port
- - SDHC: connects directly to a full SD/MMC slot
- - DSPI: 64 MB high-speed flash Memory for boot code and storage (up to 108MHz)
- - 4 I2C controllers
- - UART
- - Two 4-pin serial ports at up to 115.2 Kbit/s
- - Two DB9 D-Type connectors supporting one Serial port each
- - ARM JTAG support
-
-Memory map from core's view
-----------------------------
-Start Address End Address Description Size
-0x00_0000_0000 - 0x00_000F_FFFF Secure Boot ROM 1MB
-0x00_0100_0000 - 0x00_0FFF_FFFF CCSRBAR 240MB
-0x00_1000_0000 - 0x00_1000_FFFF OCRAM0 64KB
-0x00_1001_0000 - 0x00_1001_FFFF OCRAM1 64KB
-0x00_2000_0000 - 0x00_20FF_FFFF DCSR 16MB
-0x00_7E80_0000 - 0x00_7E80_FFFF IFC - NAND Flash 64KB
-0x00_7FB0_0000 - 0x00_7FB0_0FFF IFC - CPLD 4KB
-0x00_8000_0000 - 0x00_FFFF_FFFF DRAM1 2GB
-0x05_0000_0000 - 0x05_07FF_FFFF QMAN S/W Portal 128M
-0x05_0800_0000 - 0x05_0FFF_FFFF BMAN S/W Portal 128M
-0x08_8000_0000 - 0x09_FFFF_FFFF DRAM2 6GB
-0x40_0000_0000 - 0x47_FFFF_FFFF PCI Express1 32G
-0x48_0000_0000 - 0x4F_FFFF_FFFF PCI Express2 32G
-0x50_0000_0000 - 0x57_FFFF_FFFF PCI Express3 32G
-
-QSPI flash map:
-Start Address End Address Description Size
-0x00_4000_0000 - 0x00_400F_FFFF RCW + PBI 1MB
-0x00_4010_0000 - 0x00_402F_FFFF U-Boot 2MB
-0x00_4030_0000 - 0x00_403F_FFFF U-Boot Env 1MB
-0x00_4040_0000 - 0x00_405F_FFFF PPA 2MB
-0x00_4060_0000 - 0x00_408F_FFFF Secure boot header
- + bootscript 3MB
-0x00_4090_0000 - 0x00_4093_FFFF FMan ucode 256KB
-0x00_4094_0000 - 0x00_4097_FFFF QE/uQE firmware 256KB
-0x00_4098_0000 - 0x00_40FF_FFFF Reserved 6MB
-0x00_4100_0000 - 0x00_43FF_FFFF FIT Image 48MB
-
-Booting Options
----------------
-a) QSPI boot
-b) SD boot
-c) eMMC boot
diff --git a/board/freescale/ls1046ardb/ls1046ardb.c b/board/freescale/ls1046ardb/ls1046ardb.c
index d0abfe8..f2949cf 100644
--- a/board/freescale/ls1046ardb/ls1046ardb.c
+++ b/board/freescale/ls1046ardb/ls1046ardb.c
@@ -7,6 +7,8 @@
#include <i2c.h>
#include <fdt_support.h>
#include <init.h>
+#include <semihosting.h>
+#include <serial.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
@@ -27,6 +29,15 @@
DECLARE_GLOBAL_DATA_PTR;
+struct serial_device *default_serial_console(void)
+{
+#if IS_ENABLED(CONFIG_SEMIHOSTING_SERIAL)
+ if (semihosting_enabled())
+ return &serial_smh_device;
+#endif
+ return &eserial1_device;
+}
+
int board_early_init_f(void)
{
fsl_lsch2_early_init_f();
diff --git a/cmd/fdt.c b/cmd/fdt.c
index 2a207bf..7d7cae8 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -638,7 +638,7 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
if (argc == 4) {
initrd_start = hextoul(argv[2], NULL);
- initrd_end = hextoul(argv[3], NULL);
+ initrd_end = initrd_start + hextoul(argv[3], NULL) - 1;
}
fdt_chosen(working_fdt);
@@ -1083,8 +1083,8 @@ static char fdt_help_text[] =
"fdt rsvmem print - Show current mem reserves\n"
"fdt rsvmem add <addr> <size> - Add a mem reserve\n"
"fdt rsvmem delete <index> - Delete a mem reserves\n"
- "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n"
- " <start>/<end> - initrd start/end addr\n"
+ "fdt chosen [<start> <size>] - Add/update the /chosen branch in the tree\n"
+ " <start>/<size> - initrd start addr/size\n"
#if defined(CONFIG_FIT_SIGNATURE)
"fdt checksign [<addr>] - check FIT signature\n"
" <start> - addr of key blob\n"
diff --git a/common/spl/Makefile b/common/spl/Makefile
index db8fd36..e71e7be 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o
obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o
obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o
obj-$(CONFIG_$(SPL_TPL_)SATA) += spl_sata.o
+obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += spl_semihosting.o
obj-$(CONFIG_$(SPL_TPL_)DFU) += spl_dfu.o
obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o
obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o
diff --git a/common/spl/spl_semihosting.c b/common/spl/spl_semihosting.c
new file mode 100644
index 0000000..df6aeb2
--- /dev/null
+++ b/common/spl/spl_semihosting.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#include <common.h>
+#include <image.h>
+#include <log.h>
+#include <semihosting.h>
+#include <spl.h>
+
+static int smh_read_full(long fd, void *memp, size_t len)
+{
+ long read;
+
+ read = smh_read(fd, memp, len);
+ if (read < 0)
+ return read;
+ if (read != len)
+ return -EIO;
+ return 0;
+}
+
+static int spl_smh_load_image(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev)
+{
+ const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
+ int ret;
+ long fd, len;
+ struct image_header *header =
+ spl_get_load_buffer(-sizeof(*header), sizeof(*header));
+
+ fd = smh_open(filename, MODE_READ | MODE_BINARY);
+ if (fd < 0) {
+ log_debug("could not open %s: %ld\n", filename, fd);
+ return fd;
+ }
+
+ ret = smh_flen(fd);
+ if (ret < 0) {
+ log_debug("could not get length of image: %d\n", ret);
+ goto out;
+ }
+ len = ret;
+
+ ret = smh_read_full(fd, header, sizeof(struct image_header));
+ if (ret) {
+ log_debug("could not read image header: %d\n", ret);
+ goto out;
+ }
+
+ ret = spl_parse_image_header(spl_image, bootdev, header);
+ if (ret) {
+ log_debug("failed to parse image header: %d\n", ret);
+ goto out;
+ }
+
+ ret = smh_seek(fd, 0);
+ if (ret) {
+ log_debug("could not seek to start of image: %d\n", ret);
+ goto out;
+ }
+
+ ret = smh_read_full(fd, (void *)spl_image->load_addr, len);
+ if (ret)
+ log_debug("could not read %s: %d\n", filename, ret);
+out:
+ smh_close(fd);
+ return ret;
+}
+SPL_LOAD_IMAGE_METHOD("SEMIHOSTING", 0, BOOT_DEVICE_SMH, spl_smh_load_image);
diff --git a/configs/vexpress_aemv8a_juno_defconfig b/configs/vexpress_aemv8a_juno_defconfig
index 76a851c..374fa32 100644
--- a/configs/vexpress_aemv8a_juno_defconfig
+++ b/configs/vexpress_aemv8a_juno_defconfig
@@ -1,55 +1,30 @@
CONFIG_ARM=y
-CONFIG_TARGET_VEXPRESS64_JUNO=y
-CONFIG_SYS_TEXT_BASE=0xe0000000
-CONFIG_SYS_MALLOC_LEN=0x810000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ARCH_VEXPRESS64=y
CONFIG_NR_DRAM_BANKS=2
-CONFIG_ENV_SIZE=0x10000
-CONFIG_ENV_SECT_SIZE=0x10000
CONFIG_DEFAULT_DEVICE_TREE="juno-r2"
CONFIG_IDENT_STRING=" vexpress_aemv8a"
+CONFIG_TARGET_VEXPRESS64_JUNO=y
CONFIG_SYS_MEMTEST_START=0x80000000
CONFIG_SYS_MEMTEST_END=0xff000000
-CONFIG_DISTRO_DEFAULTS=y
CONFIG_REMAKE_ELF=y
-CONFIG_SYS_LOAD_ADDR=0x90000000
CONFIG_BOOTDELAY=1
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyAMA0,115200n8 root=/dev/sda2 rw rootwait earlycon=pl011,0x7ff80000 debug user_debug=31 androidboot.hardware=juno loglevel=9"
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SYS_PROMPT="VExpress64# "
-# CONFIG_CMD_CONSOLE is not set
-# CONFIG_CMD_XIMG is not set
-# CONFIG_CMD_EDITENV is not set
CONFIG_CMD_MEMTEST=y
CONFIG_CMD_ARMFLASH=y
-# CONFIG_CMD_LOADS is not set
CONFIG_CMD_PCI=y
CONFIG_CMD_SATA=y
-CONFIG_CMD_USB=y
-# CONFIG_CMD_ITEST is not set
-# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_BOOTFILESIZE=y
-# CONFIG_CMD_NFS is not set
CONFIG_CMD_CACHE=y
-# CONFIG_CMD_SLEEP is not set
CONFIG_CMD_UBI=y
-CONFIG_ENV_IS_IN_FLASH=y
-CONFIG_ENV_ADDR=0xBFC0000
-CONFIG_SATA_SIL=y
# CONFIG_MMC is not set
CONFIG_MTD=y
-CONFIG_MTD_NOR_FLASH=y
-CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
CONFIG_SYS_FLASH_CFI=y
-CONFIG_SMC911X=y
-CONFIG_SMC911X_32_BIT=y
+CONFIG_DM_ETH=y
CONFIG_PCI=y
-CONFIG_PCIE_ECAM_GENERIC=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_GENERIC=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_GENERIC=y
+CONFIG_USB=y
diff --git a/configs/vexpress_aemv8a_semi_defconfig b/configs/vexpress_aemv8a_semi_defconfig
index b36a33a..eca6176 100644
--- a/configs/vexpress_aemv8a_semi_defconfig
+++ b/configs/vexpress_aemv8a_semi_defconfig
@@ -1,51 +1,27 @@
CONFIG_ARM=y
# CONFIG_ARM64_CRC32 is not set
-CONFIG_TARGET_VEXPRESS64_BASE_FVP=y
-CONFIG_SYS_TEXT_BASE=0x88000000
-CONFIG_SYS_MALLOC_LEN=0x840000
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ARCH_VEXPRESS64=y
CONFIG_NR_DRAM_BANKS=2
-CONFIG_ENV_SIZE=0x40000
-CONFIG_ENV_SECT_SIZE=0x40000
+CONFIG_DEFAULT_DEVICE_TREE="fvp-base-revc"
CONFIG_IDENT_STRING=" vexpress_aemv8a"
CONFIG_SYS_MEMTEST_START=0x80000000
CONFIG_SYS_MEMTEST_END=0xff000000
-CONFIG_DISTRO_DEFAULTS=y
CONFIG_REMAKE_ELF=y
-CONFIG_SYS_LOAD_ADDR=0x90000000
CONFIG_ANDROID_BOOT_IMAGE=y
CONFIG_BOOTDELAY=1
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 loglevel=9"
-CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then setenv bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; setenv fdt_high 0xffffffffffffffff; setenv initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr_r}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr_r - $fdt_addr_r; fi"
# CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SYS_PROMPT="VExpress64# "
-# CONFIG_CMD_CONSOLE is not set
CONFIG_CMD_ABOOTIMG=y
-# CONFIG_CMD_XIMG is not set
-# CONFIG_CMD_EDITENV is not set
CONFIG_CMD_MEMTEST=y
CONFIG_CMD_ARMFLASH=y
-# CONFIG_CMD_LOADS is not set
-# CONFIG_CMD_ITEST is not set
-# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_BOOTFILESIZE=y
-# CONFIG_CMD_NFS is not set
CONFIG_CMD_CACHE=y
-# CONFIG_CMD_SLEEP is not set
CONFIG_CMD_UBI=y
-# CONFIG_ISO_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-CONFIG_ENV_IS_IN_FLASH=y
-CONFIG_ENV_ADDR=0xFFC0000
-CONFIG_DM=y
# CONFIG_MMC is not set
CONFIG_MTD=y
-CONFIG_MTD_NOR_FLASH=y
-CONFIG_FLASH_CFI_DRIVER=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_SYS_FLASH_PROTECTION=y
CONFIG_SYS_FLASH_CFI=y
-CONFIG_DM_SERIAL=y
-CONFIG_OF_LIBFDT=y
+CONFIG_VIRTIO_MMIO=y
diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig
new file mode 100644
index 0000000..612797e
--- /dev/null
+++ b/configs/vexpress_aemv8r_defconfig
@@ -0,0 +1,14 @@
+CONFIG_ARM=y
+CONFIG_ARCH_VEXPRESS64=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_DEFAULT_DEVICE_TREE="arm_fvp"
+CONFIG_IDENT_STRING=" vexpress_aemv8r64"
+CONFIG_TARGET_VEXPRESS64_BASER_FVP=y
+CONFIG_REMAKE_ELF=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x9c090000 rootfstype=ext4 root=/dev/vda2 rw rootwait"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_SYS_PROMPT="VExpress64# "
+# CONFIG_MMC is not set
+CONFIG_VIRTIO_MMIO=y
diff --git a/disk/part.c b/disk/part.c
index 49e39a2..b95405b 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -455,7 +455,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
int part;
struct disk_partition tmpinfo;
-#ifdef CONFIG_SANDBOX
+#if IS_ENABLED(CONFIG_SANDBOX) || IS_ENABLED(CONFIG_SEMIHOSTING)
/*
* Special-case a pseudo block device "hostfs", to allow access to the
* host's own filesystem.
@@ -467,7 +467,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
info->blksz = 0;
info->bootable = 0;
strcpy((char *)info->type, BOOT_PART_TYPE);
- strcpy((char *)info->name, "Sandbox host");
+ strcpy((char *)info->name, "Host filesystem");
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
info->uuid[0] = 0;
#endif
diff --git a/doc/README.semihosting b/doc/README.semihosting
deleted file mode 100644
index f382d01..0000000
--- a/doc/README.semihosting
+++ /dev/null
@@ -1,38 +0,0 @@
-SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright 2014 Broadcom Corporation.
- */
-
-Semihosting is ARM's way of having a real or virtual target communicate
-with a host or host debugger for basic operations such as file I/O,
-console I/O, etc. Please see
-http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471c/Bgbjjgij.html for more information.
-
-For developing on armv8 virtual fastmodel platforms, semihosting is a
-valuable tool since it allows access to image/configuration files before
-eMMC or other NV media are available.
-
-There are two main ARM virtual Fixed Virtual Platform (FVP) models,
-Versatile Express (VE) FVP and BASE FVP (See
-http://www.arm.com/products/tools/models/fast-models/foundation-model.php)
-The initial vexpress64 u-boot board created here runs on the VE virtual
-platform using the license-free Foundation_v8 simulator. Fortunately,
-the Foundation_v8 simulator also supports the BASE_FVP model which
-companies can purchase licenses for and contain much more functionality.
-So we can, in u-boot, run either model by either using the VE FVP (default),
-or turning on CONFIG_BASE_FVP for the more full featured model.
-
-Rather than create a new armv8 board similar to armltd/vexpress64, add
-semihosting calls to the existing one, enabled with CONFIG_SEMIHOSTING
-and CONFIG_BASE_FVP both set. Also reuse the existing board config file
-vexpress_aemv8.h but differentiate the two models by the presence or
-absence of CONFIG_BASE_FVP. This change is tested and works on both the
-Foundation and Base fastmodel simulators.
-
-The semihosting code adds a command:
-
- smhload <image> <address> [env var]
-
-That will load an image from the host filesystem into RAM at the specified
-address and optionally store the load end address in the specified
-environment variable.
diff --git a/doc/arch/arm64.rst b/doc/arch/arm64.rst
index 80498f6..7c07135 100644
--- a/doc/arch/arm64.rst
+++ b/doc/arch/arm64.rst
@@ -18,7 +18,8 @@ Notes
classical firmware (like initial hardware setup, CPU errata workarounds
or SMP bringup). U-Boot can be entered in EL2 when its main purpose is
that of a boot loader. It can drop to lower exception levels before
- entering the OS.
+ entering the OS. For ARMv8-R it is recommened to enter at S-EL1, as for this
+ architecture there is no S-EL3.
2. U-Boot for arm64 is compiled with AArch64-gcc. AArch64-gcc
use rela relocation format, a tool(tools/relocate-rela) by Scott Wood
diff --git a/doc/board/armltd/vexpress64.rst b/doc/board/armltd/vexpress64.rst
index d87b1c3..a7f771d 100644
--- a/doc/board/armltd/vexpress64.rst
+++ b/doc/board/armltd/vexpress64.rst
@@ -6,6 +6,7 @@ Arm Versatile Express
The vexpress_* board configuration supports the following platforms:
* FVP_Base_RevC-2xAEMvA
+ * FVP_BaseR_AEMv8R
* Juno development board
Fixed Virtual Platforms
diff --git a/doc/board/nxp/index.rst b/doc/board/nxp/index.rst
index 6395628..4514b89 100644
--- a/doc/board/nxp/index.rst
+++ b/doc/board/nxp/index.rst
@@ -13,6 +13,7 @@ NXP Semiconductors
imx8qxp_mek
imxrt1020-evk
imxrt1050-evk
+ ls1046ardb
mx6sabreauto
mx6sabresd
mx6ul_14x14_evk
diff --git a/doc/board/nxp/ls1046ardb.rst b/doc/board/nxp/ls1046ardb.rst
new file mode 100644
index 0000000..35465d0
--- /dev/null
+++ b/doc/board/nxp/ls1046ardb.rst
@@ -0,0 +1,193 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+LS1046ARDB
+==========
+
+The LS1046A Reference Design Board (RDB) is a high-performance computing,
+evaluation, and development platform that supports the QorIQ LS1046A
+LayerScape Architecture processor. The LS1046ARDB provides SW development
+platform for the Freescale LS1046A processor series, with a complete
+debugging environment. The LS1046A RDB is lead-free and RoHS-compliant.
+
+LS1046A SoC Overview
+--------------------
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1046A
+SoC overview.
+
+LS1046ARDB board Overview
+-------------------------
+- SERDES1 Connections, 4 lanes supporting:
+
+ - Lane0: 10GBase-R with x1 RJ45 connector
+ - Lane1: 10GBase-R Cage
+ - Lane2: SGMII.5
+ - Lane3: SGMII.6
+
+- SERDES2 Connections, 4 lanes supporting:
+
+ - Lane0: PCIe1 with miniPCIe slot
+ - Lane1: PCIe2 with PCIe x2 slot
+ - Lane2: PCIe3 with PCIe x4 slot
+ - Lane3: SATA
+
+- DDR Controller
+
+ - 8GB 64bits DDR4 SDRAM. Support rates of up to 2133MT/s
+
+- IFC/Local Bus
+
+ - One 512 MB NAND flash with ECC support
+ - CPLD connection
+
+- USB 3.0
+
+ - one Type A port, one Micro-AB port
+
+- SDHC: connects directly to a full SD/MMC slot
+- DSPI: 64 MB high-speed flash Memory for boot code and storage (up to 108MHz)
+- 4 I2C controllers
+- UART
+
+ - Two 4-pin serial ports at up to 115.2 Kbit/s
+ - Two DB9 D-Type connectors supporting one Serial port each
+
+- ARM JTAG support
+
+Memory map from core's view
+----------------------------
+
+================== ================== ================ =====
+Start Address End Address Description Size
+================== ================== ================ =====
+``0x00_0000_0000`` ``0x00_000F_FFFF`` Secure Boot ROM 1M
+``0x00_0100_0000`` ``0x00_0FFF_FFFF`` CCSRBAR 240M
+``0x00_1000_0000`` ``0x00_1000_FFFF`` OCRAM0 64K
+``0x00_1001_0000`` ``0x00_1001_FFFF`` OCRAM1 64K
+``0x00_2000_0000`` ``0x00_20FF_FFFF`` DCSR 16M
+``0x00_7E80_0000`` ``0x00_7E80_FFFF`` IFC - NAND Flash 64K
+``0x00_7FB0_0000`` ``0x00_7FB0_0FFF`` IFC - CPLD 4K
+``0x00_8000_0000`` ``0x00_FFFF_FFFF`` DRAM1 2G
+``0x05_0000_0000`` ``0x05_07FF_FFFF`` QMAN S/W Portal 128M
+``0x05_0800_0000`` ``0x05_0FFF_FFFF`` BMAN S/W Portal 128M
+``0x08_8000_0000`` ``0x09_FFFF_FFFF`` DRAM2 6G
+``0x40_0000_0000`` ``0x47_FFFF_FFFF`` PCI Express1 32G
+``0x48_0000_0000`` ``0x4F_FFFF_FFFF`` PCI Express2 32G
+``0x50_0000_0000`` ``0x57_FFFF_FFFF`` PCI Express3 32G
+================== ================== ================ =====
+
+QSPI flash map
+--------------
+
+================== ================== ================== =====
+Start Address End Address Description Size
+================== ================== ================== =====
+``0x00_4000_0000`` ``0x00_400F_FFFF`` RCW + PBI 1M
+``0x00_4010_0000`` ``0x00_402F_FFFF`` U-Boot 2M
+``0x00_4030_0000`` ``0x00_403F_FFFF`` U-Boot Env 1M
+``0x00_4040_0000`` ``0x00_405F_FFFF`` PPA 2M
+``0x00_4060_0000`` ``0x00_408F_FFFF`` Secure boot header 3M
+ + bootscript
+``0x00_4090_0000`` ``0x00_4093_FFFF`` FMan ucode 256K
+``0x00_4094_0000`` ``0x00_4097_FFFF`` QE/uQE firmware 256K
+``0x00_4098_0000`` ``0x00_40FF_FFFF`` Reserved 6M
+``0x00_4100_0000`` ``0x00_43FF_FFFF`` FIT Image 48M
+================== ================== ================== =====
+
+Booting Options
+---------------
+
+NB: The reference manual documents the RCW source with the *least-significant
+bit first*.
+
+QSPI boot
+^^^^^^^^^
+
+This is the default. ``{ SW5[0:8], SW4[0] }`` should be ``0010_0010_0``.
+
+SD boot and eMMC boot
+^^^^^^^^^^^^^^^^^^^^^
+
+``{ SW5[0:8], SW4[0] }`` should be ``0010_0000_0``. eMMC is selected only if
+there is no SD card in the slot.
+
+.. _ls1046ardb_jtag:
+
+JTAG boot
+^^^^^^^^^
+
+To recover a bricked board, or to perform initial programming, the ls1046
+supports using two hard-coded Reset Configuration Words (RCWs). Unfortunately,
+this configuration disables most functionality, including the uarts and ethernet.
+However, the SD/MMC and flash controllers are still functional. To get around
+the lack of a serial console, we will use ARM semihosting instead. When
+enabled, OpenOCD will interpret certain instructions as calls to the host
+operating system. This allows U-Boot to use the console, read/write files, or
+run arbitrary commands (!).
+
+When configuring U-Boot, ensure that ``CONFIG_SEMIHOSTING``,
+``CONFIG_SPL_SEMIHOSTING``, and ``CONFIG_SEMIHOSTING_SERIAL`` are enabled.
+``{ SW5[0:8], SW4[0] }`` should be ``0100_1111_0``. Additionally, ``SW4[7]``
+should be set to ``0``. Connect to the "console" USB connector on the front of
+the enclosure.
+
+Create a new file called ``u-boot.tcl`` (or whatever you choose) with the
+following contents::
+
+ # Load the configuration for the LS1046ARDB
+ source [find board/nxp_rdb-ls1046a.cfg]
+ # Initialize the scan chain
+ init
+ # Stop the processor
+ halt
+ # Enable semihosting
+ arm semihosting enable
+ # Load U-Boot SPL
+ load_image spl/u-boot-spl 0 elf
+ # Start executing SPL at the beginning of OCRAM
+ resume 0x10000000
+
+Then, launch openocd like::
+
+ openocd -f u-boot.tcl
+
+You should see the U-boot SPL banner followed by the banner for U-Boot proper
+in the output of openocd. The CMSIS-DAP adapter is slow, so this can take a
+long time. If you don't see it, something has gone wrong. After a while, you
+should see the prompt. You can load an image using semihosting by running::
+
+ => load hostfs - $loadaddr <name of file>
+
+Note that openocd's terminal is "cooked," so commands will only be sent to
+U-Boot when you press enter, and all commands will be echoed twice.
+Additionally, openocd will block when waiting for input, ignoring gdb, JTAG
+events, and Ctrl-Cs. To make openocd process these events, just hit enter.
+
+Using an external JTAG adapter
+""""""""""""""""""""""""""""""
+
+The CMSIS-DAP adapter can be rather slow. To speed up booting, use an external
+JTAG adapter. The following examples assume you are using a J-Link, though any
+adapter supported by OpenOCD will do. Ensure that ``SW4[7]`` is ``1``. Attach
+your jtag adapter to J22. Modify ``u-boot.tcl`` and replace the first two lines
+with the following::
+
+ # Load the J-Link configuration (or whatever your adapter is)
+ source [find interface/jlink.cfg]
+ # Use JTAG, since the J-Link also supports SWD
+ transport select jtag
+ # The reset pin resets the whole CPU
+ reset_config srst_only
+ # Load the LS1046A config
+ source [find target/ls1046a.cfg]
+
+You can proceed as normal through the rest of the steps above. I got a speedup
+of around 100x by using a J-Link.
+
+Debug UART
+----------
+
+To enable the debug UART, enable the following config options::
+
+ CONFIG_DEBUG_UART_NS16550=y
+ CONFIG_DEBUG_UART_BASE=0x21c0500
+ CONFIG_DEBUG_UART_CLOCK=300000000
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 5b42579..3e52053 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -11,6 +11,7 @@ Use U-Boot
netconsole
partitions
cmdline
+ semihosting
Shell commands
--------------
diff --git a/doc/usage/semihosting.rst b/doc/usage/semihosting.rst
new file mode 100644
index 0000000..6a280b4
--- /dev/null
+++ b/doc/usage/semihosting.rst
@@ -0,0 +1,107 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2014 Broadcom Corporation.
+
+Semihosting
+===========
+
+Semihosting is ARM's way of having a real or virtual target communicate
+with a host or host debugger for basic operations such as file I/O,
+console I/O, etc. Please see `Arm's semihosting documentation
+<https://developer.arm.com/documentation/100863/latest/>`_ for more
+information.
+
+Platform Support
+----------------
+
+Versatile Express
+^^^^^^^^^^^^^^^^^
+
+For developing on armv8 virtual fastmodel platforms, semihosting is a
+valuable tool since it allows access to image/configuration files before
+eMMC or other NV media are available.
+
+There are two main ARM virtual Fixed Virtual Platform (FVP) models,
+`Versatile Express (VE) FVP and BASE FVP
+<http://www.arm.com/products/tools/models/fast-models/foundation-model.php>`_.
+The initial vexpress64 u-boot board created here runs on the VE virtual
+platform using the license-free Foundation_v8 simulator. Fortunately,
+the Foundation_v8 simulator also supports the BASE_FVP model which
+companies can purchase licenses for and contain much more functionality.
+So we can, in U-Boot, run either model by either using the VE FVP (default),
+or turning on ``CONFIG_BASE_FVP`` for the more full featured model.
+
+Rather than create a new armv8 board similar to ``armltd/vexpress64``, add
+semihosting calls to the existing one, enabled with ``CONFIG_SEMIHOSTING``
+and ``CONFIG_BASE_FVP`` both set. Also reuse the existing board config file
+vexpress_aemv8.h but differentiate the two models by the presence or
+absence of ``CONFIG_BASE_FVP``. This change is tested and works on both the
+Foundation and Base fastmodel simulators.
+
+QEMU
+^^^^
+
+Another ARM emulator which supports semihosting is `QEMU
+<https://www.qemu.org/>`_. To enable semihosting, enable
+``CONFIG_SERIAL_PROBE_ALL`` when configuring U-Boot, and use
+``-semihosting`` when invoking QEMU. Adding ``-nographic`` can also be
+helpful. When using a semihosted serial console, QEMU will block waiting
+for input. This will cause the GUI to become unresponsive. To mitigate
+this, try adding ``-nographic``. For more information about building and
+running QEMU, refer to the :doc:`board documentation
+<../board/emulation/qemu-arm>`.
+
+OpenOCD
+^^^^^^^
+
+Any ARM platform can use semihosting with an attached debugger. One such
+debugger with good support for a variety of boards and JTAG adapters is
+`OpenOCD <https://openocd.org/>`_. Semihosting is not enabled by default,
+so you will need to enable it::
+
+ $ openocd -f <your board config> -c init -c halt -c \
+ 'arm semihosting enable' -c resume
+
+Note that enabling semihosting can only be done after attaching to the
+board with ``init``, and must be done while the CPU is halted. For a more
+extended example, refer to the :ref:`LS1046ARDB docs <ls1046ardb_jtag>`.
+
+Loading files
+-------------
+
+The semihosting code adds a "semihosting filesystem"::
+
+ load hostfs - <address> <image>
+
+That will load an image from the host filesystem into RAM at the specified
+address. If you are using U-Boot SPL, you can also use ``BOOT_DEVICE_SMH``
+which will load ``CONFIG_SPL_FS_LOAD_PAYLOAD_NAME``.
+
+Host console
+------------
+
+U-Boot can use the host's console instead of a physical serial device by
+enabling ``CONFIG_SERIAL_SEMIHOSTING``. If you don't have
+``CONFIG_DM_SERIAL`` enabled, make sure you disable any other serial
+drivers.
+
+Migrating from ``smhload``
+--------------------------
+
+If you were using the ``smhload`` command, you can migrate commands like::
+
+ smhload <file> <address> [<end var>]
+
+to a generic load command like::
+
+ load hostfs - <address> <file>
+
+The ``load`` command will set the ``filesize`` variable with the size of
+the file. The ``fdt chosen`` command has been updated to take a size
+instead of an end address. If you were adding the initramfs to your device
+tree like::
+
+ fdt chosen <address> <end var>
+
+you can now run::
+
+ fdt chosen <address> $filesize
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 610f806..76171e7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -133,6 +133,19 @@ config SERIAL_RX_BUFFER_SIZE
help
The size of the RX buffer (needs to be power of 2)
+config SERIAL_PUTS
+ bool "Enable printing strings all at once"
+ depends on DM_SERIAL
+ help
+ Some serial drivers are much more efficient when printing multiple
+ characters at once rather than printing characters individually. This
+ can be because they can load a fifo, or because individual print
+ calls have a constant overhead. With this option set, the serial
+ subsystem will try to provide serial drivers with as many characters
+ at once as possible, instead of printing characters one by one. Most
+ serial drivers do not need this config to print efficiently. If
+ unsure, say N.
+
config SERIAL_SEARCH_ALL
bool "Search for serial devices after default one failed"
depends on DM_SERIAL
@@ -399,6 +412,15 @@ config DEBUG_UART_SANDBOX
start up driver model. The driver will be available until the real
driver model serial is running.
+config DEBUG_UART_SEMIHOSTING
+ bool "semihosting"
+ depends on SEMIHOSTING_SERIAL
+ help
+ Select this to enable the debug UART using the semihosting driver.
+ This provides basic serial output from the console without needing to
+ start up driver model. The driver will be available until the real
+ driver model serial is running.
+
config DEBUG_UART_SIFIVE
bool "SiFive UART"
depends on SIFIVE_SERIAL
@@ -782,6 +804,19 @@ config SCIF_CONSOLE
on systems with RCar or SH SoCs, say Y to this option. If unsure,
say N.
+config SEMIHOSTING_SERIAL
+ bool "Semihosting UART support"
+ depends on SEMIHOSTING && !SERIAL_RX_BUFFER
+ help
+ Select this to enable a serial UART using semihosting. Special halt
+ instructions will be issued which an external debugger (such as a
+ JTAG emulator) may interpret. The debugger will display U-Boot's
+ console output on the host system.
+
+ Enable this option only if you are using a debugger which supports
+ semihosting. If you are not using a debugger, this driver will halt
+ the boot.
+
config UNIPHIER_SERIAL
bool "Support for UniPhier on-chip UART"
depends on ARCH_UNIPHIER
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 52e70aa..b68b5e7 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -52,6 +52,7 @@ endif
obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o
obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o
obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
+obj-$(CONFIG_SEMIHOSTING_SERIAL) += serial_semihosting.o
obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index f30f352..10d6b80 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -200,8 +200,30 @@ static void _serial_putc(struct udevice *dev, char ch)
static void _serial_puts(struct udevice *dev, const char *str)
{
- while (*str)
- _serial_putc(dev, *str++);
+ struct dm_serial_ops *ops = serial_get_ops(dev);
+
+ if (!CONFIG_IS_ENABLED(SERIAL_PUTS) || !ops->puts) {
+ while (*str)
+ _serial_putc(dev, *str++);
+ return;
+ }
+
+ do {
+ const char *newline = strchrnul(str, '\n');
+ size_t len = newline - str + !!*newline;
+
+ do {
+ ssize_t written = ops->puts(dev, str, len);
+
+ if (written < 0)
+ return;
+ str += written;
+ len -= written;
+ } while (len);
+
+ if (*newline)
+ _serial_putc(dev, '\r');
+ } while (*str);
}
static int __serial_getc(struct udevice *dev)
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index ebbd219..6cdbb89 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -126,6 +126,7 @@ serial_initfunc(mxc_serial_initialize);
serial_initfunc(ns16550_serial_initialize);
serial_initfunc(pl01x_serial_initialize);
serial_initfunc(pxa_serial_initialize);
+serial_initfunc(smh_serial_initialize);
serial_initfunc(sh_serial_initialize);
serial_initfunc(mtk_serial_initialize);
@@ -180,6 +181,7 @@ int serial_initialize(void)
ns16550_serial_initialize();
pl01x_serial_initialize();
pxa_serial_initialize();
+ smh_serial_initialize();
sh_serial_initialize();
mtk_serial_initialize();
diff --git a/drivers/serial/serial_semihosting.c b/drivers/serial/serial_semihosting.c
new file mode 100644
index 0000000..62b1b22
--- /dev/null
+++ b/drivers/serial/serial_semihosting.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <semihosting.h>
+
+/**
+ * struct smh_serial_priv - Semihosting serial private data
+ * @infd: stdin file descriptor (or error)
+ */
+struct smh_serial_priv {
+ int infd;
+ int outfd;
+};
+
+#if CONFIG_IS_ENABLED(DM_SERIAL)
+static int smh_serial_getc(struct udevice *dev)
+{
+ char ch = 0;
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+
+ if (priv->infd < 0)
+ return smh_getc();
+
+ smh_read(priv->infd, &ch, sizeof(ch));
+ return ch;
+}
+
+static int smh_serial_putc(struct udevice *dev, const char ch)
+{
+ smh_putc(ch);
+ return 0;
+}
+
+static const struct dm_serial_ops smh_serial_ops = {
+ .putc = smh_serial_putc,
+ .getc = smh_serial_getc,
+};
+
+static int smh_serial_bind(struct udevice *dev)
+{
+ if (semihosting_enabled())
+ return 0;
+ return -ENOENT;
+}
+
+static int smh_serial_probe(struct udevice *dev)
+{
+ struct smh_serial_priv *priv = dev_get_priv(dev);
+
+ priv->infd = smh_open(":tt", MODE_READ);
+ return 0;
+}
+
+U_BOOT_DRIVER(smh_serial) = {
+ .name = "serial_semihosting",
+ .id = UCLASS_SERIAL,
+ .bind = smh_serial_bind,
+ .probe = smh_serial_probe,
+ .priv_auto = sizeof(struct smh_serial_priv),
+ .ops = &smh_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRVINFO(smh_serial) = {
+ .name = "serial_semihosting",
+};
+#else /* DM_SERIAL */
+static int infd = -ENODEV;
+static int outfd = -ENODEV;
+
+static int smh_serial_start(void)
+{
+ infd = smh_open(":tt", MODE_READ);
+ outfd = smh_open(":tt", MODE_WRITE);
+ return 0;
+}
+
+static int smh_serial_stop(void)
+{
+ if (outfd >= 0)
+ smh_close(outfd);
+ return 0;
+}
+
+static void smh_serial_setbrg(void)
+{
+}
+
+static int smh_serial_getc(void)
+{
+ char ch = 0;
+
+ if (infd < 0)
+ return smh_getc();
+
+ smh_read(infd, &ch, sizeof(ch));
+ return ch;
+}
+
+static int smh_serial_tstc(void)
+{
+ return 1;
+}
+
+static void smh_serial_puts(const char *s)
+{
+ ulong unused;
+
+ if (outfd < 0)
+ smh_puts(s);
+ else
+ smh_write(outfd, s, strlen(s), &unused);
+}
+
+struct serial_device serial_smh_device = {
+ .name = "serial_smh",
+ .start = smh_serial_start,
+ .stop = smh_serial_stop,
+ .setbrg = smh_serial_setbrg,
+ .getc = smh_serial_getc,
+ .tstc = smh_serial_tstc,
+ .putc = smh_putc,
+ .puts = smh_serial_puts,
+};
+
+void smh_serial_initialize(void)
+{
+ if (semihosting_enabled())
+ serial_register(&serial_smh_device);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &serial_smh_device;
+}
+#endif
+
+#ifdef CONFIG_DEBUG_UART_SEMIHOSTING
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+}
+
+static inline void _debug_uart_putc(int c)
+{
+ smh_putc(c);
+}
+
+DEBUG_UART_FUNCS
+#endif
diff --git a/fs/Makefile b/fs/Makefile
index f05a21c..4bed2ff 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_FS_FAT) += fat/
obj-$(CONFIG_FS_JFFS2) += jffs2/
obj-$(CONFIG_CMD_REISER) += reiserfs/
obj-$(CONFIG_SANDBOX) += sandbox/
+obj-$(CONFIG_SEMIHOSTING) += semihostingfs.o
obj-$(CONFIG_CMD_UBIFS) += ubifs/
obj-$(CONFIG_YAFFS2) += yaffs2/
obj-$(CONFIG_CMD_ZFS) += zfs/
diff --git a/fs/fs.c b/fs/fs.c
index 99dac0f..c3a2ed9 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -18,6 +18,7 @@
#include <fat.h>
#include <fs.h>
#include <sandboxfs.h>
+#include <semihostingfs.h>
#include <ubifs_uboot.h>
#include <btrfs.h>
#include <asm/global_data.h>
@@ -247,6 +248,25 @@ static struct fstype_info fstypes[] = {
.ln = fs_ln_unsupported,
},
#endif
+#ifdef CONFIG_SEMIHOSTING
+ {
+ .fstype = FS_TYPE_SEMIHOSTING,
+ .name = "semihosting",
+ .null_dev_desc_ok = true,
+ .probe = smh_fs_set_blk_dev,
+ .close = fs_close_unsupported,
+ .ls = fs_ls_unsupported,
+ .exists = fs_exists_unsupported,
+ .size = smh_fs_size,
+ .read = smh_fs_read,
+ .write = smh_fs_write,
+ .uuid = fs_uuid_unsupported,
+ .opendir = fs_opendir_unsupported,
+ .unlink = fs_unlink_unsupported,
+ .mkdir = fs_mkdir_unsupported,
+ .ln = fs_ln_unsupported,
+ },
+#endif
#ifdef CONFIG_CMD_UBIFS
{
.fstype = FS_TYPE_UBIFS,
diff --git a/fs/semihostingfs.c b/fs/semihostingfs.c
new file mode 100644
index 0000000..96eb334
--- /dev/null
+++ b/fs/semihostingfs.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022, Sean Anderson <sean.anderson@seco.com>
+ * Copyright (c) 2012, Google Inc.
+ */
+
+#include <common.h>
+#include <fs.h>
+#include <malloc.h>
+#include <os.h>
+#include <semihosting.h>
+#include <semihostingfs.h>
+
+int smh_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info)
+{
+ /*
+ * Only accept a NULL struct blk_desc for the semihosting, which is when
+ * hostfs interface is used
+ */
+ return !!rbdd;
+}
+
+static int smh_fs_read_at(const char *filename, loff_t pos, void *buffer,
+ loff_t maxsize, loff_t *actread)
+{
+ long fd, size, ret;
+
+ fd = smh_open(filename, MODE_READ | MODE_BINARY);
+ if (fd < 0)
+ return fd;
+ ret = smh_seek(fd, pos);
+ if (ret < 0) {
+ smh_close(fd);
+ return ret;
+ }
+ if (!maxsize) {
+ size = smh_flen(fd);
+ if (ret < 0) {
+ smh_close(fd);
+ return size;
+ }
+
+ maxsize = size;
+ }
+
+ size = smh_read(fd, buffer, maxsize);
+ smh_close(fd);
+ if (size < 0)
+ return size;
+
+ *actread = size;
+ return 0;
+}
+
+static int smh_fs_write_at(const char *filename, loff_t pos, void *buffer,
+ loff_t towrite, loff_t *actwrite)
+{
+ long fd, size, ret;
+
+ fd = smh_open(filename, MODE_READ | MODE_BINARY | MODE_PLUS);
+ if (fd < 0)
+ return fd;
+ ret = smh_seek(fd, pos);
+ if (ret < 0) {
+ smh_close(fd);
+ return ret;
+ }
+
+ ret = smh_write(fd, buffer, towrite, &size);
+ smh_close(fd);
+ *actwrite = size;
+ return ret;
+}
+
+int smh_fs_size(const char *filename, loff_t *result)
+{
+ long fd, size;
+
+ fd = smh_open(filename, MODE_READ | MODE_BINARY);
+ if (fd < 0)
+ return fd;
+
+ size = smh_flen(fd);
+ smh_close(fd);
+
+ if (size < 0)
+ return size;
+
+ *result = size;
+ return 0;
+}
+
+int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len,
+ loff_t *actread)
+{
+ int ret;
+
+ ret = smh_fs_read_at(filename, offset, buf, len, actread);
+ if (ret)
+ printf("** Unable to read file %s **\n", filename);
+
+ return ret;
+}
+
+int smh_fs_write(const char *filename, void *buf, loff_t offset,
+ loff_t len, loff_t *actwrite)
+{
+ int ret;
+
+ ret = smh_fs_write_at(filename, offset, buf, len, actwrite);
+ if (ret)
+ printf("** Unable to write file %s **\n", filename);
+
+ return ret;
+}
diff --git a/include/configs/ls1046ardb.h b/include/configs/ls1046ardb.h
index 04c3ad0..df699bc 100644
--- a/include/configs/ls1046ardb.h
+++ b/include/configs/ls1046ardb.h
@@ -140,6 +140,8 @@
#endif
#endif
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img"
+
#include <asm/fsl_secure_boot.h>
#endif /* __LS1046ARDB_H__ */
diff --git a/include/configs/vexpress_aemv8.h b/include/configs/vexpress_aemv8.h
index b956bd9..4f0ff23 100644
--- a/include/configs/vexpress_aemv8.h
+++ b/include/configs/vexpress_aemv8.h
@@ -20,8 +20,13 @@
#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* Increase max gunzip size */
/* CS register bases for the original memory map. */
-#define V2M_BASE 0x80000000
+#ifdef CONFIG_TARGET_VEXPRESS64_BASER_FVP
+#define V2M_DRAM_BASE 0x00000000
+#define V2M_PA_BASE 0x80000000
+#else
+#define V2M_DRAM_BASE 0x80000000
#define V2M_PA_BASE 0x00000000
+#endif
#define V2M_PA_CS0 (V2M_PA_BASE + 0x00000000)
#define V2M_PA_CS1 (V2M_PA_BASE + 0x14000000)
@@ -99,10 +104,8 @@
#define CONFIG_PL011_CLOCK 24000000
#endif
-/* Miscellaneous configurable options */
-
/* Physical Memory Map */
-#define PHYS_SDRAM_1 (V2M_BASE) /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1 (V2M_DRAM_BASE) /* SDRAM Bank #1 */
/* Top 16MB reserved for secure world use */
#define DRAM_SEC_SIZE 0x01000000
#define PHYS_SDRAM_1_SIZE 0x80000000 - DRAM_SEC_SIZE
@@ -116,11 +119,7 @@
#define PHYS_SDRAM_2_SIZE 0x80000000
#endif
-/* Enable memtest */
-
-/* Initial environment variables */
-#ifdef CONFIG_TARGET_VEXPRESS64_JUNO
-/* Copy the kernel and FDT to DRAM memory and boot */
+/* Copy the kernel, initrd and FDT from NOR flash to DRAM memory and boot. */
#define BOOTENV_DEV_AFS(devtypeu, devtypel, instance) \
"bootcmd_afs=" \
"afs load ${kernel_name} ${kernel_addr_r} ;"\
@@ -143,6 +142,54 @@
"booti ${kernel_addr_r} ${ramdisk_param} ${fdt_addr_r}\0"
#define BOOTENV_DEV_NAME_AFS(devtypeu, devtypel, instance) "afs "
+/* Boot by executing a U-Boot script pre-loaded into DRAM. */
+#define BOOTENV_DEV_MEM(devtypeu, devtypel, instance) \
+ "bootcmd_mem= " \
+ "source ${scriptaddr}; " \
+ "if test $? -eq 1; then " \
+ " env import -t ${scriptaddr}; " \
+ " if test -n $uenvcmd; then " \
+ " echo Running uenvcmd ...; " \
+ " run uenvcmd; " \
+ " fi; " \
+ "fi\0"
+#define BOOTENV_DEV_NAME_MEM(devtypeu, devtypel, instance) "mem "
+
+#ifdef CONFIG_CMD_VIRTIO
+#define FUNC_VIRTIO(func) func(VIRTIO, virtio, 0)
+#else
+#define FUNC_VIRTIO(func)
+#endif
+
+/*
+ * Boot by loading an Android image, or kernel, initrd and FDT through
+ * semihosting into DRAM.
+ */
+#define BOOTENV_DEV_SMH(devtypeu, devtypel, instance) \
+ "bootcmd_smh= " \
+ "if load hostfs - ${boot_addr_r} ${boot_name}; then" \
+ " setenv bootargs;" \
+ " abootimg addr ${boot_addr_r};" \
+ " abootimg get dtb --index=0 fdt_addr_r;" \
+ " bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r};" \
+ "else" \
+ " if load hostfs - ${kernel_addr_r} ${kernel_name}; then" \
+ " setenv fdt_high 0xffffffffffffffff;" \
+ " setenv initrd_high 0xffffffffffffffff;" \
+ " load hostfs - ${fdt_addr_r} ${fdtfile};" \
+ " load hostfs - ${ramdisk_addr_r} ${ramdisk_name};" \
+ " fdt addr ${fdt_addr_r};" \
+ " fdt resize;" \
+ " fdt chosen ${ramdisk_addr_r} ${filesize};" \
+ " booti $kernel_addr_r - $fdt_addr_r;" \
+ " fi;" \
+ "fi\0"
+#define BOOTENV_DEV_NAME_SMH(devtypeu, devtypel, instance) "smh "
+
+/* Boot sources for distro boot and load addresses, per board */
+
+#ifdef CONFIG_TARGET_VEXPRESS64_JUNO /* Arm Juno board */
+
#define BOOT_TARGET_DEVICES(func) \
func(USB, usb, 0) \
func(SATA, sata, 0) \
@@ -151,42 +198,74 @@
func(DHCP, dhcp, na) \
func(AFS, afs, na)
-#include <config_distro_bootcmd.h>
+#define VEXPRESS_KERNEL_ADDR 0x80080000
+#define VEXPRESS_PXEFILE_ADDR 0x8fb00000
+#define VEXPRESS_FDT_ADDR 0x8fc00000
+#define VEXPRESS_SCRIPT_ADDR 0x8fd00000
+#define VEXPRESS_RAMDISK_ADDR 0x8fe00000
-/*
- * Defines where the kernel and FDT exist in NOR flash and where it will
- * be copied into DRAM
- */
-#define CONFIG_EXTRA_ENV_SETTINGS \
- "kernel_name=norkern\0" \
- "kernel_alt_name=Image\0" \
- "kernel_addr_r=0x80080000\0" \
- "ramdisk_name=ramdisk.img\0" \
- "ramdisk_addr_r=0x88000000\0" \
- "fdtfile=board.dtb\0" \
- "fdt_alt_name=juno\0" \
- "fdt_addr_r=0x80000000\0" \
- BOOTENV
-
-#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP
-
-#define VEXPRESS_KERNEL_ADDR 0x80080000
-#define VEXPRESS_FDT_ADDR 0x8fc00000
-#define VEXPRESS_BOOT_ADDR 0x8fd00000
-#define VEXPRESS_RAMDISK_ADDR 0x8fe00000
+#define EXTRA_ENV_NAMES \
+ "kernel_name=norkern\0" \
+ "kernel_alt_name=Image\0" \
+ "ramdisk_name=ramdisk.img\0" \
+ "fdtfile=board.dtb\0" \
+ "fdt_alt_name=juno\0"
-#define CONFIG_EXTRA_ENV_SETTINGS \
- "kernel_name=Image\0" \
- "kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \
- "ramdisk_name=ramdisk.img\0" \
- "ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \
- "fdtfile=devtree.dtb\0" \
- "fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0" \
- "boot_name=boot.img\0" \
- "boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0"
+#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP /* ARMv8-A base model */
+
+#define BOOT_TARGET_DEVICES(func) \
+ func(SMH, smh, na) \
+ func(MEM, mem, na) \
+ FUNC_VIRTIO(func) \
+ func(PXE, pxe, na) \
+ func(DHCP, dhcp, na)
+
+#define VEXPRESS_KERNEL_ADDR 0x80080000
+#define VEXPRESS_PXEFILE_ADDR 0x8fa00000
+#define VEXPRESS_SCRIPT_ADDR 0x8fb00000
+#define VEXPRESS_FDT_ADDR 0x8fc00000
+#define VEXPRESS_BOOT_ADDR 0x8fd00000
+#define VEXPRESS_RAMDISK_ADDR 0x8fe00000
+
+#define EXTRA_ENV_NAMES \
+ "kernel_name=Image\0" \
+ "ramdisk_name=ramdisk.img\0" \
+ "fdtfile=devtree.dtb\0" \
+ "boot_name=boot.img\0" \
+ "boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0"
+#elif CONFIG_TARGET_VEXPRESS64_BASER_FVP /* ARMv8-R base model */
+
+#define BOOT_TARGET_DEVICES(func) \
+ func(MEM, mem, na) \
+ FUNC_VIRTIO(func) \
+ func(PXE, pxe, na) \
+ func(DHCP, dhcp, na)
+
+#define VEXPRESS_KERNEL_ADDR 0x00200000
+#define VEXPRESS_PXEFILE_ADDR 0x0fb00000
+#define VEXPRESS_FDT_ADDR 0x0fc00000
+#define VEXPRESS_SCRIPT_ADDR 0x0fd00000
+#define VEXPRESS_RAMDISK_ADDR 0x0fe00000
+
+#define EXTRA_ENV_NAMES \
+ "kernel_name=Image\0" \
+ "ramdisk_name=ramdisk.img\0" \
+ "fdtfile=board.dtb\0"
#endif
+#include <config_distro_bootcmd.h>
+
+/* Default load addresses and names for the different payloads. */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \
+ "ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \
+ "pxefile_addr_r=" __stringify(VEXPRESS_PXEFILE_ADDR) "\0" \
+ "fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0" \
+ "scriptaddr=" __stringify(VEXPRESS_SCRIPT_ADDR) "\0" \
+ EXTRA_ENV_NAMES \
+ BOOTENV
+
/* Monitor Command Prompt */
#define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */
#define CONFIG_SYS_MAXARGS 64 /* max command args */
diff --git a/include/fs.h b/include/fs.h
index b607b00..e2beba3 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -18,6 +18,7 @@ struct cmd_tbl;
#define FS_TYPE_BTRFS 5
#define FS_TYPE_SQUASHFS 6
#define FS_TYPE_EROFS 7
+#define FS_TYPE_SEMIHOSTING 8
struct blk_desc;
diff --git a/include/semihosting.h b/include/semihosting.h
new file mode 100644
index 0000000..f1f7346
--- /dev/null
+++ b/include/semihosting.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#ifndef _SEMIHOSTING_H
+#define _SEMIHOSTING_H
+
+/*
+ * These are the encoded instructions used to indicate a semihosting trap. They
+ * are named like SMH_ISA_INSN, where ISA is the instruction set (e.g.
+ * AArch64), and INSN is the mneumonic for the instruction.
+ */
+#define SMH_A64_HLT 0xD45E0000
+#define SMH_A32_SVC 0xEF123456
+#define SMH_A32_HLT 0xE10F0070
+#define SMH_T32_SVC 0xDFAB
+#define SMH_T32_HLT 0xBABC
+
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+/**
+ * semihosting_enabled() - Determine whether semihosting is supported
+ *
+ * Semihosting-based drivers should call this function before making other
+ * semihosting calls.
+ *
+ * Return: %true if a debugger is attached which supports semihosting, %false
+ * otherwise
+ */
+bool semihosting_enabled(void);
+
+/**
+ * disable_semihosting() - Cause semihosting_enabled() to return false
+ *
+ * If U-Boot ever receives an unhandled exception caused by a semihosting trap,
+ * the trap handler should call this function.
+ */
+void disable_semihosting(void);
+#else
+static inline bool semihosting_enabled(void)
+{
+ return CONFIG_IS_ENABLED(SEMIHOSTING);
+}
+
+static inline void disable_semihosting(void)
+{
+}
+#endif
+
+/**
+ * enum smh_open_mode - Numeric file modes for use with smh_open()
+ * MODE_READ: 'r'
+ * MODE_BINARY: 'b'
+ * MODE_PLUS: '+'
+ * MODE_WRITE: 'w'
+ * MODE_APPEND: 'a'
+ *
+ * These modes represent the mode string used by fopen(3) in a form which can
+ * be passed to smh_open(). These do NOT correspond directly to %O_RDONLY,
+ * %O_CREAT, etc; see fopen(3) for details. In particular, @MODE_PLUS
+ * effectively results in adding %O_RDWR, and @MODE_WRITE will add %O_TRUNC.
+ * For compatibility, @MODE_BINARY should be added when opening non-text files
+ * (such as images).
+ */
+enum smh_open_mode {
+ MODE_READ = 0x0,
+ MODE_BINARY = 0x1,
+ MODE_PLUS = 0x2,
+ MODE_WRITE = 0x4,
+ MODE_APPEND = 0x8,
+};
+
+/**
+ * smh_open() - Open a file on the host
+ * @fname: The name of the file to open
+ * @mode: The mode to use when opening the file
+ *
+ * Return: Either a file descriptor or a negative error on failure
+ */
+long smh_open(const char *fname, enum smh_open_mode mode);
+
+/**
+ * smh_read() - Read data from a file
+ * @fd: A file descriptor returned from smh_open()
+ * @memp: Pointer to a buffer of memory of at least @len bytes
+ * @len: The number of bytes to read
+ *
+ * Return:
+ * * The number of bytes read on success, with 0 indicating %EOF
+ * * A negative error on failure
+ */
+long smh_read(long fd, void *memp, size_t len);
+
+/**
+ * smh_write() - Write data to a file
+ * @fd: A file descriptor returned from smh_open()
+ * @memp: Pointer to a buffer of memory of at least @len bytes
+ * @len: The number of bytes to read
+ * @written: Pointer which will be updated with the actual bytes written
+ *
+ * Return: 0 on success or negative error on failure
+ */
+long smh_write(long fd, const void *memp, size_t len, ulong *written);
+
+/**
+ * smh_close() - Close an open file
+ * @fd: A file descriptor returned from smh_open()
+ *
+ * Return: 0 on success or negative error on failure
+ */
+long smh_close(long fd);
+
+/**
+ * smh_flen() - Get the length of a file
+ * @fd: A file descriptor returned from smh_open()
+ *
+ * Return: The length of the file, in bytes, or a negative error on failure
+ */
+long smh_flen(long fd);
+
+/**
+ * smh_seek() - Seek to a position in a file
+ * @fd: A file descriptor returned from smh_open()
+ * @pos: The offset (in bytes) to seek to
+ *
+ * Return: 0 on success or negative error on failure
+ */
+long smh_seek(long fd, long pos);
+
+/**
+ * smh_getc() - Read a character from stdin
+ *
+ * Return: The character read, or a negative error on failure
+ */
+int smh_getc(void);
+
+/**
+ * smh_putc() - Print a character on stdout
+ * @ch: The character to print
+ */
+void smh_putc(char ch);
+
+/**
+ * smh_write0() - Print a nul-terminated string on stdout
+ * @s: The string to print
+ */
+void smh_puts(const char *s);
+
+#endif /* _SEMIHOSTING_H */
diff --git a/include/semihostingfs.h b/include/semihostingfs.h
new file mode 100644
index 0000000..25ebdbb
--- /dev/null
+++ b/include/semihostingfs.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022, Sean Anderson <sean.anderson@seco.com>
+ * Copyright (c) 2012, Google Inc.
+ */
+
+#ifndef __SEMIHOSTING_FS__
+#define __SEMIHOSTING_FS__
+
+struct blk_desc;
+struct disk_partition;
+
+int smh_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info);
+void smh_fs_close(void);
+int smh_fs_size(const char *filename, loff_t *size);
+int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len,
+ loff_t *actread);
+int smh_fs_write(const char *filename, void *buf, loff_t offset,
+ loff_t len, loff_t *actwrite);
+
+#endif
diff --git a/include/serial.h b/include/serial.h
index 19a8c0c..8c2e7ad 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -23,6 +23,7 @@ struct serial_device {
void default_serial_puts(const char *s);
extern struct serial_device serial_smc_device;
+extern struct serial_device serial_smh_device;
extern struct serial_device serial_scc_device;
extern struct serial_device *default_serial_console(void);
@@ -195,6 +196,24 @@ struct dm_serial_ops {
*/
int (*putc)(struct udevice *dev, const char ch);
/**
+ * puts() - Write a string
+ *
+ * This writes a string. This function should be implemented only if
+ * writing multiple characters at once is more performant than just
+ * calling putc() in a loop.
+ *
+ * If the whole string cannot be written at once, then this function
+ * should return the number of characters written. Returning a negative
+ * error code implies that no characters were written. If this function
+ * returns 0, then it will be called again with the same arguments.
+ *
+ * @dev: Device pointer
+ * @s: The string to write
+ * @len: The length of the string to write.
+ * @return The number of characters written on success, or -ve on error
+ */
+ ssize_t (*puts)(struct udevice *dev, const char *s, size_t len);
+ /**
* pending() - Check if input/output characters are waiting
*
* This can be used to return an indication of the number of waiting