Merge pull request #1157 from antonio-nino-diaz-arm/an/rpi3
Introduce AArch64 Raspberry Pi 3 port
This commit is contained in:
commit
3923bdb019
|
@ -0,0 +1,364 @@
|
|||
Arm Trusted Firmware for Raspberry Pi 3
|
||||
=======================================
|
||||
|
||||
.. section-numbering::
|
||||
:suffix: .
|
||||
|
||||
.. contents::
|
||||
|
||||
The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four
|
||||
Cortex-A53 cores, which makes it possible to have a port of the Arm Trusted
|
||||
Firmware.
|
||||
|
||||
The following instructions explain how to use this port of the Trusted Firmware
|
||||
with the default distribution of `Raspbian`_ because that's the distribution
|
||||
officially supported by the Raspberry Pi Foundation. At the moment of writing
|
||||
this, the officially supported kernel is a AArch32 kernel. This doesn't mean
|
||||
that this port of the Trusted Firmware can't boot a AArch64 kernel. The `Linux
|
||||
tree fork`_ maintained by the Foundation can be compiled for AArch64 by
|
||||
following the steps in `AArch64 kernel build instructions`_.
|
||||
|
||||
**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM,
|
||||
which is available from both the Non-secure and Secure worlds. This port
|
||||
shouldn't be considered more than a prototype to play with and implement
|
||||
elements like PSCI to support the Linux kernel.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The SoC used by the Raspberry Pi 3 is the Broadcom BCM2837. It is a SoC with a
|
||||
VideoCore IV that acts as primary processor (and loads everything from the SD
|
||||
card) and is located between all Arm cores and the DRAM. Check the `Raspberry Pi
|
||||
3 documentation`_ for more information.
|
||||
|
||||
This explains why it is possible to change the execution state (AArch64/AArch32)
|
||||
depending on a few files on the SD card. We only care about the cases in which
|
||||
the cores boot in AArch64 mode.
|
||||
|
||||
The rules are simple:
|
||||
|
||||
- If a file called ``kernel8.img`` is located on the ``boot`` partition of the
|
||||
SD card, it will load it and execute in EL2 in AArch64. Basically, it executes
|
||||
a `default AArch64 stub`_ at address **0x0** that jumps to the kernel.
|
||||
|
||||
- If there is also a file called ``armstub8.bin``, it will load it at address
|
||||
**0x0** (instead of the default stub) and execute it in EL3 in AArch64. All
|
||||
the cores are powered on at the same time and start at address **0x0**.
|
||||
|
||||
This means that we can use the default AArch32 kernel provided in the official
|
||||
`Raspbian`_ distribution by renaming it to ``kernel8.img``, while the Trusted
|
||||
Firmware and anything else we need is in ``armstub8.bin``. This way we can
|
||||
forget about the default bootstrap code. When using a AArch64 kernel, it is only
|
||||
needed to make sure that the name on the SD card is ``kernel8.img``.
|
||||
|
||||
Ideally, we want to load the kernel and have all cores available, which means
|
||||
that we need to make the secondary cores work in the way the kernel expects, as
|
||||
explained in `Secondary cores`_. In practice, a small bootstrap is needed
|
||||
between the Trusted Firmware and the kernel.
|
||||
|
||||
To get the most out of a AArch32 kernel, we want to boot it in Hypervisor mode
|
||||
in AArch32. This means that BL33 can't be in EL2 in AArch64 mode. The
|
||||
architecture specifies that AArch32 Hypervisor mode isn't present when AArch64
|
||||
is used for EL2. When using a AArch64 kernel, it should simply start in EL2.
|
||||
|
||||
Placement of images
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding
|
||||
between them so that the addresses they are loaded to match the ones specified
|
||||
when compiling the Trusted Firmware.
|
||||
|
||||
The device tree block is loaded by the VideoCore loader from an appropriate
|
||||
file, but we can specify the address it is loaded to in ``config.txt``.
|
||||
|
||||
The file ``kernel8.img`` contains a kernel image that is loaded to the address
|
||||
specified in ``config.txt``. The `Linux kernel tree`_ has information about how
|
||||
a AArch32 Linux kernel image is loaded in ``Documentation/arm/Booting``:
|
||||
|
||||
::
|
||||
|
||||
The zImage may also be placed in system RAM and called there. The
|
||||
kernel should be placed in the first 128MiB of RAM. It is recommended
|
||||
that it is loaded above 32MiB in order to avoid the need to relocate
|
||||
prior to decompression, which will make the boot process slightly
|
||||
faster.
|
||||
|
||||
There are no similar restrictions for AArch64 kernels, as specified in the file
|
||||
``Documentation/arm64/booting.txt``.
|
||||
|
||||
This means that we need to avoid the first 128 MiB of RAM when placing the
|
||||
Trusted Firmware images (and specially the first 32 MiB, as they are directly
|
||||
used to place the uncompressed AArch32 kernel image. This way, both AArch32 and
|
||||
AArch64 kernels can be placed at the same address.
|
||||
|
||||
In the end, the images look like the following diagram when placed in memory.
|
||||
All addresses are Physical Addresses from the point of view of the Arm cores.
|
||||
Again, note that this is all just part of the same DRAM that goes from
|
||||
**0x00000000** to **0x3F000000**, it just has different names to simulate a real
|
||||
secure platform!
|
||||
|
||||
::
|
||||
|
||||
0x00000000 +-----------------+
|
||||
| ROM | BL1
|
||||
0x00010000 +-----------------+
|
||||
| FIP |
|
||||
0x00200000 +-----------------+
|
||||
| |
|
||||
| ... |
|
||||
| |
|
||||
0x01000000 +-----------------+
|
||||
| Kernel |
|
||||
+-----------------+
|
||||
| |
|
||||
| ... |
|
||||
| |
|
||||
0x02000000 +-----------------+
|
||||
| DTB |
|
||||
+-----------------+
|
||||
| |
|
||||
| ... |
|
||||
| |
|
||||
0x10000000 +-----------------+
|
||||
| Secure SRAM | BL2, BL31
|
||||
0x10100000 +-----------------+
|
||||
| Secure DRAM |
|
||||
0x10300000 +-----------------+
|
||||
| Non-secure DRAM | BL33
|
||||
0x11000000 +-----------------+
|
||||
| |
|
||||
| ... |
|
||||
| |
|
||||
0x3F000000 +-----------------+
|
||||
| I/O |
|
||||
0x40000000 +-----------------+
|
||||
|
||||
The area between **0x10000000** and **0x11000000** has to be protected so that
|
||||
the kernel doesn't use it. That is done by adding ``memmap=256M$16M`` to the
|
||||
command line passed to the kernel. See the `Setup SD card`_ instructions to see
|
||||
how to do it.
|
||||
|
||||
The last 16 MiB of DRAM can only be accessed by the VideoCore, that has
|
||||
different mappings than the Arm cores in which the I/O addresses don't overlap
|
||||
the DRAM. The memory reserved to be used by the VideoCore is always placed at
|
||||
the end of the DRAM, so this space isn't wasted.
|
||||
|
||||
Considering the 128 MiB allocated to the GPU and the 16 MiB allocated for the
|
||||
Trusted Firmware, there are 880 MiB available for Linux.
|
||||
|
||||
Boot sequence
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The boot sequence of the Trusted Firmware is the usual one except when booting
|
||||
a AArch32 kernel. In that case, BL33 is booted in AArch32 Hypervisor mode so
|
||||
that it can jump to the kernel in the same mode and let it take over that
|
||||
privilege level. If BL33 was running in EL2 in AArch64 (as in the default
|
||||
bootflow of the Trusted Firmware) it could only jump to the kernel in AArch32 in
|
||||
Supervisor mode.
|
||||
|
||||
The `Linux kernel tree`_ has instructions on how to jump to the Linux kernel
|
||||
in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The
|
||||
bootstrap should take care of this.
|
||||
|
||||
Secondary cores
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to
|
||||
use mailboxes to trap the secondary cores until they are ready to jump to the
|
||||
kernel. This mailbox is located at a different address in the AArch32 default
|
||||
kernel than in the AArch64 kernel.
|
||||
|
||||
Also, this port of the Trusted Firmware has another Trusted Mailbox in Shared BL
|
||||
RAM. During cold boot, all secondary cores wait in a loop until they are given
|
||||
given an address to jump to in this Mailbox (``bl31_warm_entrypoint``).
|
||||
|
||||
Once BL31 has finished and the primary core has jumped to the BL33 payload, it
|
||||
has to call ``PSCI_CPU_ON`` to release the secondary CPUs from the wait loop.
|
||||
The payload then makes them wait in another waitloop listening from messages
|
||||
from the kernel. When the primary CPU jumps into the kernel, it will send an
|
||||
address to the mailbox so that the secondary CPUs jump to it and are recognised
|
||||
by the kernel.
|
||||
|
||||
Build Instructions
|
||||
------------------
|
||||
|
||||
To boot a AArch64 kernel, only the AArch64 toolchain is required.
|
||||
|
||||
To boot a AArch32 kernel, both AArch64 and AArch32 toolchains are required. The
|
||||
AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit
|
||||
kernel.
|
||||
|
||||
First, clone and compile `Raspberry Pi 3 Arm Trusted Firmware bootstrap`_.
|
||||
Choose the one needed for the architecture of your kernel.
|
||||
|
||||
Then compile the Arm Trusted Firmware. For a AArch32 kernel, use the following
|
||||
command line:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
|
||||
RPI3_BL33_IN_AARCH32=1 \
|
||||
BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin \
|
||||
all fip
|
||||
|
||||
For a AArch64 kernel, use this other command line:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
|
||||
BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin \
|
||||
all fip
|
||||
|
||||
Then, join BL1 and the FIP with the following instructions (replace ``release``
|
||||
by ``debug`` if you set the build option ``DEBUG=1``):
|
||||
|
||||
.. code:: shell
|
||||
|
||||
cp build/rpi3/release/bl1.bin bl1.pad.bin
|
||||
truncate --size=65536 bl1.pad.bin
|
||||
cat bl1.pad.bin build/rpi3/release/fip.bin > armstub8.bin
|
||||
|
||||
The resulting file, ``armstub8.bin``, contains BL1 and the FIP in the place they
|
||||
need to be for the Trusted Firmware to boot correctly. Now, follow the
|
||||
instructions in `Setup SD card`_.
|
||||
|
||||
The following build options are supported:
|
||||
|
||||
- ``PRELOADED_BL33_BASE``: Specially useful because the file ``kernel8.img`` can
|
||||
be loaded anywhere by modifying the file ``config.txt``. It doesn't have to
|
||||
contain a kernel, it could have any arbitrary payload.
|
||||
|
||||
- ``RESET_TO_BL31``: Set to 1 by default. If using a 32-bit kernel like
|
||||
`Raspbian`_, the space used by BL1 can overwritten by the kernel when it is
|
||||
being loaded. Even when using a AArch64 kernel the region used by
|
||||
BL1 isn't protected and the kernel could overwrite it. The space used by BL31
|
||||
is reserved by the command line passed to the kernel.
|
||||
|
||||
- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image.
|
||||
By default this option is 0, which means that the Trusted Firmware will jump
|
||||
to BL33 in EL2 in AArch64 mode. If set to 1, it will jump to BL33 in
|
||||
Hypervisor in AArch32 mode.
|
||||
|
||||
The following is not currently supported:
|
||||
|
||||
- AArch32 for the Trusted Firmware itself.
|
||||
|
||||
- ``EL3_PAYLOAD_BASE``: The reason is that you can already load anything to any
|
||||
address by changing the file ``armstub8.bin``, so there's no point in using
|
||||
the Trusted Firmware in this case.
|
||||
|
||||
- ``LOAD_IMAGE_V2=0``: Only version 2 is supported.
|
||||
|
||||
AArch64 kernel build instructions
|
||||
---------------------------------
|
||||
|
||||
The following instructions show how to install and run a AArch64 kernel by
|
||||
using a SD card with the default `Raspbian`_ install as base. Skip them if you
|
||||
want to use the default 32-bit kernel.
|
||||
|
||||
Note that this system won't be fully 64-bit because all the tools in the
|
||||
filesystem are 32-bit binaries, but it's a quick way to get it working, and it
|
||||
allows the user to run 64-bit binaries in addition to 32-bit binaries.
|
||||
|
||||
1. Clone the `Linux tree fork`_ maintained by the Raspberry Pi Foundation. To
|
||||
speed things up, do a shallow clone of the desired branch.
|
||||
|
||||
.. code:: shell
|
||||
|
||||
git clone --depth=1 -b rpi-4.14.y https://github.com/raspberrypi/linux
|
||||
cd linux
|
||||
|
||||
2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is
|
||||
1.5 times the number of CPUs in your computer. This may take some time to
|
||||
finish.
|
||||
|
||||
.. code:: shell
|
||||
|
||||
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig
|
||||
make -j 6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
|
||||
|
||||
3. Copy the kernel image and the device tree to the SD card. Replace the path
|
||||
by the corresponding path in your computers to the ``boot`` partition of the
|
||||
SD card.
|
||||
|
||||
.. code:: shell
|
||||
|
||||
cp arch/arm64/boot/Image /path/to/boot/kernel8.img
|
||||
cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/
|
||||
|
||||
4. Install the kernel modules. Replace the path by the corresponding path to the
|
||||
filesystem partition of the SD card on your computer.
|
||||
|
||||
.. code:: shell
|
||||
|
||||
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \
|
||||
INSTALL_MOD_PATH=/path/to/filesystem modules_install
|
||||
|
||||
5. Follow the instructions in `Setup SD card`_ except for the step of renaming
|
||||
the existing ``kernel7.img`` (we have already copied a AArch64 kernel).
|
||||
|
||||
Setup SD card
|
||||
-------------
|
||||
|
||||
The instructions assume that you have an SD card with a fresh install of
|
||||
`Raspbian`_ (or that, at least, the ``boot`` partition is untouched, or nearly
|
||||
untouched). They have been tested with the image available in 2017-09-07.
|
||||
|
||||
1. Insert the SD card and open the ``boot`` partition.
|
||||
|
||||
2. Rename ``kernel7.img`` to ``kernel8.img``. This tricks the VideoCore
|
||||
bootloader into booting the Arm cores in AArch64 mode, like the Trusted
|
||||
Firmware needs, even though the kernel is not compiled for AArch64.
|
||||
|
||||
3. Copy ``armstub8.bin`` here. When ``kernel8.img`` is available, The VideoCore
|
||||
bootloader will look for a file called ``armstub8.bin`` and load it at
|
||||
address **0x0** instead of a predefined one.
|
||||
|
||||
4. Open ``cmdline.txt`` and add ``memmap=256M$16M`` to prevent the kernel from
|
||||
using the memory needed by the Trusted Firmware. If you want to enable the
|
||||
serial port "Mini UART", make sure that this file also contains
|
||||
``console=serial0,115200 console=tty1``.
|
||||
|
||||
Note that the 16 MiB reserved this way won't be available for Linux, the same
|
||||
way as the memory reserved in DRAM for the GPU isn't available.
|
||||
|
||||
5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1``
|
||||
is only needed to enable debugging through the Mini UART):
|
||||
|
||||
::
|
||||
|
||||
enable_uart=1
|
||||
kernel_address=0x01000000
|
||||
device_tree_address=0x02000000
|
||||
|
||||
If you connect a serial cable to the Mini UART and your computer, and connect
|
||||
to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some
|
||||
text. In the case of an AArch32 kernel, you should see something like this:
|
||||
|
||||
::
|
||||
|
||||
NOTICE: Booting Trusted Firmware
|
||||
NOTICE: BL1: v1.4(release):v1.4-329-g61e94684-dirty
|
||||
NOTICE: BL1: Built : 00:09:25, Nov 6 2017
|
||||
NOTICE: BL1: Booting BL2
|
||||
NOTICE: BL2: v1.4(release):v1.4-329-g61e94684-dirty
|
||||
NOTICE: BL2: Built : 00:09:25, Nov 6 2017
|
||||
NOTICE: BL1: Booting BL31
|
||||
NOTICE: BL31: v1.4(release):v1.4-329-g61e94684-dirty
|
||||
NOTICE: BL31: Built : 00:09:25, Nov 6 2017
|
||||
[ 0.266484] bcm2835-aux-uart 3f215040.serial: could not get clk: -517
|
||||
|
||||
Raspbian GNU/Linux 9 raspberrypi ttyS0
|
||||
raspberrypi login:
|
||||
|
||||
Just enter your credentials, everything should work as expected. Note that the
|
||||
HDMI output won't show any text during boot.
|
||||
|
||||
.. _default Arm stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub7.S
|
||||
.. _default AArch64 stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S
|
||||
.. _Linux kernel tree: https://github.com/torvalds/linux
|
||||
.. _Linux tree fork: https://github.com/raspberrypi/linux
|
||||
.. _Raspberry Pi 3: https://www.raspberrypi.org/products/raspberry-pi-3-model-b/
|
||||
.. _Raspberry Pi 3 Arm Trusted Firmware bootstrap: https://github.com/AntonioND/rpi3-arm-tf-bootstrap
|
||||
.. _Raspberry Pi 3 documentation: https://www.raspberrypi.org/documentation/
|
||||
.. _Raspbian: https://www.raspberrypi.org/downloads/raspbian/
|
|
@ -71,6 +71,15 @@ Files:
|
|||
|
||||
- plat/mediatek/\*
|
||||
|
||||
Raspberry Pi 3 platform sub-maintainer
|
||||
--------------------------------------
|
||||
|
||||
Antonio Niño Díaz (antonio.ninodiaz@arm.com, `antonio-nino-diaz-arm`_)
|
||||
|
||||
Files:
|
||||
|
||||
- plat/rpi3/\*
|
||||
|
||||
RockChip platform sub-maintainer
|
||||
--------------------------------
|
||||
|
||||
|
@ -96,6 +105,7 @@ ARMv7 architecture sub-maintainer
|
|||
|
||||
Etienne Carriere (etienne.carriere@linaro.org, `etienne-lms`_)
|
||||
|
||||
.. _antonio-nino-diaz-arm: https://github.com/antonio-nino-diaz-arm
|
||||
.. _danh-arm: https://github.com/danh-arm
|
||||
.. _davidcunado-arm: https://github.com/davidcunado-arm
|
||||
.. _jenswi-linaro: https://github.com/jenswi-linaro
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "../rpi3_hw.h"
|
||||
|
||||
.globl plat_crash_console_flush
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl platform_mem_init
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_my_core_pos
|
||||
.globl plat_reset_handler
|
||||
.globl plat_rpi3_calc_core_pos
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_my_core_pos(void)
|
||||
*
|
||||
* This function uses the plat_rpi3_calc_core_pos()
|
||||
* definition to get the index of the calling CPU.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_my_core_pos
|
||||
mrs x0, mpidr_el1
|
||||
b plat_rpi3_calc_core_pos
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
|
||||
*
|
||||
* CorePos = (ClusterId * 4) + CoreId
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_rpi3_calc_core_pos
|
||||
and x1, x0, #MPIDR_CPU_MASK
|
||||
and x0, x0, #MPIDR_CLUSTER_MASK
|
||||
add x0, x1, x0, LSR #6
|
||||
ret
|
||||
endfunc plat_rpi3_calc_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
|
||||
cmp x0, #RPI3_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
*
|
||||
* This function performs any platform specific actions
|
||||
* needed for a secondary cpu after a cold reset e.g
|
||||
* mark the cpu's presence, mechanism to place it in a
|
||||
* holding pen etc.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
/* Calculate address of our hold entry */
|
||||
bl plat_my_core_pos
|
||||
lsl x0, x0, #3
|
||||
mov_imm x2, PLAT_RPI3_TM_HOLD_BASE
|
||||
add x0, x0, x2
|
||||
|
||||
/*
|
||||
* This code runs way before requesting the warmboot of this core,
|
||||
* so it is possible to clear the mailbox before getting a request
|
||||
* to boot.
|
||||
*/
|
||||
mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT
|
||||
str x1,[x0]
|
||||
|
||||
/* Wait until we have a go */
|
||||
poll_mailbox:
|
||||
wfe
|
||||
ldr x1, [x0]
|
||||
cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO
|
||||
bne poll_mailbox
|
||||
|
||||
/* Jump to the provided entrypoint */
|
||||
mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT
|
||||
ldr x1, [x0]
|
||||
br x1
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* uintptr_t plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between a cold and a warm
|
||||
* boot.
|
||||
*
|
||||
* This functions returns:
|
||||
* - 0 for a cold boot.
|
||||
* - Any other value for a warm boot.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* TODO: support warm boot */
|
||||
mov x0, #0
|
||||
ret
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void platform_mem_init (void);
|
||||
*
|
||||
* No need to carry out any memory initialization.
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_init(void)
|
||||
* Function to initialize the crash console
|
||||
* without a C Runtime to print crash report.
|
||||
* Clobber list : x0 - x3
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, PLAT_RPI3_UART_BASE
|
||||
mov_imm x1, PLAT_RPI3_UART_CLK_IN_HZ
|
||||
mov_imm x2, PLAT_RPI3_UART_BAUDRATE
|
||||
b console_core_init
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_putc(int c)
|
||||
* Function to print a character on the crash
|
||||
* console without a C Runtime.
|
||||
* Clobber list : x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, PLAT_RPI3_UART_BASE
|
||||
b console_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_flush()
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* Out : return -1 on error else return 0.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
mov_imm x1, PLAT_RPI3_UART_BASE
|
||||
b console_core_flush
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void plat_reset_handler(void);
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_reset_handler
|
||||
/* use the 19.2 MHz clock for the architected timer */
|
||||
mov x0, #RPI3_INTC_BASE_ADDRESS
|
||||
mov w1, #0x80000000
|
||||
str wzr, [x0, #RPI3_INTC_CONTROL_OFFSET]
|
||||
str w1, [x0, #RPI3_INTC_PRESCALER_OFFSET]
|
||||
|
||||
/* wire mailbox 3 to the FIQ line */
|
||||
mov w1, RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ
|
||||
str w1, [x0, #RPI3_INTC_MBOX_CONTROL_OFFSET]
|
||||
ret
|
||||
endfunc plat_reset_handler
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <bl_common.h>
|
||||
#include <desc_image_load.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Following descriptor provides BL image/ep information that gets used
|
||||
* by BL2 to load the images and also subset of this information is
|
||||
* passed to next BL image. The image loading sequence is managed by
|
||||
* populating the images in required loading order. The image execution
|
||||
* sequence is managed by populating the `next_handoff_image_id` with
|
||||
* the next executable image id.
|
||||
******************************************************************************/
|
||||
static bl_mem_params_node_t bl2_mem_params_descs[] = {
|
||||
|
||||
/* Fill BL31 related information */
|
||||
{
|
||||
.image_id = BL31_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | EXECUTABLE | EP_FIRST_EXE),
|
||||
.ep_info.pc = BL31_BASE,
|
||||
.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS),
|
||||
#if DEBUG
|
||||
.ep_info.args.arg1 = RPI3_BL31_PLAT_PARAM_VAL,
|
||||
#endif
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t,
|
||||
IMAGE_ATTRIB_PLAT_SETUP),
|
||||
.image_info.image_base = BL31_BASE,
|
||||
.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
|
||||
|
||||
# ifdef BL32_BASE
|
||||
.next_handoff_image_id = BL32_IMAGE_ID,
|
||||
# else
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
# endif
|
||||
},
|
||||
|
||||
# ifdef BL32_BASE
|
||||
/* Fill BL32 related information */
|
||||
{
|
||||
.image_id = BL32_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | EXECUTABLE),
|
||||
.ep_info.pc = BL32_BASE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = BL32_BASE,
|
||||
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
|
||||
|
||||
.next_handoff_image_id = BL33_IMAGE_ID,
|
||||
},
|
||||
|
||||
/*
|
||||
* Fill BL32 external 1 related information.
|
||||
* A typical use for extra1 image is with OP-TEE where it is the pager
|
||||
* image.
|
||||
*/
|
||||
{
|
||||
.image_id = BL32_EXTRA1_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | NON_EXECUTABLE),
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t,
|
||||
IMAGE_ATTRIB_SKIP_LOADING),
|
||||
.image_info.image_base = BL32_BASE,
|
||||
.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
|
||||
/*
|
||||
* Fill BL32 external 2 related information.
|
||||
* A typical use for extra2 image is with OP-TEE where it is the paged
|
||||
* image.
|
||||
*/
|
||||
{
|
||||
.image_id = BL32_EXTRA2_IMAGE_ID,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
SECURE | NON_EXECUTABLE),
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t,
|
||||
IMAGE_ATTRIB_SKIP_LOADING),
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
},
|
||||
# endif /* BL32_BASE */
|
||||
|
||||
/* Fill BL33 related information */
|
||||
{
|
||||
.image_id = BL33_IMAGE_ID,
|
||||
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
|
||||
VERSION_2, entry_point_info_t,
|
||||
NON_SECURE | EXECUTABLE),
|
||||
# ifdef PRELOADED_BL33_BASE
|
||||
.ep_info.pc = PRELOADED_BL33_BASE,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t,
|
||||
IMAGE_ATTRIB_SKIP_LOADING),
|
||||
# else
|
||||
.ep_info.pc = PLAT_RPI3_NS_IMAGE_OFFSET,
|
||||
|
||||
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
|
||||
VERSION_2, image_info_t, 0),
|
||||
.image_info.image_base = PLAT_RPI3_NS_IMAGE_OFFSET,
|
||||
.image_info.image_max_size = PLAT_RPI3_NS_IMAGE_MAX_SIZE,
|
||||
# endif /* PRELOADED_BL33_BASE */
|
||||
|
||||
.next_handoff_image_id = INVALID_IMAGE_ID,
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef __PLAT_MACROS_S__
|
||||
#define __PLAT_MACROS_S__
|
||||
|
||||
#include <arm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below required platform porting macro
|
||||
* prints out relevant platform registers
|
||||
* whenever an unhandled exception is taken in
|
||||
* BL31.
|
||||
* Clobbers: x0 - x10, x16, x17, sp
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
.endm
|
||||
|
||||
#endif /* __PLAT_MACROS_S__ */
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __PLATFORM_DEF_H__
|
||||
#define __PLATFORM_DEF_H__
|
||||
|
||||
#include <arch.h>
|
||||
#include <common_def.h>
|
||||
#include <tbbr_img_def.h>
|
||||
#include <utils_def.h>
|
||||
|
||||
#include "../rpi3_hw.h"
|
||||
|
||||
/* Special value used to verify platform parameters from BL2 to BL31 */
|
||||
#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
|
||||
|
||||
#define PLATFORM_STACK_SIZE ULL(0x1000)
|
||||
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
|
||||
|
||||
#define RPI3_PRIMARY_CPU U(0)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(2)
|
||||
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define PLAT_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define PLAT_LOCAL_STATE_RET U(1)
|
||||
/*
|
||||
* Local power state for OFF/power-down. Valid for CPU and cluster power
|
||||
* domains.
|
||||
*/
|
||||
#define PLAT_LOCAL_STATE_OFF U(2)
|
||||
|
||||
/*
|
||||
* Macros used to parse state information from State-ID if it is using the
|
||||
* recommended encoding for State-ID.
|
||||
*/
|
||||
#define PLAT_LOCAL_PSTATE_WIDTH U(4)
|
||||
#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
|
||||
|
||||
/*
|
||||
* Some data must be aligned on the biggest cache line size in the platform.
|
||||
* This is known only to the platform as it might have a combination of
|
||||
* integrated and external caches.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_SHIFT U(6)
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/*
|
||||
* Partition memory into secure ROM, non-secure DRAM, secure "SRAM", and
|
||||
* secure DRAM. Note that this is all actually DRAM with different names,
|
||||
* there is no Secure RAM in the Raspberry Pi 3.
|
||||
*/
|
||||
#define SEC_ROM_BASE ULL(0x00000000)
|
||||
#define SEC_ROM_SIZE ULL(0x00010000)
|
||||
|
||||
/* FIP placed after ROM to append it to BL1 with very little padding. */
|
||||
#define PLAT_RPI3_FIP_BASE ULL(0x00010000)
|
||||
#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001F0000)
|
||||
|
||||
/* We have 16M of memory reserved at at 256M */
|
||||
#define SEC_SRAM_BASE ULL(0x10000000)
|
||||
#define SEC_SRAM_SIZE ULL(0x00100000)
|
||||
|
||||
#define SEC_DRAM0_BASE ULL(0x10100000)
|
||||
#define SEC_DRAM0_SIZE ULL(0x00200000)
|
||||
|
||||
#define NS_DRAM0_BASE ULL(0x10300000)
|
||||
#define NS_DRAM0_SIZE ULL(0x00D00000)
|
||||
/* End of reserved memory */
|
||||
|
||||
/*
|
||||
* BL33 entrypoint.
|
||||
*/
|
||||
#define PLAT_RPI3_NS_IMAGE_OFFSET NS_DRAM0_BASE
|
||||
#define PLAT_RPI3_NS_IMAGE_MAX_SIZE NS_DRAM0_SIZE
|
||||
|
||||
/*
|
||||
* I/O registers.
|
||||
*/
|
||||
#define DEVICE0_BASE RPI3_IO_BASE
|
||||
#define DEVICE0_SIZE RPI3_IO_SIZE
|
||||
|
||||
/*
|
||||
* Arm TF lives in SRAM, partition it here
|
||||
*/
|
||||
#define SHARED_RAM_BASE SEC_SRAM_BASE
|
||||
#define SHARED_RAM_SIZE ULL(0x00001000)
|
||||
|
||||
#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE)
|
||||
#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE)
|
||||
|
||||
/*
|
||||
* Mailbox to control the secondary cores.All secondary cores are held in a wait
|
||||
* loop in cold boot. To release them perform the following steps (plus any
|
||||
* additional barriers that may be needed):
|
||||
*
|
||||
* uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT;
|
||||
* *entrypoint = ADDRESS_TO_JUMP_TO;
|
||||
*
|
||||
* uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
|
||||
* mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO;
|
||||
*
|
||||
* sev();
|
||||
*/
|
||||
#define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE
|
||||
|
||||
#define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE
|
||||
#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8)
|
||||
|
||||
#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \
|
||||
PLAT_RPI3_TM_ENTRYPOINT_SIZE)
|
||||
#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8)
|
||||
#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \
|
||||
PLAT_RPI3_TM_HOLD_SIZE)
|
||||
|
||||
#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0)
|
||||
#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1)
|
||||
|
||||
/*
|
||||
* BL1 specific defines.
|
||||
*
|
||||
* BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
|
||||
* addresses.
|
||||
*
|
||||
* Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using
|
||||
* the current BL1 RW debug size plus a little space for growth.
|
||||
*/
|
||||
#define PLAT_MAX_BL1_RW_SIZE ULL(0x12000)
|
||||
|
||||
#define BL1_RO_BASE SEC_ROM_BASE
|
||||
#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE)
|
||||
#define BL1_RW_BASE (BL1_RW_LIMIT - PLAT_MAX_BL1_RW_SIZE)
|
||||
#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
|
||||
|
||||
/*
|
||||
* BL2 specific defines.
|
||||
*
|
||||
* Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug
|
||||
* size plus a little space for growth.
|
||||
*/
|
||||
#define PLAT_MAX_BL2_SIZE ULL(0x2C000)
|
||||
|
||||
#define BL2_BASE (BL2_LIMIT - PLAT_MAX_BL2_SIZE)
|
||||
#define BL2_LIMIT BL31_BASE
|
||||
|
||||
/*
|
||||
* BL31 specific defines.
|
||||
*
|
||||
* Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
|
||||
* current BL31 debug size plus a little space for growth.
|
||||
*/
|
||||
#define PLAT_MAX_BL31_SIZE ULL(0x20000)
|
||||
|
||||
#define BL31_BASE (BL31_LIMIT - PLAT_MAX_BL31_SIZE)
|
||||
#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE)
|
||||
#define BL31_PROGBITS_LIMIT BL1_RW_BASE
|
||||
|
||||
/*
|
||||
* BL32 specific defines.
|
||||
*
|
||||
* BL32 can execute from Secure SRAM or Secure DRAM.
|
||||
*/
|
||||
#define BL32_SRAM_BASE BL_RAM_BASE
|
||||
#define BL32_SRAM_LIMIT BL31_BASE
|
||||
#define BL32_DRAM_BASE SEC_DRAM0_BASE
|
||||
#define BL32_DRAM_LIMIT (SEC_DRAM0_BASE + SEC_DRAM0_SIZE)
|
||||
|
||||
#define SEC_SRAM_ID 0
|
||||
#define SEC_DRAM_ID 1
|
||||
|
||||
#if RPI3_BL32_RAM_LOCATION_ID == SEC_SRAM_ID
|
||||
# define BL32_MEM_BASE BL_RAM_BASE
|
||||
# define BL32_MEM_SIZE BL_RAM_SIZE
|
||||
# define BL32_BASE BL32_SRAM_BASE
|
||||
# define BL32_LIMIT BL32_SRAM_LIMIT
|
||||
#elif RPI3_BL32_RAM_LOCATION_ID == SEC_DRAM_ID
|
||||
# define BL32_MEM_BASE SEC_DRAM0_BASE
|
||||
# define BL32_MEM_SIZE SEC_DRAM0_SIZE
|
||||
# define BL32_BASE BL32_DRAM_BASE
|
||||
# define BL32_LIMIT BL32_DRAM_LIMIT
|
||||
#else
|
||||
# error "Unsupported RPI3_BL32_RAM_LOCATION_ID value"
|
||||
#endif
|
||||
#define BL32_SIZE (BL32_LIMIT - BL32_BASE)
|
||||
|
||||
#ifdef SPD_none
|
||||
#undef BL32_BASE
|
||||
#endif /* SPD_none */
|
||||
|
||||
/*
|
||||
* Other memory-related defines.
|
||||
*/
|
||||
#define ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
|
||||
#define MAX_MMAP_REGIONS U(8)
|
||||
#define MAX_XLAT_TABLES U(4)
|
||||
|
||||
#define MAX_IO_DEVICES U(3)
|
||||
#define MAX_IO_HANDLES U(4)
|
||||
|
||||
/*
|
||||
* Serial-related constants.
|
||||
*/
|
||||
#define PLAT_RPI3_UART_BASE RPI3_MINI_UART_BASE
|
||||
#define PLAT_RPI3_UART_CLK_IN_HZ RPI3_MINI_UART_CLK_IN_HZ
|
||||
#define PLAT_RPI3_UART_BAUDRATE ULL(115200)
|
||||
|
||||
/*
|
||||
* System counter
|
||||
*/
|
||||
#define SYS_COUNTER_FREQ_IN_TICKS ULL(19200000)
|
||||
|
||||
#endif /* __PLATFORM_DEF_H__ */
|
|
@ -0,0 +1,113 @@
|
|||
#
|
||||
# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/common/tbbr \
|
||||
-Iinclude/plat/arm/common/ \
|
||||
-Iinclude/plat/arm/common/aarch64/ \
|
||||
-Iplat/rpi3/include
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := drivers/console/aarch64/console.S \
|
||||
drivers/ti/uart/aarch64/16550_console.S \
|
||||
plat/rpi3/rpi3_common.c
|
||||
|
||||
BL1_SOURCES += drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_storage.c \
|
||||
lib/cpus/aarch64/cortex_a53.S \
|
||||
plat/common/aarch64/platform_mp_stack.S \
|
||||
plat/rpi3/aarch64/plat_helpers.S \
|
||||
plat/rpi3/rpi3_bl1_setup.c \
|
||||
plat/rpi3/rpi3_io_storage.c
|
||||
|
||||
BL2_SOURCES += common/desc_image_load.c \
|
||||
drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_storage.c \
|
||||
plat/common/aarch64/platform_mp_stack.S \
|
||||
plat/rpi3/aarch64/plat_helpers.S \
|
||||
plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \
|
||||
plat/rpi3/rpi3_bl2_setup.c \
|
||||
plat/rpi3/rpi3_image_load.c \
|
||||
plat/rpi3/rpi3_io_storage.c
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
|
||||
plat/common/aarch64/plat_psci_common.c \
|
||||
plat/rpi3/aarch64/plat_helpers.S \
|
||||
plat/rpi3/rpi3_bl31_setup.c \
|
||||
plat/rpi3/rpi3_pm.c \
|
||||
plat/rpi3/rpi3_topology.c
|
||||
|
||||
# Translation tables library
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
|
||||
|
||||
# Tune compiler for Cortex-A53
|
||||
ifeq ($(notdir $(CC)),armclang)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else ifneq ($(findstring clang,$(notdir $(CC))),)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else
|
||||
TF_CFLAGS_aarch64 += -mtune=cortex-a53
|
||||
endif
|
||||
|
||||
# Build config flags
|
||||
# ------------------
|
||||
|
||||
# Enable all errata workarounds for Cortex-A53
|
||||
ERRATA_A53_826319 := 1
|
||||
ERRATA_A53_835769 := 1
|
||||
ERRATA_A53_836870 := 1
|
||||
ERRATA_A53_843419 := 1
|
||||
ERRATA_A53_855873 := 1
|
||||
|
||||
# Disable the PSCI platform compatibility layer by default
|
||||
ENABLE_PLAT_COMPAT := 0
|
||||
|
||||
# Enable reset to BL31 by default
|
||||
RESET_TO_BL31 := 1
|
||||
|
||||
# Have different sections for code and rodata
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# Use Coherent memory
|
||||
USE_COHERENT_MEM := 1
|
||||
|
||||
# Enable new version of image loading
|
||||
LOAD_IMAGE_V2 := 1
|
||||
|
||||
# Platform build flags
|
||||
# --------------------
|
||||
|
||||
# BL33 images are in AArch64 by default
|
||||
RPI3_BL33_IN_AARCH32 := 0
|
||||
|
||||
# BL32 location
|
||||
RPI3_BL32_RAM_LOCATION := tdram
|
||||
ifeq (${RPI3_BL32_RAM_LOCATION}, tsram)
|
||||
RPI3_BL32_RAM_LOCATION_ID = SEC_SRAM_ID
|
||||
else ifeq (${RPI3_BL32_RAM_LOCATION}, tdram)
|
||||
RPI3_BL32_RAM_LOCATION_ID = SEC_DRAM_ID
|
||||
else
|
||||
$(error "Unsupported RPI3_BL32_RAM_LOCATION value")
|
||||
endif
|
||||
|
||||
# Process platform flags
|
||||
# ----------------------
|
||||
|
||||
$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID))
|
||||
$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
|
||||
|
||||
# Verify build config
|
||||
# -------------------
|
||||
|
||||
ifneq (${LOAD_IMAGE_V2}, 1)
|
||||
$(error Error: rpi3 needs LOAD_IMAGE_V2=1)
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error Error: AArch32 not supported on rpi3)
|
||||
endif
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <platform_def.h>
|
||||
#include <xlat_mmu_helpers.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
#include "../../bl1/bl1_private.h"
|
||||
#include "rpi3_private.h"
|
||||
|
||||
/* Data structure which holds the extents of the trusted SRAM for BL1 */
|
||||
static meminfo_t bl1_tzram_layout;
|
||||
|
||||
meminfo_t *bl1_plat_sec_mem_layout(void)
|
||||
{
|
||||
return &bl1_tzram_layout;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL1 specific platform actions.
|
||||
******************************************************************************/
|
||||
void bl1_early_platform_setup(void)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
|
||||
PLAT_RPI3_UART_BAUDRATE);
|
||||
|
||||
/* Allow BL1 to see the whole Trusted RAM */
|
||||
bl1_tzram_layout.total_base = BL_RAM_BASE;
|
||||
bl1_tzram_layout.total_size = BL_RAM_SIZE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Perform the very early platform specific architecture setup. This only
|
||||
* does basic initialization. Later architectural setup (bl1_arch_setup())
|
||||
* does not do anything platform specific.
|
||||
*****************************************************************************/
|
||||
void bl1_plat_arch_setup(void)
|
||||
{
|
||||
rpi3_setup_page_tables(bl1_tzram_layout.total_base,
|
||||
bl1_tzram_layout.total_size,
|
||||
BL_CODE_BASE, BL1_CODE_END,
|
||||
BL1_RO_DATA_BASE, BL1_RO_DATA_END
|
||||
#if USE_COHERENT_MEM
|
||||
, BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
|
||||
#endif
|
||||
);
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
void bl1_platform_setup(void)
|
||||
{
|
||||
/* Initialise the IO layer and register platform IO devices */
|
||||
plat_rpi3_io_setup();
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <desc_image_load.h>
|
||||
#include <platform_def.h>
|
||||
#include <xlat_mmu_helpers.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
#include "rpi3_private.h"
|
||||
|
||||
/* Data structure which holds the extents of the trusted SRAM for BL2 */
|
||||
static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
|
||||
|
||||
/*******************************************************************************
|
||||
* BL1 has passed the extents of the trusted SRAM that should be visible to BL2
|
||||
* in x0. This memory layout is sitting at the base of the free trusted SRAM.
|
||||
* Copy it to a safe location before its reclaimed by later BL2 functionality.
|
||||
******************************************************************************/
|
||||
void bl2_early_platform_setup(meminfo_t *mem_layout)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
|
||||
PLAT_RPI3_UART_BAUDRATE);
|
||||
|
||||
/* Setup the BL2 memory layout */
|
||||
bl2_tzram_layout = *mem_layout;
|
||||
|
||||
plat_rpi3_io_setup();
|
||||
}
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
/*
|
||||
* This is where a TrustZone address space controller and other
|
||||
* security related peripherals, would be configured.
|
||||
*/
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform the very early platform specific architectural setup here.
|
||||
******************************************************************************/
|
||||
void bl2_plat_arch_setup(void)
|
||||
{
|
||||
rpi3_setup_page_tables(bl2_tzram_layout.total_base,
|
||||
bl2_tzram_layout.total_size,
|
||||
BL_CODE_BASE, BL_CODE_END,
|
||||
BL_RO_DATA_BASE, BL_RO_DATA_END
|
||||
#if USE_COHERENT_MEM
|
||||
, BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
|
||||
#endif
|
||||
);
|
||||
|
||||
enable_mmu_el1(0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function can be used by the platforms to update/use image
|
||||
* information for given `image_id`.
|
||||
******************************************************************************/
|
||||
int bl2_plat_handle_post_image_load(unsigned int image_id)
|
||||
{
|
||||
int err = 0;
|
||||
bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
|
||||
|
||||
assert(bl_mem_params != NULL);
|
||||
|
||||
switch (image_id) {
|
||||
case BL32_IMAGE_ID:
|
||||
bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
|
||||
break;
|
||||
|
||||
case BL33_IMAGE_ID:
|
||||
/* BL33 expects to receive the primary CPU MPID (through r0) */
|
||||
bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
|
||||
bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <xlat_mmu_helpers.h>
|
||||
#include <xlat_tables_defs.h>
|
||||
|
||||
#include "rpi3_private.h"
|
||||
|
||||
#define BL31_END (uintptr_t)(&__BL31_END__)
|
||||
|
||||
/*
|
||||
* Placeholder variables for copying the arguments that have been passed to
|
||||
* BL31 from BL2.
|
||||
*/
|
||||
static entry_point_info_t bl32_image_ep_info;
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
|
||||
/*******************************************************************************
|
||||
* Return a pointer to the 'entry_point_info' structure of the next image for
|
||||
* the security state specified. BL33 corresponds to the non-secure image type
|
||||
* while BL32 corresponds to the secure image type. A NULL pointer is returned
|
||||
* if the image does not exist.
|
||||
******************************************************************************/
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
entry_point_info_t *next_image_info;
|
||||
|
||||
assert(sec_state_is_valid(type) != 0);
|
||||
|
||||
next_image_info = (type == NON_SECURE)
|
||||
? &bl33_image_ep_info : &bl32_image_ep_info;
|
||||
|
||||
/* None of the images can have 0x0 as the entrypoint. */
|
||||
if (next_image_info->pc) {
|
||||
return next_image_info;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 early platform setup. Here is an opportunity to copy
|
||||
* parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
|
||||
* they are lost (potentially). This needs to be done before the MMU is
|
||||
* initialized so that the memory layout can be used while creating page
|
||||
* tables. BL2 has flushed this information to memory, so we are guaranteed
|
||||
* to pick up good data.
|
||||
******************************************************************************/
|
||||
void bl31_early_platform_setup(void *from_bl2,
|
||||
void *plat_params_from_bl2)
|
||||
{
|
||||
/* Initialize the console to provide early debug support */
|
||||
console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
|
||||
PLAT_RPI3_UART_BAUDRATE);
|
||||
|
||||
#if RESET_TO_BL31
|
||||
|
||||
/* There are no parameters from BL2 if BL31 is a reset vector */
|
||||
assert(from_bl2 == NULL);
|
||||
assert(plat_params_from_bl2 == NULL);
|
||||
|
||||
#ifdef BL32_BASE
|
||||
/* Populate entry point information for BL32 */
|
||||
SET_PARAM_HEAD(&bl32_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
|
||||
bl32_image_ep_info.pc = BL32_BASE;
|
||||
bl32_image_ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
|
||||
#endif /* BL32_BASE */
|
||||
|
||||
/* Populate entry point information for BL33 */
|
||||
SET_PARAM_HEAD(&bl33_image_ep_info,
|
||||
PARAM_EP,
|
||||
VERSION_1,
|
||||
0);
|
||||
/*
|
||||
* Tell BL31 where the non-trusted software image
|
||||
* is located and the entry state information
|
||||
*/
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
|
||||
bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
|
||||
#else /* RESET_TO_BL31 */
|
||||
|
||||
/*
|
||||
* In debug builds, we pass a special value in 'plat_params_from_bl2'
|
||||
* to verify platform parameters from BL2 to BL31.
|
||||
* In release builds, it's not used.
|
||||
*/
|
||||
assert(((uintptr_t)plat_params_from_bl2) == RPI3_BL31_PLAT_PARAM_VAL);
|
||||
|
||||
/*
|
||||
* Check params passed from BL2 should not be NULL,
|
||||
*/
|
||||
bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
|
||||
|
||||
assert(params_from_bl2 != NULL);
|
||||
assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
|
||||
assert(params_from_bl2->h.version >= VERSION_2);
|
||||
|
||||
bl_params_node_t *bl_params = params_from_bl2->head;
|
||||
|
||||
/*
|
||||
* Copy BL33 and BL32 (if present), entry point information.
|
||||
* They are stored in Secure RAM, in BL2's address space.
|
||||
*/
|
||||
while (bl_params) {
|
||||
if (bl_params->image_id == BL32_IMAGE_ID) {
|
||||
bl32_image_ep_info = *bl_params->ep_info;
|
||||
}
|
||||
|
||||
if (bl_params->image_id == BL33_IMAGE_ID) {
|
||||
bl33_image_ep_info = *bl_params->ep_info;
|
||||
}
|
||||
|
||||
bl_params = bl_params->next_params_info;
|
||||
}
|
||||
|
||||
if (bl33_image_ep_info.pc == 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
#endif /* RESET_TO_BL31 */
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE,
|
||||
BL_CODE_BASE, BL_CODE_END,
|
||||
BL_RO_DATA_BASE, BL_RO_DATA_END
|
||||
#if USE_COHERENT_MEM
|
||||
, BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END
|
||||
#endif
|
||||
);
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
#if RESET_TO_BL31
|
||||
/*
|
||||
* Do initial security configuration to allow DRAM/device access
|
||||
* (if earlier BL has not already done so).
|
||||
*/
|
||||
#endif /* RESET_TO_BL31 */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
/* Initialize the runtime console */
|
||||
console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ,
|
||||
PLAT_RPI3_UART_BAUDRATE);
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <interrupt_mgmt.h>
|
||||
#include <platform_def.h>
|
||||
#include <xlat_tables_v2.h>
|
||||
|
||||
#include "rpi3_hw.h"
|
||||
#include "rpi3_private.h"
|
||||
|
||||
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
|
||||
DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \
|
||||
SHARED_RAM_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_FIP MAP_REGION_FLAT(PLAT_RPI3_FIP_BASE, \
|
||||
PLAT_RPI3_FIP_MAX_SIZE, \
|
||||
MT_MEMORY | MT_RO | MT_NS)
|
||||
|
||||
#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
/*
|
||||
* Table of regions for various BL stages to map using the MMU.
|
||||
*/
|
||||
#ifdef IMAGE_BL1
|
||||
static const mmap_region_t plat_rpi3_mmap[] = {
|
||||
MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
MAP_FIP,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef IMAGE_BL2
|
||||
static const mmap_region_t plat_rpi3_mmap[] = {
|
||||
MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
MAP_FIP,
|
||||
MAP_NS_DRAM0,
|
||||
#ifdef BL32_BASE
|
||||
MAP_BL32_MEM,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef IMAGE_BL31
|
||||
static const mmap_region_t plat_rpi3_mmap[] = {
|
||||
MAP_SHARED_RAM,
|
||||
MAP_DEVICE0,
|
||||
#ifdef BL32_BASE
|
||||
MAP_BL32_MEM,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that sets up the translation tables.
|
||||
******************************************************************************/
|
||||
void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
|
||||
uintptr_t code_start, uintptr_t code_limit,
|
||||
uintptr_t rodata_start, uintptr_t rodata_limit
|
||||
#if USE_COHERENT_MEM
|
||||
, uintptr_t coh_start, uintptr_t coh_limit
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/*
|
||||
* Map the Trusted SRAM with appropriate memory attributes.
|
||||
* Subsequent mappings will adjust the attributes for specific regions.
|
||||
*/
|
||||
VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n",
|
||||
(void *) total_base, (void *) (total_base + total_size));
|
||||
mmap_add_region(total_base, total_base,
|
||||
total_size,
|
||||
MT_MEMORY | MT_RW | MT_SECURE);
|
||||
|
||||
/* Re-map the code section */
|
||||
VERBOSE("Code region: %p - %p\n",
|
||||
(void *) code_start, (void *) code_limit);
|
||||
mmap_add_region(code_start, code_start,
|
||||
code_limit - code_start,
|
||||
MT_CODE | MT_SECURE);
|
||||
|
||||
/* Re-map the read-only data section */
|
||||
VERBOSE("Read-only data region: %p - %p\n",
|
||||
(void *) rodata_start, (void *) rodata_limit);
|
||||
mmap_add_region(rodata_start, rodata_start,
|
||||
rodata_limit - rodata_start,
|
||||
MT_RO_DATA | MT_SECURE);
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
/* Re-map the coherent memory region */
|
||||
VERBOSE("Coherent region: %p - %p\n",
|
||||
(void *) coh_start, (void *) coh_limit);
|
||||
mmap_add_region(coh_start, coh_start,
|
||||
coh_limit - coh_start,
|
||||
MT_DEVICE | MT_RW | MT_SECURE);
|
||||
#endif
|
||||
|
||||
mmap_add(plat_rpi3_mmap);
|
||||
|
||||
init_xlat_tables();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Return entrypoint of BL33.
|
||||
******************************************************************************/
|
||||
uintptr_t plat_get_ns_image_entrypoint(void)
|
||||
{
|
||||
#ifdef PRELOADED_BL33_BASE
|
||||
return PRELOADED_BL33_BASE;
|
||||
#else
|
||||
return PLAT_RPI3_NS_IMAGE_OFFSET;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Gets SPSR for BL32 entry
|
||||
******************************************************************************/
|
||||
uint32_t rpi3_get_spsr_for_bl32_entry(void)
|
||||
{
|
||||
/*
|
||||
* The Secure Payload Dispatcher service is responsible for
|
||||
* setting the SPSR prior to entry into the BL32 image.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Gets SPSR for BL33 entry
|
||||
******************************************************************************/
|
||||
uint32_t rpi3_get_spsr_for_bl33_entry(void)
|
||||
{
|
||||
#if RPI3_BL33_IN_AARCH32
|
||||
INFO("BL33 will boot in Non-secure AArch32 Hypervisor mode\n");
|
||||
return SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
#else
|
||||
return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
return SYS_COUNTER_FREQ_IN_TICKS;
|
||||
}
|
||||
|
||||
uint32_t plat_ic_get_pending_interrupt_type(void)
|
||||
{
|
||||
return INTR_TYPE_INVAL;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __RPI3_HW__
|
||||
#define __RPI3_HW__
|
||||
|
||||
#include <utils_def.h>
|
||||
|
||||
/*
|
||||
* Peripherals
|
||||
*/
|
||||
|
||||
#define RPI3_IO_BASE ULL(0x3F000000)
|
||||
#define RPI3_IO_SIZE ULL(0x01000000)
|
||||
|
||||
/*
|
||||
* Serial port (called 'Mini UART' in the BCM docucmentation).
|
||||
*/
|
||||
#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
|
||||
#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
|
||||
#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000)
|
||||
|
||||
/*
|
||||
* Power management, reset controller, watchdog.
|
||||
*/
|
||||
#define RPI3_IO_PM_OFFSET ULL(0x00100000)
|
||||
#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET)
|
||||
/* Registers on top of RPI3_PM_BASE. */
|
||||
#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
|
||||
#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
|
||||
/* Watchdog constants */
|
||||
#define RPI3_PM_PASSWORD ULL(0x5A000000)
|
||||
#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030)
|
||||
#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020)
|
||||
|
||||
/*
|
||||
* Local interrupt controller
|
||||
*/
|
||||
#define RPI3_INTC_BASE_ADDRESS ULL(0x40000000)
|
||||
/* Registers on top of RPI3_INTC_BASE_ADDRESS */
|
||||
#define RPI3_INTC_CONTROL_OFFSET ULL(0x00000000)
|
||||
#define RPI3_INTC_PRESCALER_OFFSET ULL(0x00000008)
|
||||
#define RPI3_INTC_MBOX_CONTROL_OFFSET ULL(0x00000050)
|
||||
#define RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ ULL(0x00000080)
|
||||
#define RPI3_INTC_PENDING_FIQ_OFFSET ULL(0x00000070)
|
||||
#define RPI3_INTC_PENDING_FIQ_MBOX3 ULL(0x00000080)
|
||||
|
||||
#endif /* __RPI3_HW__ */
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <bl_common.h>
|
||||
#include <desc_image_load.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* This function flushes the data structures so that they are visible
|
||||
* in memory for the next BL image.
|
||||
******************************************************************************/
|
||||
void plat_flush_next_bl_params(void)
|
||||
{
|
||||
flush_bl_params_desc();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the list of loadable images.
|
||||
******************************************************************************/
|
||||
bl_load_info_t *plat_get_bl_image_load_info(void)
|
||||
{
|
||||
return get_bl_load_info_from_mem_params_desc();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the list of executable images.
|
||||
******************************************************************************/
|
||||
bl_params_t *plat_get_next_bl_params(void)
|
||||
{
|
||||
return get_next_bl_params_from_mem_params_desc();
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <debug.h>
|
||||
#include <firmware_image_package.h>
|
||||
#include <io_driver.h>
|
||||
#include <io_fip.h>
|
||||
#include <io_memmap.h>
|
||||
#include <platform_def.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Semihosting filenames */
|
||||
#define BL2_IMAGE_NAME "bl2.bin"
|
||||
#define BL31_IMAGE_NAME "bl31.bin"
|
||||
#define BL32_IMAGE_NAME "bl32.bin"
|
||||
#define BL33_IMAGE_NAME "bl33.bin"
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
#define BL2_CERT_NAME "bl2.crt"
|
||||
#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
|
||||
#define BL31_KEY_CERT_NAME "bl31_key.crt"
|
||||
#define BL32_KEY_CERT_NAME "bl32_key.crt"
|
||||
#define BL33_KEY_CERT_NAME "bl33_key.crt"
|
||||
#define BL31_CERT_NAME "bl31.crt"
|
||||
#define BL32_CERT_NAME "bl32.crt"
|
||||
#define BL33_CERT_NAME "bl33.crt"
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
/* IO devices */
|
||||
static const io_dev_connector_t *fip_dev_con;
|
||||
static uintptr_t fip_dev_handle;
|
||||
static const io_dev_connector_t *memmap_dev_con;
|
||||
static uintptr_t memmap_dev_handle;
|
||||
|
||||
static const io_block_spec_t fip_block_spec = {
|
||||
.offset = PLAT_RPI3_FIP_BASE,
|
||||
.length = PLAT_RPI3_FIP_MAX_SIZE
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl2_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl31_uuid_spec = {
|
||||
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl32_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl33_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
|
||||
};
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
static const io_uuid_spec_t bl2_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
|
||||
.uuid = UUID_TRUSTED_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl31_key_cert_uuid_spec = {
|
||||
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl32_key_cert_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl33_key_cert_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl31_cert_uuid_spec = {
|
||||
.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl32_cert_uuid_spec = {
|
||||
.uuid = UUID_SECURE_PAYLOAD_BL32_CERT,
|
||||
};
|
||||
|
||||
static const io_uuid_spec_t bl33_cert_uuid_spec = {
|
||||
.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
|
||||
};
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
static int open_fip(const uintptr_t spec);
|
||||
static int open_memmap(const uintptr_t spec);
|
||||
|
||||
struct plat_io_policy {
|
||||
uintptr_t *dev_handle;
|
||||
uintptr_t image_spec;
|
||||
int (*check)(const uintptr_t spec);
|
||||
};
|
||||
|
||||
/* By default, load images from the FIP */
|
||||
static const struct plat_io_policy policies[] = {
|
||||
[FIP_IMAGE_ID] = {
|
||||
&memmap_dev_handle,
|
||||
(uintptr_t)&fip_block_spec,
|
||||
open_memmap
|
||||
},
|
||||
[BL2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl2_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL31_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl31_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL33_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl33_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
[BL2_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl2_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&trusted_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL31_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl31_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL33_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl33_key_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL31_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl31_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL32_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl32_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
[BL33_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&bl33_cert_uuid_spec,
|
||||
open_fip
|
||||
},
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
};
|
||||
|
||||
static int open_fip(const uintptr_t spec)
|
||||
{
|
||||
int result;
|
||||
uintptr_t local_image_handle;
|
||||
|
||||
/* See if a Firmware Image Package is available */
|
||||
result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
|
||||
if (result == 0) {
|
||||
result = io_open(fip_dev_handle, spec, &local_image_handle);
|
||||
if (result == 0) {
|
||||
VERBOSE("Using FIP\n");
|
||||
io_close(local_image_handle);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int open_memmap(const uintptr_t spec)
|
||||
{
|
||||
int result;
|
||||
uintptr_t local_image_handle;
|
||||
|
||||
result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
|
||||
if (result == 0) {
|
||||
result = io_open(memmap_dev_handle, spec, &local_image_handle);
|
||||
if (result == 0) {
|
||||
VERBOSE("Using Memmap\n");
|
||||
io_close(local_image_handle);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void plat_rpi3_io_setup(void)
|
||||
{
|
||||
int io_result;
|
||||
|
||||
io_result = register_io_dev_fip(&fip_dev_con);
|
||||
assert(io_result == 0);
|
||||
|
||||
io_result = register_io_dev_memmap(&memmap_dev_con);
|
||||
assert(io_result == 0);
|
||||
|
||||
/* Open connections to devices and cache the handles */
|
||||
io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
|
||||
&fip_dev_handle);
|
||||
assert(io_result == 0);
|
||||
|
||||
io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
|
||||
&memmap_dev_handle);
|
||||
assert(io_result == 0);
|
||||
|
||||
/* Ignore improbable errors in release builds */
|
||||
(void)io_result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an IO device handle and specification which can be used to access
|
||||
* an image. Use this to enforce platform load policy
|
||||
*/
|
||||
int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
|
||||
uintptr_t *image_spec)
|
||||
{
|
||||
int result;
|
||||
const struct plat_io_policy *policy;
|
||||
|
||||
assert(image_id < ARRAY_SIZE(policies));
|
||||
|
||||
policy = &policies[image_id];
|
||||
result = policy->check(policy->image_spec);
|
||||
if (result == 0) {
|
||||
*image_spec = policy->image_spec;
|
||||
*dev_handle = *(policy->dev_handle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <platform.h>
|
||||
#include <psci.h>
|
||||
|
||||
#include "rpi3_hw.h"
|
||||
|
||||
/*
|
||||
* The secure entry point to be used on warm reset.
|
||||
*/
|
||||
static uintptr_t secure_entrypoint;
|
||||
|
||||
/* Make composite power state parameter till power level 0 */
|
||||
#if PSCI_EXTENDED_STATE_ID
|
||||
|
||||
#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
|
||||
(((lvl0_state) << PSTATE_ID_SHIFT) | \
|
||||
((type) << PSTATE_TYPE_SHIFT))
|
||||
|
||||
#else
|
||||
|
||||
#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
|
||||
(((lvl0_state) << PSTATE_ID_SHIFT) | \
|
||||
((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
|
||||
((type) << PSTATE_TYPE_SHIFT))
|
||||
|
||||
#endif /* PSCI_EXTENDED_STATE_ID */
|
||||
|
||||
#define rpi3_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
|
||||
(((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \
|
||||
rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
|
||||
|
||||
/*
|
||||
* The table storing the valid idle power states. Ensure that the
|
||||
* array entries are populated in ascending order of state-id to
|
||||
* enable us to use binary search during power state validation.
|
||||
* The table must be terminated by a NULL entry.
|
||||
*/
|
||||
static const unsigned int rpi3_pm_idle_states[] = {
|
||||
/* State-id - 0x01 */
|
||||
rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET,
|
||||
MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
|
||||
/* State-id - 0x02 */
|
||||
rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF,
|
||||
MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
|
||||
/* State-id - 0x22 */
|
||||
rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF,
|
||||
MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
|
||||
0,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called to check the validity of the power state
|
||||
* parameter. The power state parameter has to be a composite power state.
|
||||
******************************************************************************/
|
||||
static int rpi3_validate_power_state(unsigned int power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
unsigned int state_id;
|
||||
int i;
|
||||
|
||||
assert(req_state != 0);
|
||||
|
||||
/*
|
||||
* Currently we are using a linear search for finding the matching
|
||||
* entry in the idle power state array. This can be made a binary
|
||||
* search if the number of entries justify the additional complexity.
|
||||
*/
|
||||
for (i = 0; rpi3_pm_idle_states[i] != 0; i++) {
|
||||
if (power_state == rpi3_pm_idle_states[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return error if entry not found in the idle state array */
|
||||
if (!rpi3_pm_idle_states[i]) {
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
state_id = psci_get_pstate_id(power_state);
|
||||
|
||||
/* Parse the State ID and populate the state info parameter */
|
||||
while (state_id) {
|
||||
req_state->pwr_domain_state[i++] = state_id &
|
||||
PLAT_LOCAL_PSTATE_MASK;
|
||||
state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a CPU is about to enter standby.
|
||||
******************************************************************************/
|
||||
static void rpi3_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
assert(cpu_state == PLAT_LOCAL_STATE_RET);
|
||||
|
||||
/*
|
||||
* Enter standby state.
|
||||
* dsb is good practice before using wfi to enter low power states
|
||||
*/
|
||||
dsb();
|
||||
wfi();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a power domain is about to be turned on. The
|
||||
* mpidr determines the CPU to be turned on.
|
||||
******************************************************************************/
|
||||
static int rpi3_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
int rc = PSCI_E_SUCCESS;
|
||||
unsigned int pos = plat_core_pos_by_mpidr(mpidr);
|
||||
uint64_t *hold_base = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
|
||||
|
||||
assert(pos < PLATFORM_CORE_COUNT);
|
||||
|
||||
hold_base[pos] = PLAT_RPI3_TM_HOLD_STATE_GO;
|
||||
|
||||
/* Make sure that the write has completed */
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
sev();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a power domain has just been powered on after
|
||||
* being turned off earlier. The target_state encodes the low power state that
|
||||
* each level has woken up from.
|
||||
******************************************************************************/
|
||||
void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||
PLAT_LOCAL_STATE_OFF);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler to reboot the system
|
||||
******************************************************************************/
|
||||
#define RESET_TIMEOUT 10
|
||||
|
||||
static void __dead2 rpi3_system_reset(void)
|
||||
{
|
||||
/* Setup watchdog for reset */
|
||||
|
||||
static const uintptr_t base = RPI3_PM_BASE;
|
||||
uint32_t rstc;
|
||||
|
||||
INFO("rpi3: PSCI System Reset: invoking watchdog reset\n");
|
||||
|
||||
console_flush();
|
||||
|
||||
rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET);
|
||||
rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
|
||||
rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET;
|
||||
|
||||
dmbst();
|
||||
|
||||
/*
|
||||
* Watchdog timer = Timer clock / 16
|
||||
* Password (31:16) | Value (11:0)
|
||||
*/
|
||||
mmio_write_32(base + RPI3_PM_WDOG_OFFSET,
|
||||
RPI3_PM_PASSWORD | RESET_TIMEOUT);
|
||||
mmio_write_32(base + RPI3_PM_RSTC_OFFSET,
|
||||
RPI3_PM_PASSWORD | rstc);
|
||||
|
||||
for (;;) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handlers and setup function.
|
||||
******************************************************************************/
|
||||
static const plat_psci_ops_t plat_rpi3_psci_pm_ops = {
|
||||
.cpu_standby = rpi3_cpu_standby,
|
||||
.pwr_domain_on = rpi3_pwr_domain_on,
|
||||
.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
|
||||
.system_reset = rpi3_system_reset,
|
||||
.validate_power_state = rpi3_validate_power_state,
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
uintptr_t *mailbox = (void *)PLAT_RPI3_TRUSTED_MAILBOX_BASE;
|
||||
|
||||
*mailbox = sec_entrypoint;
|
||||
secure_entrypoint = (uintptr_t)sec_entrypoint;
|
||||
*psci_ops = &plat_rpi3_psci_pm_ops;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __RPI3_PRIVATE_H__
|
||||
#define __RPI3_PRIVATE_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Function and variable prototypes
|
||||
******************************************************************************/
|
||||
|
||||
/* Utility functions */
|
||||
void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
|
||||
uintptr_t code_start, uintptr_t code_limit,
|
||||
uintptr_t rodata_start, uintptr_t rodata_limit
|
||||
#if USE_COHERENT_MEM
|
||||
, uintptr_t coh_start, uintptr_t coh_limit
|
||||
#endif
|
||||
);
|
||||
|
||||
/* Optional functions required in the Raspberry Pi 3 port */
|
||||
unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
|
||||
|
||||
/* BL2 utility functions */
|
||||
uint32_t rpi3_get_spsr_for_bl32_entry(void);
|
||||
uint32_t rpi3_get_spsr_for_bl33_entry(void);
|
||||
|
||||
/* IO storage utility functions */
|
||||
void plat_rpi3_io_setup(void);
|
||||
|
||||
#endif /*__RPI3_PRIVATE_H__ */
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <platform_def.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "rpi3_private.h"
|
||||
|
||||
/* The power domain tree descriptor */
|
||||
static unsigned char power_domain_tree_desc[] = {
|
||||
/* Number of root nodes */
|
||||
PLATFORM_CLUSTER_COUNT,
|
||||
/* Number of children for the first node */
|
||||
PLATFORM_CLUSTER0_CORE_COUNT,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the ARM default topology tree information.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
return power_domain_tree_desc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function implements a part of the critical interface between the psci
|
||||
* generic layer and the platform that allows the former to query the platform
|
||||
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
|
||||
* in case the MPIDR is invalid.
|
||||
******************************************************************************/
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster_id, cpu_id;
|
||||
|
||||
mpidr &= MPIDR_AFFINITY_MASK;
|
||||
if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
|
||||
if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return plat_rpi3_calc_core_pos(mpidr);
|
||||
}
|
Loading…
Reference in New Issue