rpi3: Introduce AArch64 Raspberry Pi 3 port
authorAntonio Nino Diaz <antonio.ninodiaz@arm.com>
Mon, 6 Nov 2017 14:49:04 +0000 (14:49 +0000)
committerAntonio Nino Diaz <antonio.ninodiaz@arm.com>
Fri, 1 Dec 2017 10:20:47 +0000 (10:20 +0000)
This port can be compiled to boot an AArch64 or AArch32 payload with the
build option `RPI3_BL33_AARCH32`.

Note: This is not a secure port of the Trusted Firmware. This port is
only meant to be a reference implementation to experiment with an
inexpensive board in real hardware.

Change-Id: Ide58114299289bf765ef1366199eb05c46f81903
Co-authored-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
16 files changed:
maintainers.rst
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 701ea17ec481fcec05b030eb25138ef65ff1faa4..c878f619f37f08a163a1c4be3f07df1c8658a7af 100644 (file)
@@ -71,6 +71,15 @@ Files:
 
 -  plat/mediatek/\*
 
+Raspberry Pi 3 platform sub-maintainer
+--------------------------------------
+
+Antonio Niño Díaz (antonio.ninodiaz@arm.com, `antonio-nino-diaz-arm`_)
+
+Files:
+
+-  plat/rpi3/\*
+
 RockChip platform sub-maintainer
 --------------------------------
 
@@ -96,6 +105,7 @@ ARMv7 architecture sub-maintainer
 
 Etienne Carriere (etienne.carriere@linaro.org, `etienne-lms`_)
 
+.. _antonio-nino-diaz-arm: https://github.com/antonio-nino-diaz-arm
 .. _danh-arm: https://github.com/danh-arm
 .. _davidcunado-arm: https://github.com/davidcunado-arm
 .. _jenswi-linaro: https://github.com/jenswi-linaro
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);
+}