Merge pull request #1174 from antonio-nino-diaz-arm/an/page-size
authordavidcunado-arm <david.cunado@arm.com>
Fri, 8 Dec 2017 16:29:19 +0000 (16:29 +0000)
committerGitHub <noreply@github.com>
Fri, 8 Dec 2017 16:29:19 +0000 (16:29 +0000)
Replace magic numbers in linkerscripts by PAGE_SIZE

33 files changed:
Makefile
bl32/sp_min/sp_min.ld.S
docs/plat/rpi3.rst [new file with mode: 0644]
docs/user-guide.rst
include/plat/arm/board/common/board_arm_def.h
include/plat/arm/common/arm_def.h
lib/cpus/aarch32/cortex_a53.S
lib/cpus/aarch32/cortex_a57.S
lib/cpus/aarch32/cortex_a72.S
maintainers.rst
make_helpers/defaults.mk
make_helpers/tbbr/tbbr_tools.mk
plat/arm/board/juno/include/platform_def.h
plat/arm/board/juno/juno_bl2_setup.c
plat/arm/board/juno/platform.mk
plat/arm/css/common/css_bl2_setup.c
plat/hisilicon/hikey960/hikey960_pm.c
plat/hisilicon/hikey960/include/platform_def.h
plat/rpi3/aarch64/plat_helpers.S [new file with mode: 0644]
plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c [new file with mode: 0644]
plat/rpi3/include/plat_macros.S [new file with mode: 0644]
plat/rpi3/include/platform_def.h [new file with mode: 0644]
plat/rpi3/platform.mk [new file with mode: 0644]
plat/rpi3/rpi3_bl1_setup.c [new file with mode: 0644]
plat/rpi3/rpi3_bl2_setup.c [new file with mode: 0644]
plat/rpi3/rpi3_bl31_setup.c [new file with mode: 0644]
plat/rpi3/rpi3_common.c [new file with mode: 0644]
plat/rpi3/rpi3_hw.h [new file with mode: 0644]
plat/rpi3/rpi3_image_load.c [new file with mode: 0644]
plat/rpi3/rpi3_io_storage.c [new file with mode: 0644]
plat/rpi3/rpi3_pm.c [new file with mode: 0644]
plat/rpi3/rpi3_private.h [new file with mode: 0644]
plat/rpi3/rpi3_topology.c [new file with mode: 0644]

index fe18bc0ea4ade881a953b5271c33b49757e42d0e..fe757984c2d06baf2bf213201ac65895a614c675 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -383,6 +383,17 @@ ifdef SCP_BL2
         NEED_SCP_BL2           :=      yes
 endif
 
+# For AArch32, BL31 is not currently supported.
+ifneq (${ARCH},aarch32)
+    ifdef BL31_SOURCES
+        # When booting an EL3 payload, there is no need to compile the BL31 image nor
+        # put it in the FIP.
+        ifndef EL3_PAYLOAD_BASE
+            NEED_BL31 := yes
+        endif
+    endif
+endif
+
 # Process TBB related flags
 ifneq (${GENERATE_COT},0)
         # Common cert_create options
@@ -434,17 +445,11 @@ NEED_BL2U := yes
 include bl2u/bl2u.mk
 endif
 
-# For AArch32, BL31 is not currently supported.
-ifneq (${ARCH},aarch32)
+ifeq (${NEED_BL31},yes)
 ifdef BL31_SOURCES
-# When booting an EL3 payload, there is no need to compile the BL31 image nor
-# put it in the FIP.
-ifndef EL3_PAYLOAD_BASE
-NEED_BL31 := yes
 include bl31/bl31.mk
 endif
 endif
-endif
 
 ################################################################################
 # Build options checks
index 8202cf9e36df46cec88262ffdd28e99c8864414c..e798a0d38e3d2d03d80ce9acf8ff81e8d1825e4f 100644 (file)
@@ -111,6 +111,10 @@ SECTIONS
         __DATA_END__ = .;
     } >RAM
 
+#ifdef BL32_PROGBITS_LIMIT
+    ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.")
+#endif
+
     stacks (NOLOAD) : {
         __STACKS_START__ = .;
         *(tzfw_normal_stacks)
diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst
new file mode 100644 (file)
index 0000000..219faaf
--- /dev/null
@@ -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/
index 79d660d0251fea3787e9ef04adabba2f47bb13c7..138ed8b3d764545b18ccb634840df44cf6ca5a22 100644 (file)
@@ -1212,7 +1212,7 @@ corrupted binaries.
 
           make ARCH=aarch64 PLAT=juno LOAD_IMAGE_V2=1 JUNO_AARCH32_EL3_RUNTIME=1 \
           BL33=<path-to-juno32-oe-uboot>/SOFTWARE/bl33-uboot.bin \
-          SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin SPD=tspd \
+          SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin \
           BL32=<path-to-bl32>/bl32.bin all fip
 
 The resulting BL1 and FIP images may be found in:
index 97a1af4bff6623e5626d12dbc6aa7603a1d7a9df..68f4a0ec0905fc66109026e9fcfbf9ff72c56f25 100644 (file)
 #define PLAT_ARM_MAX_BL31_SIZE         0x1D000
 #endif
 
+#ifdef AARCH32
+/*
+ * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
+ * Payload.
+ */
+# define PLAT_ARM_MAX_BL32_SIZE                0x1D000
+#endif
+
 #endif /* ARM_BOARD_OPTIMISE_MEM */
 
 #define MAX_IO_DEVICES                 3
index b8955afcc48320b7495f7fec0abb9b5b4661e5db..7887525992705e9811fe8aeda876c33a64d01d82 100644 (file)
 /*******************************************************************************
  * BL2 specific defines.
  ******************************************************************************/
-#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
+#if ARM_BL31_IN_DRAM
 /*
- * For AArch32 BL31 is not applicable.
  * For AArch64 BL31 is loaded in the DRAM.
  * Put BL2 just below BL1.
  */
 #define BL2_BASE                       (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
 #define BL2_LIMIT                      BL1_RW_BASE
+
+#elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
+/*
+ * Put BL2 just below BL32.
+ */
+#define BL2_BASE                       (BL32_BASE - PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_LIMIT                      BL32_BASE
+
 #else
 /*
  * Put BL2 just below BL31.
 #define BL31_LIMIT                     (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 #endif
 
+#if defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
 /*******************************************************************************
- * BL32 specific defines.
+ * BL32 specific defines for EL3 runtime in AArch32 mode
+ ******************************************************************************/
+# if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME
+/* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM to BL32 */
+#  define BL32_BASE                    ARM_BL_RAM_BASE
+#  define BL32_LIMIT                   (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+# else
+/* Put BL32 at the top of the Trusted SRAM.*/
+#  define BL32_BASE                    (ARM_BL_RAM_BASE +              \
+                                               ARM_BL_RAM_SIZE -       \
+                                               PLAT_ARM_MAX_BL32_SIZE)
+#  define BL32_PROGBITS_LIMIT          BL1_RW_BASE
+#  define BL32_LIMIT                   (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
+# endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */
+
+#else
+/*******************************************************************************
+ * BL32 specific defines for EL3 runtime in AArch64 mode
  ******************************************************************************/
 /*
  * On ARM standard platforms, the TSP can execute from Trusted SRAM,
  * Trusted DRAM (if available) or the DRAM region secured by the TrustZone
  * controller.
  */
-#if ENABLE_SPM
-# define TSP_SEC_MEM_BASE              (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
-# define TSP_SEC_MEM_SIZE              (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
-# define BL32_BASE                     (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
-# define BL32_LIMIT                    (ARM_AP_TZC_DRAM1_BASE +        \
+# if ENABLE_SPM
+#  define TSP_SEC_MEM_BASE             (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define TSP_SEC_MEM_SIZE             (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
+#  define BL32_BASE                    (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define BL32_LIMIT                   (ARM_AP_TZC_DRAM1_BASE +        \
                                                ARM_AP_TZC_DRAM1_SIZE)
-#elif ARM_BL31_IN_DRAM
-# define TSP_SEC_MEM_BASE              (ARM_AP_TZC_DRAM1_BASE +        \
+# elif ARM_BL31_IN_DRAM
+#  define TSP_SEC_MEM_BASE             (ARM_AP_TZC_DRAM1_BASE +        \
                                                PLAT_ARM_MAX_BL31_SIZE)
-# define TSP_SEC_MEM_SIZE              (ARM_AP_TZC_DRAM1_SIZE -        \
+#  define TSP_SEC_MEM_SIZE             (ARM_AP_TZC_DRAM1_SIZE -        \
                                                PLAT_ARM_MAX_BL31_SIZE)
-# define BL32_BASE                     (ARM_AP_TZC_DRAM1_BASE +        \
+#  define BL32_BASE                    (ARM_AP_TZC_DRAM1_BASE +        \
                                                PLAT_ARM_MAX_BL31_SIZE)
-# define BL32_LIMIT                    (ARM_AP_TZC_DRAM1_BASE +        \
+#  define BL32_LIMIT                   (ARM_AP_TZC_DRAM1_BASE +        \
                                                ARM_AP_TZC_DRAM1_SIZE)
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
-# define TSP_SEC_MEM_BASE              ARM_BL_RAM_BASE
-# define TSP_SEC_MEM_SIZE              ARM_BL_RAM_SIZE
-# define TSP_PROGBITS_LIMIT            BL2_BASE
-# define BL32_BASE                     ARM_BL_RAM_BASE
-# define BL32_LIMIT                    BL31_BASE
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
-# define TSP_SEC_MEM_BASE              PLAT_ARM_TRUSTED_DRAM_BASE
-# define TSP_SEC_MEM_SIZE              PLAT_ARM_TRUSTED_DRAM_SIZE
-# define BL32_BASE                     PLAT_ARM_TRUSTED_DRAM_BASE
-# define BL32_LIMIT                    (PLAT_ARM_TRUSTED_DRAM_BASE     \
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
+#  define TSP_SEC_MEM_BASE             ARM_BL_RAM_BASE
+#  define TSP_SEC_MEM_SIZE             ARM_BL_RAM_SIZE
+#  define TSP_PROGBITS_LIMIT           BL2_BASE
+#  define BL32_BASE                    ARM_BL_RAM_BASE
+#  define BL32_LIMIT                   BL31_BASE
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
+#  define TSP_SEC_MEM_BASE             PLAT_ARM_TRUSTED_DRAM_BASE
+#  define TSP_SEC_MEM_SIZE             PLAT_ARM_TRUSTED_DRAM_SIZE
+#  define BL32_BASE                    PLAT_ARM_TRUSTED_DRAM_BASE
+#  define BL32_LIMIT                   (PLAT_ARM_TRUSTED_DRAM_BASE     \
                                                + (1 << 21))
-#elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID
-# define TSP_SEC_MEM_BASE              ARM_AP_TZC_DRAM1_BASE
-# define TSP_SEC_MEM_SIZE              ARM_AP_TZC_DRAM1_SIZE
-# define BL32_BASE                     ARM_AP_TZC_DRAM1_BASE
-# define BL32_LIMIT                    (ARM_AP_TZC_DRAM1_BASE +        \
+# elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID
+#  define TSP_SEC_MEM_BASE             ARM_AP_TZC_DRAM1_BASE
+#  define TSP_SEC_MEM_SIZE             ARM_AP_TZC_DRAM1_SIZE
+#  define BL32_BASE                    ARM_AP_TZC_DRAM1_BASE
+#  define BL32_LIMIT                   (ARM_AP_TZC_DRAM1_BASE +        \
                                                ARM_AP_TZC_DRAM1_SIZE)
-#else
-# error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
-#endif
+# else
+#  error "Unsupported ARM_TSP_RAM_LOCATION_ID value"
+# endif
+#endif /* AARCH32 || JUNO_AARCH32_EL3_RUNTIME */
 
 /*
  * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no
  * SPD and no SPM, as they are the only ones that can be used as BL32.
  */
-#ifndef AARCH32
+#if !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME)
 # if defined(SPD_none) && !ENABLE_SPM
 #  undef BL32_BASE
-# endif
-#endif
+# endif /* defined(SPD_none) && !ENABLE_SPM */
+#endif /* !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME) */
 
 /*******************************************************************************
  * FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
  ******************************************************************************/
 #define BL2U_BASE                      BL2_BASE
-#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME))
-/*
- * For AArch32 BL31 is not applicable.
- * For AArch64 BL31 is loaded in the DRAM.
- * BL2U extends up to BL1.
- */
-#define BL2U_LIMIT                     BL1_RW_BASE
-#else
-/* BL2U extends up to BL31. */
-#define BL2U_LIMIT                     BL31_BASE
-#endif
+#define BL2U_LIMIT                     BL2_LIMIT
+
 #define NS_BL2U_BASE                   ARM_NS_DRAM1_BASE
 #define NS_BL1U_BASE                   (PLAT_ARM_NVM_BASE + 0x03EB8000)
 
index 74cedc35c79bfbb1adf227e6a8bb1571652f6d52..1647e169f64a17467983c09a557bfe9c2be3ec32 100644 (file)
@@ -174,7 +174,7 @@ func cortex_a53_core_pwr_dwn
        push    {r12, lr}
 
        /* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
        ldcopr  r0, SCTLR
        tst     r0, #SCTLR_C_BIT
        ASM_ASSERT(eq)
@@ -204,7 +204,7 @@ func cortex_a53_cluster_pwr_dwn
        push    {r12, lr}
 
        /* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
        ldcopr  r0, SCTLR
        tst     r0, #SCTLR_C_BIT
        ASM_ASSERT(eq)
index b5189e77fab45fc5e24acfa5591d9c2186008cbc..64a6d6745170a88f23fc9cfce2c516b896c3010d 100644 (file)
@@ -406,7 +406,7 @@ func cortex_a57_core_pwr_dwn
        push    {r12, lr}
 
        /* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
        ldcopr  r0, SCTLR
        tst     r0, #SCTLR_C_BIT
        ASM_ASSERT(eq)
@@ -448,7 +448,7 @@ func cortex_a57_cluster_pwr_dwn
        push    {r12, lr}
 
        /* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
        ldcopr  r0, SCTLR
        tst     r0, #SCTLR_C_BIT
        ASM_ASSERT(eq)
index 69cc2ea55886c895167b17a1b67d11a039297f79..75505206430b49759dc1e63790c4234502f516d1 100644 (file)
@@ -120,7 +120,7 @@ func cortex_a72_core_pwr_dwn
        push    {r12, lr}
 
        /* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
        ldcopr  r0, SCTLR
        tst     r0, #SCTLR_C_BIT
        ASM_ASSERT(eq)
@@ -167,7 +167,7 @@ func cortex_a72_cluster_pwr_dwn
        push    {r12, lr}
 
        /* Assert if cache is enabled */
-#if ASM_ASSERTION
+#if ENABLE_ASSERTIONS
        ldcopr  r0, SCTLR
        tst     r0, #SCTLR_C_BIT
        ASM_ASSERT(eq)
index 701ea17ec481fcec05b030eb25138ef65ff1faa4..04ab695e00fa591bfb8dffc009117994ba6842b5 100644 (file)
@@ -21,8 +21,8 @@ Jens Wiklander (jens.wiklander@linaro.org, `jenswi-linaro`_)
 
 Files:
 
--  docs/spd/optee-dispatcher.md
--  docs/plat/qemu.md
+-  docs/plat/qemu.rst
+-  docs/spd/optee-dispatcher.rst
 -  services/spd/opteed/\*
 -  plat/qemu/\*
 
@@ -33,8 +33,9 @@ Varun Wadekar (vwadekar@nvidia.com, `vwadekar`_)
 
 Files:
 
--  docs/spd/tlk-dispatcher.md
--  docs/spd/trusty-dispatcher.md
+-  docs/plat/nvidia-tegra.rst
+-  docs/spd/tlk-dispatcher.rst
+-  docs/spd/trusty-dispatcher.rst
 -  include/bl32/payloads/tlk.h
 -  include/lib/cpus/aarch64/denver.h
 -  lib/cpus/aarch64/denver.S
@@ -49,8 +50,9 @@ Haojian Zhuang (haojian.zhuang@linaro.org, `hzhuang1`_)
 
 Files:
 
--  docs/plat/hikey.md
--  docs/plat/hikey960.md
+-  docs/plat/hikey.rst
+-  docs/plat/hikey960.rst
+-  docs/plat/poplar.rst
 -  drivers/emmc/\*
 -  drivers/partition/\*
 -  drivers/synopsys/emmc/\*
@@ -71,24 +73,44 @@ Files:
 
 -  plat/mediatek/\*
 
+Raspberry Pi 3 platform sub-maintainer
+--------------------------------------
+
+Antonio Niño Díaz (antonio.ninodiaz@arm.com, `antonio-nino-diaz-arm`_)
+
+Files:
+
+-  docs/plat/rpi3.rst
+-  plat/rpi3/\*
+
 RockChip platform sub-maintainer
 --------------------------------
 
 Tony Xie (tony.xie@rock-chips.com, `TonyXie06`_
-or `rkchrome`_)
+or `rockchip-linux`_)
 
 Files:
 
 -  plat/rockchip/\*
 
+UniPhier platform sub-maintainer
+--------------------------------
+
+Masahiro Yamada (yamada.masahiro@socionext.com, `masahir0y`_)
+
+Files:
+
+- docs/plat/socionext-uniphier.rst
+- plat/socionext/\*
+
 Xilinx platform sub-maintainer
 ------------------------------
 
-Sören Brinkmann (soren.brinkmann@xilinx.com, `sorenb-xlnx`_)
+Siva Durga Prasad Paladugu (siva.durga.paladugu@xilinx.com, `sivadur`_)
 
 Files:
 
--  docs/plat/xilinx-zynqmp.md
+-  docs/plat/xilinx-zynqmp.rst
 -  plat/xilinx/\*
 
 ARMv7 architecture sub-maintainer
@@ -96,13 +118,15 @@ 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
 .. _vwadekar: https://github.com/vwadekar
 .. _hzhuang1: https://github.com/hzhuang1
+.. _masahir0y: https://github.com/masahir0y
 .. _mtk09422: https://github.com/mtk09422
 .. _TonyXie06: https://github.com/TonyXie06
-.. _rkchrome: https://github.com/rkchrome
-.. _sorenb-xlnx: https://github.com/sorenb-xlnx
+.. _sivadur: https://github.com/sivadur
+.. _rockchip-linux: https://github.com/rockchip-linux
 .. _etienne-lms: https://github.com/etienne-lms
index 9f7abed1ebee2c3d6f75194f7ba99163daa4225f..4584e6353ac3da6752c6b8b3172da93a817467dd 100644 (file)
@@ -24,9 +24,6 @@ ARM_ARCH_MINOR                        := 0
 # in EL3. The platform port can change this value if needed.
 ARM_GIC_ARCH                   := 2
 
-# Flag used to indicate if ASM_ASSERTION should be enabled for the build.
-ASM_ASSERTION                  := 0
-
 # Base commit to perform code check on
 BASE_COMMIT                    := origin/master
 
index b13afe488f72b3c2505216b312ef01696e4ad17e..6e6e2739628a9e8189bd6769e9ef6240009a9c40 100644 (file)
@@ -77,6 +77,7 @@ ifneq (${SCP_BL2},)
 endif
 
 ifeq (${ARCH},aarch64)
+ifeq (${NEED_BL31},yes)
 # Add the BL31 CoT (key cert + img cert + image)
 $(if ${BL31},$(eval $(call CERT_ADD_CMD_OPT,${BL31},--soc-fw,true)),\
              $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,31),--soc-fw,true)))
@@ -86,6 +87,7 @@ $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert))
 $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert))
 $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert))
 endif
+endif
 
 # Add the BL32 CoT (key cert + img cert + image)
 ifeq (${NEED_BL32},yes)
index ccc7771e59c80cdbbf86fec6dadc464a278aed31..e475ece5a4917914a6f029b1c2dabff48c04dc18 100644 (file)
  */
 #define PLAT_ARM_MAX_BL31_SIZE         0x1E000
 
+#if JUNO_AARCH32_EL3_RUNTIME
+/*
+ * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
+ * Payload. We also need to take care of SCP_BL2 size as well, as the SCP_BL2
+ * is loaded into the space BL32 -> BL1_RW_BASE
+ */
+# define PLAT_ARM_MAX_BL32_SIZE                0x1E000
+#endif
+
 /*
  * Since free SRAM space is scant, enable the ASSERTION message size
  * optimization by fixing the PLAT_LOG_LEVEL_ASSERT to LOG_LEVEL_INFO (40).
index 2771e0f3794d1b0c648ac03438f85eb8e741b5ea..cedef66c9a0a585135726ff3da0d8fb09677c8ed 100644 (file)
@@ -29,33 +29,4 @@ int bl2_plat_handle_post_image_load(unsigned int image_id)
 
        return err;
 }
-
-#if !CSS_USE_SCMI_SDS_DRIVER
-/*
- * We need to override some of the platform functions when booting SP_MIN
- * on Juno AArch32. These needs to be done only for SCPI/BOM SCP systems as
- * in case of SDS, the structures remain in memory and doesn't need to be
- * overwritten.
- */
-
-static unsigned int scp_boot_config;
-
-void bl2_early_platform_setup(meminfo_t *mem_layout)
-{
-       arm_bl2_early_platform_setup(mem_layout);
-
-       /* Save SCP Boot config before it gets overwritten by SCP_BL2 loading */
-       VERBOSE("BL2: Saving SCP Boot config = 0x%x\n", scp_boot_config);
-       scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR);
-}
-
-void bl2_platform_setup(void)
-{
-       arm_bl2_platform_setup();
-
-       mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
-       VERBOSE("BL2: Restored SCP Boot config = 0x%x\n", scp_boot_config);
-}
-#endif
-
 #endif /* JUNO_AARCH32_EL3_RUNTIME */
index 5cd125bff07f9b2b391916f34468dc2403c66ba5..bfb7847fed016fd4e685c54d790c04d3b2566929 100644 (file)
@@ -31,6 +31,19 @@ JUNO_AARCH32_EL3_RUNTIME     :=      0
 $(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME))
 $(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME))
 
+ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
+# Include BL32 in FIP
+NEED_BL32              := yes
+# BL31 is not required
+override BL31_SOURCES =
+
+# The BL32 needs to be built separately invoking the AARCH32 compiler and
+# be specifed via `BL32` build option.
+  ifneq (${ARCH}, aarch32)
+    override BL32_SOURCES =
+  endif
+endif
+
 ifeq (${ARCH},aarch64)
 BL1_SOURCES            +=      lib/cpus/aarch64/cortex_a53.S           \
                                lib/cpus/aarch64/cortex_a57.S           \
index 9b4800e340b87753c0f229cbb87f7257b91b0102..b4aafd464ae303263f1674a6f93ffd6fc7f66c88 100644 (file)
@@ -49,13 +49,13 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info)
 }
 
 #if !CSS_USE_SCMI_SDS_DRIVER
-# ifdef EL3_PAYLOAD_BASE
+# if defined(EL3_PAYLOAD_BASE) || JUNO_AARCH32_EL3_RUNTIME
 
 /*
  * We need to override some of the platform functions when booting an EL3
- * payload. These needs to be done only for SCPI/BOM SCP systems as
- * in case of SDS, the structures remain in memory and doesn't need to be
- * overwritten.
+ * payload or SP_MIN on Juno AArch32. This needs to be done only for
+ * SCPI/BOM SCP systems as in case of SDS, the structures remain in memory and
+ * don't need to be overwritten.
  */
 
 static unsigned int scp_boot_config;
index 348cdba517c9660edf448a896084eaa018be60a7..078f0d81344f98ef2241276045c210a226231025 100644 (file)
 #define SYSTEM_PWR_STATE(state) \
        ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
 
+#define PSTATE_WIDTH           4
+#define PSTATE_MASK            ((1 << PSTATE_WIDTH) - 1)
+
+#define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
+               (((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \
+                ((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \
+                ((lvl0_state) << (PSTATE_ID_SHIFT)) | \
+                ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
+                ((type) << PSTATE_TYPE_SHIFT))
+
+/*
+ * 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.
+ */
+const unsigned int hikey960_pwr_idle_states[] = {
+       /* State-id - 0x001 */
+       MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+                     PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+       /* State-id - 0x002 */
+       MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+                     PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
+       /* State-id - 0x003 */
+       MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
+                     PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
+       /* State-id - 0x033 */
+       MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE,
+                     PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
+       0,
+};
+
 #define DMAC_GLB_REG_SEC       0x694
 #define AXI_CONF_BASE          0x820
 
@@ -36,16 +68,21 @@ static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
        unsigned long scr;
        unsigned int val = 0;
 
-       assert(cpu_state == PLAT_MAX_RET_STATE);
+       assert(cpu_state == PLAT_MAX_STB_STATE ||
+              cpu_state == PLAT_MAX_RET_STATE);
 
        scr = read_scr_el3();
 
        /* Enable Physical IRQ and FIQ to wake the CPU*/
        write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
 
-       set_retention_ticks(val);
+       if (cpu_state == PLAT_MAX_RET_STATE)
+               set_retention_ticks(val);
+
        wfi();
-       clr_retention_ticks(val);
+
+       if (cpu_state == PLAT_MAX_RET_STATE)
+               clr_retention_ticks(val);
 
        /*
         * Restore SCR to the original value, synchronisazion of
@@ -124,38 +161,34 @@ static void __dead2 hikey960_system_reset(void)
 int hikey960_validate_power_state(unsigned int power_state,
                               psci_power_state_t *req_state)
 {
-       int pstate = psci_get_pstate_type(power_state);
-       int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
+       unsigned int state_id;
        int i;
 
        assert(req_state);
 
-       if (pwr_lvl > PLAT_MAX_PWR_LVL)
-               return PSCI_E_INVALID_PARAMS;
-
-       /* Sanity check the requested state */
-       if (pstate == PSTATE_TYPE_STANDBY) {
-               /*
-                * It's possible to enter standby only on power level 0
-                * Ignore any other power level.
-                */
-               if (pwr_lvl != MPIDR_AFFLVL0)
-                       return PSCI_E_INVALID_PARAMS;
-
-               req_state->pwr_domain_state[MPIDR_AFFLVL0] =
-                                       PLAT_MAX_RET_STATE;
-       } else {
-               for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
-                       req_state->pwr_domain_state[i] =
-                                       PLAT_MAX_OFF_STATE;
-       }
-
        /*
-        * We expect the 'state id' to be zero.
+        *  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.
         */
-       if (psci_get_pstate_id(power_state))
+       for (i = 0; !!hikey960_pwr_idle_states[i]; i++) {
+               if (power_state == hikey960_pwr_idle_states[i])
+                       break;
+       }
+
+       /* Return error if entry not found in the idle state array */
+       if (!hikey960_pwr_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 & PSTATE_MASK;
+               state_id >>= PSTATE_WIDTH;
+       }
+
        return PSCI_E_SUCCESS;
 }
 
index cb7609076cda342dffe3c56f75b65a06038398cf..2ac7f2a75c265d7bcc2fd9a0cb61b2a8b2e1f6f4 100644 (file)
 #define PLAT_NUM_PWR_DOMAINS           (PLATFORM_CORE_COUNT + \
                                         PLATFORM_CLUSTER_COUNT + 1)
 
-#define PLAT_MAX_RET_STATE             1
-#define PLAT_MAX_OFF_STATE             2
+#define PLAT_MAX_RUN_STATE             0
+#define PLAT_MAX_STB_STATE             1
+#define PLAT_MAX_RET_STATE             2
+#define PLAT_MAX_OFF_STATE             3
 
 #define MAX_IO_DEVICES                 3
 #define MAX_IO_HANDLES                 4
diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S
new file mode 100644 (file)
index 0000000..76a542f
--- /dev/null
@@ -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
diff --git a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c
new file mode 100644 (file)
index 0000000..e3acfe9
--- /dev/null
@@ -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)
diff --git a/plat/rpi3/include/plat_macros.S b/plat/rpi3/include/plat_macros.S
new file mode 100644 (file)
index 0000000..f5e057e
--- /dev/null
@@ -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__ */
diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h
new file mode 100644 (file)
index 0000000..5e2f1da
--- /dev/null
@@ -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__ */
diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk
new file mode 100644 (file)
index 0000000..821f801
--- /dev/null
@@ -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
diff --git a/plat/rpi3/rpi3_bl1_setup.c b/plat/rpi3/rpi3_bl1_setup.c
new file mode 100644 (file)
index 0000000..11c0f4a
--- /dev/null
@@ -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();
+}
diff --git a/plat/rpi3/rpi3_bl2_setup.c b/plat/rpi3/rpi3_bl2_setup.c
new file mode 100644 (file)
index 0000000..1fd822e
--- /dev/null
@@ -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;
+}
diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c
new file mode 100644 (file)
index 0000000..3913356
--- /dev/null
@@ -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);
+}
diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c
new file mode 100644 (file)
index 0000000..97dce09
--- /dev/null
@@ -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;
+}
diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h
new file mode 100644 (file)
index 0000000..70272e0
--- /dev/null
@@ -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__ */
diff --git a/plat/rpi3/rpi3_image_load.c b/plat/rpi3/rpi3_image_load.c
new file mode 100644 (file)
index 0000000..fad9e4f
--- /dev/null
@@ -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();
+}
diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c
new file mode 100644 (file)
index 0000000..7ac45ef
--- /dev/null
@@ -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;
+}
diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c
new file mode 100644 (file)
index 0000000..1d067fb
--- /dev/null
@@ -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;
+}
diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h
new file mode 100644 (file)
index 0000000..01c4055
--- /dev/null
@@ -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__ */
diff --git a/plat/rpi3/rpi3_topology.c b/plat/rpi3/rpi3_topology.c
new file mode 100644 (file)
index 0000000..0e03ec3
--- /dev/null
@@ -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);
+}