Browse Source
* changes: arm_fpga: Add platform documentation arm_fpga: Add post-build linker script arm_fpga: Add ROM trampoline arm_fpga: Add devicetree file arm_fpga: Remove SPE PMU DT node if SPE is not available arm_fpga: Adjust GICR size in DT to match number of cores fdt: Add function to adjust GICv3 redistributor size drivers: arm: gicv3: Allow detecting number of corespull/1979/head
André Przywara
4 years ago
committed by
TrustedFirmware Code Review
13 changed files with 403 additions and 1 deletions
@ -0,0 +1,97 @@ |
|||
Arm FPGA Platform |
|||
================= |
|||
|
|||
This platform supports FPGA images used internally in Arm Ltd., for |
|||
testing and bringup of new cores. With that focus, peripheral support is |
|||
minimal: there is no mass storage or display output, for instance. Also |
|||
this port ignores any power management features of the platform. |
|||
Some interconnect setup is done internally by the platform, so the TF-A code |
|||
just needs to setup UART and GIC. |
|||
|
|||
The FPGA platform requires to pass on a DTB for the non-secure payload |
|||
(mostly Linux), so we let TF-A use information from the DTB for dynamic |
|||
configuration: the UART and GIC base addresses are read from there. |
|||
|
|||
As a result this port is a fairly generic BL31-only port, which can serve |
|||
as a template for a minimal new (and possibly DT-based) platform port. |
|||
|
|||
The aim of this port is to support as many FPGA images as possible with |
|||
a single build. Image specific data must be described in the DTB or should |
|||
be auto-detected at runtime. |
|||
|
|||
As the number and topology layout of the CPU cores differs significantly |
|||
across the various images, this is detected at runtime by BL31. |
|||
The /cpus node in the DT will be added and filled accordingly, as long as |
|||
it does not exist already. |
|||
|
|||
Platform-specific build options |
|||
------------------------------- |
|||
|
|||
- ``SUPPORT_UNKNOWN_MPID`` : Boolean option to allow unknown MPIDR registers. |
|||
Normally TF-A panics if it encounters a MPID value not matched to its |
|||
internal list, but for new or experimental cores this creates a lot of |
|||
churn. With this option, the code will fall back to some basic CPU support |
|||
code (only architectural system registers, and no errata). |
|||
Default value of this flag is 1. |
|||
|
|||
- ``PRELOADED_BL33_BASE`` : Physical address of the BL33 non-secure payload. |
|||
It must have been loaded into DRAM already, typically this is done by |
|||
the script that also loads BL31 and the DTB. |
|||
It defaults to 0x80080000, which is the traditional load address for an |
|||
arm64 Linux kernel. |
|||
|
|||
- ``FPGA_PRELOADED_DTB_BASE`` : Physical address of the flattened device |
|||
tree blob (DTB). This DT will be used by TF-A for dynamic configuration, |
|||
so it must describe at least the UART and a GICv3 interrupt controller. |
|||
The DT gets amended by the code, to potentially add a command line and |
|||
fill the CPU topology nodes. It will also be passed on to BL33, by |
|||
putting its address into the x0 register before jumping to the entry |
|||
point (following the Linux kernel boot protocol). |
|||
It defaults to 0x80070000, which is 64KB before the BL33 load address. |
|||
|
|||
- ``FPGA_PRELOADED_CMD_LINE`` : Physical address of the command line to |
|||
put into the devicetree blob. Due to the lack of a proper bootloader, |
|||
a command line can be put somewhere into memory, so that BL31 will |
|||
detect it and copy it into the DTB passed on to BL33. |
|||
To avoid random garbage, there needs to be a "CMD:" signature before the |
|||
actual command line. |
|||
Defaults to 0x1000, which is normally in the "ROM" space of the typical |
|||
FPGA image (which can be written by the FPGA payload uploader, but is |
|||
read-only to the CPU). The FPGA payload tool should be given a text file |
|||
containing the desired command line, prefixed by the "CMD:" signature. |
|||
|
|||
Building the TF-A image |
|||
----------------------- |
|||
|
|||
.. code:: shell |
|||
|
|||
make PLAT=arm_fgpa DEBUG=1 |
|||
|
|||
This will use the default load addresses as described above. When those |
|||
addresses need to differ for a certain setup, they can be passed on the |
|||
make command line: |
|||
|
|||
.. code:: shell |
|||
|
|||
make PLAT=arm_fgpa DEBUG=1 PRELOADED_BL33_BASE=0x80200000 FPGA_PRELOADED_DTB_BASE=0x80180000 bl31 |
|||
|
|||
Running the TF-A image |
|||
---------------------- |
|||
|
|||
After building TF-A, the actual TF-A code will be located in ``bl31.bin`` in |
|||
the build directory. |
|||
Additionally there is a ``bl31.axf`` ELF file, which contains BL31, as well |
|||
as some simple ROM trampoline code (required by the Arm FPGA boot flow) and |
|||
a generic DTB to support most of the FPGA images. This can be simply handed |
|||
over to the FPGA payload uploader, which will take care of loading the |
|||
components at their respective load addresses. In addition to this file |
|||
you need at least a BL33 payload (typically a Linux kernel image), optionally |
|||
a Linux initrd image file and possibly a command line: |
|||
|
|||
.. code:: shell |
|||
|
|||
fpga-run ... -m bl31.axf -l auto -m Image -l 0x80080000 -m initrd.gz -l 0x84000000 -m cmdline.txt -l 0x1000 |
|||
|
|||
-------------- |
|||
|
|||
*Copyright (c) 2020, Arm Limited. All rights reserved.* |
@ -0,0 +1,102 @@ |
|||
// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) |
|||
/* |
|||
* Copyright (c) 2020, Arm Limited. All rights reserved. |
|||
* |
|||
* Devicetree for the Arm Ltd. FPGA platform |
|||
* Number and kind of CPU cores differs from image to image, so the |
|||
* topology is auto-detected by BL31, and the /cpus node is created and |
|||
* populated accordingly at runtime. |
|||
*/ |
|||
|
|||
#include <dt-bindings/interrupt-controller/arm-gic.h> |
|||
|
|||
/dts-v1/; |
|||
|
|||
/ { |
|||
model = "ARM FPGA"; |
|||
compatible = "arm,fpga", "arm,vexpress"; |
|||
interrupt-parent = <&gic>; |
|||
#address-cells = <2>; |
|||
#size-cells = <2>; |
|||
|
|||
aliases { |
|||
serial0 = &dbg_uart; |
|||
}; |
|||
|
|||
chosen { |
|||
stdout-path = "serial0:38400n8"; |
|||
bootargs = "console=ttyAMA0,38400n8 earlycon"; |
|||
/* Allow to upload a generous 100MB initrd payload. */ |
|||
linux,initrd-start = <0x0 0x84000000>; |
|||
linux,initrd-end = <0x0 0x85400000>; |
|||
}; |
|||
|
|||
/* /cpus node will be added by BL31 at runtime. */ |
|||
|
|||
psci { |
|||
compatible = "arm,psci-0.2"; |
|||
method = "smc"; |
|||
}; |
|||
|
|||
timer { |
|||
compatible = "arm,armv8-timer"; |
|||
clock-frequency = <10000000>; |
|||
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>; |
|||
}; |
|||
|
|||
/* This node will be removed at runtime on cores without SPE. */ |
|||
spe-pmu { |
|||
compatible = "arm,statistical-profiling-extension-v1"; |
|||
interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>; |
|||
}; |
|||
|
|||
memory@80000000 { |
|||
device_type = "memory"; |
|||
reg = <0x0 0x80000000 0x0 0x80000000>, |
|||
<0x8 0x80000000 0x1 0x80000000>; |
|||
}; |
|||
|
|||
|
|||
bus_refclk: refclk { |
|||
compatible = "fixed-clock"; |
|||
#clock-cells = <0>; |
|||
clock-frequency = <100000000>; |
|||
clock-output-names = "apb_pclk"; |
|||
}; |
|||
|
|||
uartclk: baudclock { |
|||
compatible = "fixed-clock"; |
|||
#clock-cells = <0>; |
|||
clock-frequency = <10000000>; |
|||
clock-output-names = "uartclk"; |
|||
}; |
|||
|
|||
dbg_uart: serial@7ff80000 { |
|||
compatible = "arm,pl011", "arm,primecell"; |
|||
reg = <0x0 0x7ff80000 0x0 0x00001000>; |
|||
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; |
|||
clocks = <&uartclk>, <&bus_refclk>; |
|||
clock-names = "uartclk", "apb_pclk"; |
|||
}; |
|||
|
|||
gic: interrupt-controller@30000000 { |
|||
compatible = "arm,gic-v3"; |
|||
#address-cells = <2>; |
|||
#interrupt-cells = <3>; |
|||
#size-cells = <2>; |
|||
ranges; |
|||
interrupt-controller; |
|||
reg = <0x0 0x30000000 0x0 0x00010000>, /* GICD */ |
|||
/* The GICR size will be adjusted at runtime to match the cores. */ |
|||
<0x0 0x30040000 0x0 0x00020000>; /* GICR for one core */ |
|||
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; |
|||
}; |
|||
}; |
@ -0,0 +1,47 @@ |
|||
/* |
|||
* Copyright (c) 2020, ARM Limited. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
* |
|||
* Linker script for the Arm Ltd. FPGA boards to generate an ELF file that |
|||
* contains the ROM trampoline, BL31 and the DTB. |
|||
* |
|||
* This allows to pass just one file to the uploader tool, and automatically |
|||
* provides the correct load addresses. |
|||
*/ |
|||
|
|||
#include <platform_def.h> |
|||
|
|||
OUTPUT_FORMAT("elf64-littleaarch64") |
|||
OUTPUT_ARCH(aarch64) |
|||
|
|||
INPUT(./bl31/bl31.elf) |
|||
INPUT(./rom_trampoline.o) |
|||
|
|||
TARGET(binary) |
|||
INPUT(./fdts/arm_fpga.dtb) |
|||
|
|||
ENTRY(_start) |
|||
|
|||
SECTIONS |
|||
{ |
|||
.rom (0x0): { |
|||
*rom_trampoline.o(.text*) |
|||
KEEP(*(.rom)) |
|||
} |
|||
|
|||
.bl31 (BL31_BASE): { |
|||
ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned"); |
|||
*bl31.elf(.text* .data* .rodata* ro* .bss*) |
|||
*bl31.elf(.stack) |
|||
} |
|||
|
|||
.dtb (FPGA_PRELOADED_DTB_BASE): { |
|||
ASSERT(. == ALIGN(8), "DTB address is not 8-byte aligned"); |
|||
*arm_fpga.dtb |
|||
} |
|||
|
|||
/DISCARD/ : { *(.debug_*) } |
|||
/DISCARD/ : { *(.note*) } |
|||
/DISCARD/ : { *(.comment*) } |
|||
} |
@ -0,0 +1,24 @@ |
|||
/* |
|||
* Copyright (c) 2020, ARM Limited. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
* |
|||
* The Arm Ltd. FPGA images start execution at address 0x0, which is |
|||
* mapped at an (emulated) ROM image. The payload uploader can write to |
|||
* this memory, but write access by the CPU cores is prohibited. |
|||
* |
|||
* Provide a simple trampoline to start BL31 execution at the actual |
|||
* load address. We put the DTB address in x0, so any code in DRAM could |
|||
* make use of that information (not yet used in BL31 right now). |
|||
*/ |
|||
|
|||
#include <asm_macros.S> |
|||
#include <common/bl_common.ld.h> |
|||
|
|||
.text |
|||
.global _start |
|||
|
|||
_start: |
|||
mov_imm x1, BL31_BASE /* beginning of DRAM */ |
|||
mov_imm x0, FPGA_PRELOADED_DTB_BASE |
|||
br x1 |
Loading…
Reference in new issue