From 01b916bff2dca219d4088b8abca0a02ac06dd615 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Thu, 17 Jul 2014 16:06:39 +0100 Subject: [PATCH 1/5] Juno: Implement initial platform port This patch adds the initial port of the ARM Trusted Firmware on the Juno development platform. This port does not support a BL3-2 image or any PSCI APIs apart from PSCI_VERSION and PSCI_CPU_ON. It enables workarounds for selected Cortex-A57 (#806969 & #813420) errata and implements the workaround for a Juno platform errata (Defect id 831273). Change-Id: Ib3d92df3af53820cfbb2977582ed0d7abf6ef893 --- include/lib/aarch64/arch.h | 4 + include/lib/cpus/aarch64/cortex_a57.h | 11 + plat/juno/aarch64/bl1_plat_helpers.S | 125 ++++++++++ plat/juno/aarch64/juno_common.c | 108 +++++++++ plat/juno/aarch64/plat_helpers.S | 161 +++++++++++++ plat/juno/bl1_plat_setup.c | 240 +++++++++++++++++++ plat/juno/bl2_plat_setup.c | 316 ++++++++++++++++++++++++++ plat/juno/bl31_plat_setup.c | 184 +++++++++++++++ plat/juno/include/plat_macros.S | 108 +++++++++ plat/juno/include/platform_def.h | 161 +++++++++++++ plat/juno/juno_def.h | 196 ++++++++++++++++ plat/juno/juno_private.h | 153 +++++++++++++ plat/juno/mhu.c | 95 ++++++++ plat/juno/mhu.h | 43 ++++ plat/juno/plat_gic.c | 283 +++++++++++++++++++++++ plat/juno/plat_io_storage.c | 197 ++++++++++++++++ plat/juno/plat_pm.c | 161 +++++++++++++ plat/juno/plat_topology.c | 60 +++++ plat/juno/platform.mk | 82 +++++++ plat/juno/scp_bootloader.c | 153 +++++++++++++ plat/juno/scp_bootloader.h | 36 +++ plat/juno/scpi.c | 126 ++++++++++ plat/juno/scpi.h | 74 ++++++ 23 files changed, 3077 insertions(+) create mode 100644 plat/juno/aarch64/bl1_plat_helpers.S create mode 100644 plat/juno/aarch64/juno_common.c create mode 100644 plat/juno/aarch64/plat_helpers.S create mode 100644 plat/juno/bl1_plat_setup.c create mode 100644 plat/juno/bl2_plat_setup.c create mode 100644 plat/juno/bl31_plat_setup.c create mode 100644 plat/juno/include/plat_macros.S create mode 100644 plat/juno/include/platform_def.h create mode 100644 plat/juno/juno_def.h create mode 100644 plat/juno/juno_private.h create mode 100644 plat/juno/mhu.c create mode 100644 plat/juno/mhu.h create mode 100644 plat/juno/plat_gic.c create mode 100644 plat/juno/plat_io_storage.c create mode 100644 plat/juno/plat_pm.c create mode 100644 plat/juno/plat_topology.c create mode 100644 plat/juno/platform.mk create mode 100644 plat/juno/scp_bootloader.c create mode 100644 plat/juno/scp_bootloader.h create mode 100644 plat/juno/scpi.c create mode 100644 plat/juno/scpi.h diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index b2aac2fb70..4056260779 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -166,6 +166,10 @@ #define EL0VTEN_BIT (1 << 8) #define EL0PCTEN_BIT (1 << 0) #define EL0VCTEN_BIT (1 << 1) +#define EVNTEN_BIT (1 << 2) +#define EVNTDIR_BIT (1 << 3) +#define EVNTI_SHIFT 4 +#define EVNTI_MASK 0xf /* CPTR_EL3 definitions */ #define TCPAC_BIT (1 << 31) diff --git a/include/lib/cpus/aarch64/cortex_a57.h b/include/lib/cpus/aarch64/cortex_a57.h index 9cf8780d01..6128b1694e 100644 --- a/include/lib/cpus/aarch64/cortex_a57.h +++ b/include/lib/cpus/aarch64/cortex_a57.h @@ -52,4 +52,15 @@ #define CPUACTLR_NO_ALLOC_WBWA (1 << 49) #define CPUACTLR_DCC_AS_DCCI (1 << 44) +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define L2CTLR_EL1 S3_1_C11_C0_2 /* Instruction def. */ + +#define L2CTLR_DATA_RAM_LATENCY_SHIFT 0 +#define L2CTLR_TAG_RAM_LATENCY_SHIFT 6 + +#define L2_DATA_RAM_LATENCY_3_CYCLES 0x2 +#define L2_TAG_RAM_LATENCY_3_CYCLES 0x2 + #endif /* __CORTEX_A57_H__ */ diff --git a/plat/juno/aarch64/bl1_plat_helpers.S b/plat/juno/aarch64/bl1_plat_helpers.S new file mode 100644 index 0000000000..785aa15adb --- /dev/null +++ b/plat/juno/aarch64/bl1_plat_helpers.S @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "../juno_def.h" + + .globl platform_get_entrypoint + .globl platform_cold_boot_init + .globl plat_secondary_cold_boot_setup + + + /* ----------------------------------------------------- + * 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 + /* Juno todo: Implement secondary CPU cold boot setup on Juno */ +cb_panic: + b cb_panic + + + /* ----------------------------------------------------- + * void platform_get_entrypoint (unsigned int mpid); + * + * Main job of this routine is to distinguish between + * a cold and warm boot. + * On a cold boot the secondaries first wait for the + * platform to be initialized after which they are + * hotplugged in. The primary proceeds to perform the + * platform initialization. + * On a warm boot, each cpu jumps to the address in its + * mailbox. + * + * TODO: Not a good idea to save lr in a temp reg + * ----------------------------------------------------- + */ +func platform_get_entrypoint + mov x9, x30 // lr + bl platform_get_core_pos + ldr x1, =TRUSTED_MAILBOXES_BASE + lsl x0, x0, #TRUSTED_MAILBOX_SHIFT + ldr x0, [x1, x0] + ret x9 + + + /* ----------------------------------------------------- + * void platform_cold_boot_init (bl1_main function); + * + * Routine called only by the primary cpu after a cold + * boot to perform early platform initialization + * ----------------------------------------------------- + */ +func platform_cold_boot_init + mov x20, x0 + + /* --------------------------------------------- + * Give ourselves a small coherent stack to + * ease the pain of initializing the MMU and + * CCI in assembler + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_coherent_stack + + /* --------------------------------------------- + * Architectural init. can be generic e.g. + * enabling stack alignment and platform spec- + * ific e.g. MMU & page table setup as per the + * platform memory map. Perform the latter here + * and the former in bl1_main. + * --------------------------------------------- + */ + bl bl1_early_platform_setup + bl bl1_plat_arch_setup + + /* --------------------------------------------- + * Give ourselves a stack allocated in Normal + * -IS-WBWA memory + * --------------------------------------------- + */ + mrs x0, mpidr_el1 + bl platform_set_stack + + /* --------------------------------------------- + * Jump to the main function. Returning from it + * is a terminal error. + * --------------------------------------------- + */ + blr x20 + +cb_init_panic: + b cb_init_panic diff --git a/plat/juno/aarch64/juno_common.c b/plat/juno/aarch64/juno_common.c new file mode 100644 index 0000000000..5ba38c1165 --- /dev/null +++ b/plat/juno/aarch64/juno_common.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../juno_def.h" + +/* + * Table of regions to map using the MMU. + * This doesn't include Trusted RAM as the 'mem_layout' argument passed to + * configure_mmu_elx() will give the available subset of that, + */ +static const mmap_region_t juno_mmap[] = { + { TZROM_BASE, TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { MHU_SECURE_BASE, MHU_SECURE_BASE, MHU_SECURE_SIZE, (MHU_PAYLOAD_CACHED ? MT_MEMORY : MT_DEVICE) | MT_RW | MT_SECURE }, + { FLASH_BASE, FLASH_BASE, FLASH_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { EMMC_BASE, EMMC_BASE, EMMC_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, + { PSRAM_BASE, PSRAM_BASE, PSRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* Used for 'TZDRAM' */ + { IOFPGA_BASE, IOFPGA_BASE, IOFPGA_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, + { DRAM_BASE, DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + {0} +}; + +/******************************************************************************* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + ******************************************************************************/ +#define DEFINE_CONFIGURE_MMU_EL(_el) \ + void configure_mmu_el##_el(unsigned long total_base, \ + unsigned long total_size, \ + unsigned long ro_start, \ + unsigned long ro_limit, \ + unsigned long coh_start, \ + unsigned long coh_limit) \ + { \ + mmap_add_region(total_base, total_base, \ + total_size, \ + MT_MEMORY | MT_RW | MT_SECURE); \ + mmap_add_region(ro_start, ro_start, \ + ro_limit - ro_start, \ + MT_MEMORY | MT_RO | MT_SECURE); \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ + mmap_add(juno_mmap); \ + init_xlat_tables(); \ + \ + enable_mmu_el##_el(0); \ + } + +/* Define EL1 and EL3 variants of the function initialising the MMU */ +DEFINE_CONFIGURE_MMU_EL(1) +DEFINE_CONFIGURE_MMU_EL(3) + + +unsigned long plat_get_ns_image_entrypoint(void) +{ + return NS_IMAGE_OFFSET; +} + +uint64_t plat_get_syscnt_freq(void) +{ + uint64_t counter_base_frequency; + + /* Read the frequency from Frequency modes table */ + counter_base_frequency = mmio_read_32(SYS_CNTCTL_BASE + CNTFID_OFF); + + /* The first entry of the frequency modes table must not be 0 */ + if (counter_base_frequency == 0) + panic(); + + return counter_base_frequency; +} diff --git a/plat/juno/aarch64/plat_helpers.S b/plat/juno/aarch64/plat_helpers.S new file mode 100644 index 0000000000..03541620c3 --- /dev/null +++ b/plat/juno/aarch64/plat_helpers.S @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include "../juno_def.h" + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_report_exception + .globl plat_reset_handler + .globl platform_get_core_pos + .globl platform_is_primary_cpu + .globl platform_mem_init + + /* Define a crash console for the plaform */ +#define JUNO_CRASH_CONSOLE_BASE PL011_UART0_BASE + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, JUNO_CRASH_CONSOLE_BASE + mov_imm x1, PL011_UART0_CLK_IN_HZ + mov_imm x2, PL011_BAUDRATE + b console_core_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, JUNO_CRASH_CONSOLE_BASE + b console_core_putc + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * On Juno platform, it updates the LEDs + * to indicate where we are + * --------------------------------------------- + */ +func plat_report_exception + mrs x1, CurrentEl + lsr x1, x1, #MODE_EL_SHIFT + lsl x1, x1, #SYS_LED_EL_SHIFT + lsl x0, x0, #SYS_LED_EC_SHIFT + mov x2, #(SECURE << SYS_LED_SS_SHIFT) + orr x0, x0, x2 + orr x0, x0, x1 + mov x1, #VE_SYSREGS_BASE + add x1, x1, #V2M_SYS_LED + str w0, [x1] + ret + + /* + * Return 0 to 3 for the A53s and 4 or 5 for the A57s + */ +func platform_get_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + eor x0, x0, #(1 << MPIDR_AFFINITY_BITS) // swap A53/A57 order + add x0, x1, x0, LSR #6 + ret + + + /* ----------------------------------------------------- + * unsigned int platform_is_primary_cpu(unsigned long mpid); + * + * Given the mpidr say whether this cpu is the primary + * cpu (applicable only after a cold boot) + * ----------------------------------------------------- + */ +func platform_is_primary_cpu + /* Juno todo: allow configuration of primary CPU using SCC */ + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #JUNO_PRIMARY_CPU + cset x0, eq + ret + + + /* ----------------------------------------------------- + * void platform_mem_init(void); + * + * We don't need to carry out any memory initialization + * on Juno. The Secure RAM is accessible straight away. + * ----------------------------------------------------- + */ +func platform_mem_init + ret + + /* ----------------------------------------------------- + * void plat_reset_handler(void); + * + * Implement workaround for defect id 831273 by enabling + * an event stream every 65536 cycles and set the L2 RAM + * latencies for Cortex-A57. + * ----------------------------------------------------- + */ +func plat_reset_handler + /* Read the MIDR_EL1 */ + mrs x0, midr_el1 + ubfx x1, x0, MIDR_PN_SHIFT, #12 + cmp w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + b.ne 1f + + /* Change the L2 Data and Tag Ram latency to 3 cycles */ + mov x0, #(L2_DATA_RAM_LATENCY_3_CYCLES | \ + (L2_TAG_RAM_LATENCY_3_CYCLES << \ + L2CTLR_TAG_RAM_LATENCY_SHIFT)) + msr L2CTLR_EL1, x0 + +1: + /* --------------------------------------------- + * Enable the event stream every 65536 cycles + * --------------------------------------------- + */ + mov x0, #(0xf << EVNTI_SHIFT) + orr x0, x0, #EVNTEN_BIT + msr CNTKCTL_EL1, x0 + isb + ret diff --git a/plat/juno/bl1_plat_setup.c b/plat/juno/bl1_plat_setup.c new file mode 100644 index 0000000000..d2f2ab4932 --- /dev/null +++ b/plat/juno/bl1_plat_setup.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../bl1/bl1_private.h" +#include "juno_def.h" +#include "juno_private.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted RAM + ******************************************************************************/ +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +/* Data structure which holds the extents of the trusted RAM 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) +{ + const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE; + + /* Initialize the console to provide early debug support */ + console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE); + + /* + * Enable CCI-400 for this cluster. No need for locks as no other cpu is + * active at the moment + */ + cci_init(CCI400_BASE, + CCI400_SL_IFACE3_CLUSTER_IX, + CCI400_SL_IFACE4_CLUSTER_IX); + cci_enable_cluster_coherency(read_mpidr()); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = TZRAM_BASE; + bl1_tzram_layout.total_size = TZRAM_SIZE; + + /* Calculate how much RAM BL1 is using and how much remains free */ + bl1_tzram_layout.free_base = TZRAM_BASE; + bl1_tzram_layout.free_size = TZRAM_SIZE; + reserve_mem(&bl1_tzram_layout.free_base, + &bl1_tzram_layout.free_size, + BL1_RAM_BASE, + bl1_size); + + INFO("BL1: 0x%lx - 0x%lx [size = %u]\n", BL1_RAM_BASE, BL1_RAM_LIMIT, + bl1_size); +} + + +/* + * Address of slave 'n' security setting in the NIC-400 address region + * control + * TODO: Ideally this macro should be moved in a "nic-400.h" header file but + * it would be the only thing in there so it's not worth it at the moment. + */ +#define NIC400_ADDR_CTRL_SECURITY_REG(n) (0x8 + (n) * 4) + +static void init_nic400(void) +{ + /* + * NIC-400 Access Control Initialization + * + * Define access privileges by setting each corresponding bit to: + * 0 = Secure access only + * 1 = Non-secure access allowed + */ + + /* + * Allow non-secure access to some SOC regions, excluding UART1, which + * remains secure. + * Note: This is the NIC-400 device on the SOC + */ + mmio_write_32(SOC_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_USB_EHCI), ~0); + mmio_write_32(SOC_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_TLX_MASTER), ~0); + mmio_write_32(SOC_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_USB_OHCI), ~0); + mmio_write_32(SOC_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_PL354_SMC), ~0); + mmio_write_32(SOC_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_APB4_BRIDGE), ~0); + mmio_write_32(SOC_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(SOC_NIC400_BOOTSEC_BRIDGE), + ~SOC_NIC400_BOOTSEC_BRIDGE_UART1); + + /* + * Allow non-secure access to some CSS regions. + * Note: This is the NIC-400 device on the CSS + */ + mmio_write_32(CSS_NIC400_BASE + + NIC400_ADDR_CTRL_SECURITY_REG(CSS_NIC400_SLAVE_BOOTSECURE), + ~0); +} + + +static void init_tzc400(void) +{ + /* Enable all filter units available */ + mmio_write_32(TZC400_BASE + GATE_KEEPER_OFF, 0x0000000f); + + /* + * Secure read and write are enabled for region 0, and the background + * region (region 0) is enabled for all four filter units + */ + mmio_write_32(TZC400_BASE + REGION_ATTRIBUTES_OFF, 0xc0000000); + + /* + * Enable Non-secure read/write accesses for the Soc Devices from the + * Non-Secure World + */ + mmio_write_32(TZC400_BASE + REGION_ID_ACCESS_OFF, + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CCI400) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_PCIE) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD0) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_HDLCD1) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_USB) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_DMA330) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_THINLINKS) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_AP) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_GPU) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_SCP) | + TZC_REGION_ACCESS_RDWR(TZC400_NSAID_CORESIGHT) + ); +} + +#define PCIE_SECURE_REG 0x3000 +#define PCIE_SEC_ACCESS_MASK ((1 << 0) | (1 << 1)) /* REG and MEM access bits */ + +static void init_pcie(void) +{ + /* + * PCIE Root Complex Security settings to enable non-secure + * access to config registers. + */ + mmio_write_32(PCIE_CONTROL_BASE + PCIE_SECURE_REG, PCIE_SEC_ACCESS_MASK); +} + + +/******************************************************************************* + * Function which will perform any remaining platform-specific setup that can + * occur after the MMU and data cache have been enabled. + ******************************************************************************/ +void bl1_platform_setup(void) +{ + init_nic400(); + init_tzc400(); + init_pcie(); + + /* Initialise the IO layer and register platform IO devices */ + io_setup(); + + /* Enable and initialize the System level generic timer */ + mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN); +} + + +/******************************************************************************* + * Perform the very early platform specific architecture setup here. At the + * moment this only does basic initialization. Later architectural setup + * (bl1_arch_setup()) does not do anything platform specific. + ******************************************************************************/ +void bl1_plat_arch_setup(void) +{ + configure_mmu_el3(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + TZROM_BASE, + TZROM_BASE + TZROM_SIZE, + BL1_COHERENT_RAM_BASE, + BL1_COHERENT_RAM_LIMIT); +} + +/******************************************************************************* + * Before calling this function BL2 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL2 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image, + entry_point_info_t *bl2_ep) +{ + SET_SECURITY_STATE(bl2_ep->h.attr, SECURE); + bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +} diff --git a/plat/juno/bl2_plat_setup.c b/plat/juno/bl2_plat_setup.c new file mode 100644 index 0000000000..0441cf6c7b --- /dev/null +++ b/plat/juno/bl2_plat_setup.c @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "juno_def.h" +#include "juno_private.h" +#include "scp_bootloader.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted RAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define BL2_RO_BASE (unsigned long)(&__RO_START__) +#define BL2_RO_LIMIT (unsigned long)(&__RO_END__) + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#define BL2_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL2_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +/* Data structure which holds the extents of the trusted RAM for BL2 */ +static meminfo_t bl2_tzram_layout +__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE), + section("tzfw_coherent_mem"))); + +/******************************************************************************* + * Structure which holds the arguments which need to be passed to BL3-1 + ******************************************************************************/ +static bl2_to_bl31_params_mem_t bl31_params_mem; + +meminfo_t *bl2_plat_sec_mem_layout(void) +{ + return &bl2_tzram_layout; +} + +/******************************************************************************* + * This function assigns a pointer to the memory that the platform has kept + * aside to pass platform specific and trusted firmware related information + * to BL31. This memory is allocated by allocating memory to + * bl2_to_bl31_params_mem_t structure which is a superset of all the + * structure whose information is passed to BL31 + * NOTE: This function should be called only once and should be done + * before generating params to BL31 + ******************************************************************************/ +bl31_params_t *bl2_plat_get_bl31_params(void) +{ + bl31_params_t *bl2_to_bl31_params; + + /* + * Initialise the memory for all the arguments that needs to + * be passed to BL3-1 + */ + memset(&bl31_params_mem, 0, sizeof(bl2_to_bl31_params_mem_t)); + + /* Assign memory for TF related information */ + bl2_to_bl31_params = &bl31_params_mem.bl31_params; + SET_PARAM_HEAD(bl2_to_bl31_params, PARAM_BL31, VERSION_1, 0); + + /* Fill BL3-1 related information */ + bl2_to_bl31_params->bl31_image_info = &bl31_params_mem.bl31_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); + + /* Fill BL3-2 related information if it exists */ +#if BL32_BASE + bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, + VERSION_1, 0); + bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); +#endif + + /* Fill BL3-3 related information */ + bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, + PARAM_EP, VERSION_1, 0); + + /* BL3-3 expects to receive the primary CPU MPID (through x0) */ + bl2_to_bl31_params->bl33_ep_info->args.arg0 = JUNO_PRIMARY_CPU; + + bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); + + return bl2_to_bl31_params; +} + +/******************************************************************************* + * This function returns a pointer to the shared memory that the platform + * has kept to point to entry point information of BL31 to BL2 + ******************************************************************************/ +struct entry_point_info *bl2_plat_get_bl31_ep_info(void) +{ +#if DEBUG + bl31_params_mem.bl31_ep_info.args.arg1 = JUNO_BL31_PLAT_PARAM_VAL; +#endif + + return &bl31_params_mem.bl31_ep_info; +} + +/******************************************************************************* + * BL1 has passed the extents of the trusted RAM that should be visible to BL2 + * in x0. This memory layout is sitting at the base of the free trusted RAM. + * Copy it to a safe loaction 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(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; +} + +/******************************************************************************* + * Perform platform specific setup, i.e. initialize the IO layer, load BL3-0 + * image and initialise the memory location to use for passing arguments to + * BL3-1. + ******************************************************************************/ +void bl2_platform_setup(void) +{ + /* Initialise the IO layer and register platform IO devices */ + io_setup(); +} + +/* Flush the TF params and the TF plat params */ +void bl2_plat_flush_bl31_params(void) +{ + flush_dcache_range((unsigned long)&bl31_params_mem, + sizeof(bl2_to_bl31_params_mem_t)); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl2_plat_arch_setup(void) +{ + configure_mmu_el1(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL2_RO_BASE, + BL2_RO_LIMIT, + BL2_COHERENT_RAM_BASE, + BL2_COHERENT_RAM_LIMIT); +} + +/******************************************************************************* + * Populate the extents of memory available for loading BL3-0, i.e. anywhere + * in trusted RAM as long as it doesn't overwrite BL2. + ******************************************************************************/ +void bl2_plat_get_bl30_meminfo(meminfo_t *bl30_meminfo) +{ + *bl30_meminfo = bl2_tzram_layout; +} + +/******************************************************************************* + * Transfer BL3-0 from Trusted RAM using the SCP Download protocol. + * Return 0 on success, -1 otherwise. + ******************************************************************************/ +int bl2_plat_handle_bl30(image_info_t *bl30_image_info) +{ + int ret; + + ret = scp_bootloader_transfer((void *)bl30_image_info->image_base, + bl30_image_info->image_size); + + if (ret == 0) + INFO("BL2: BL3-0 transferred to SCP\n\r"); + else + ERROR("BL2: BL3-0 transfer failure\n\r"); + + return ret; +} + +/******************************************************************************* + * Before calling this function BL31 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL31 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl2_plat_set_bl31_ep_info(image_info_t *bl31_image_info, + entry_point_info_t *bl31_ep_info) +{ + SET_SECURITY_STATE(bl31_ep_info->h.attr, SECURE); + bl31_ep_info->spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); +} + + +/******************************************************************************* + * Before calling this function BL32 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL32 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info, + entry_point_info_t *bl32_ep_info) +{ + SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE); + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + bl32_ep_info->spsr = 0; +} + +/******************************************************************************* + * Before calling this function BL33 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL33 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + ******************************************************************************/ +void bl2_plat_set_bl33_ep_info(image_info_t *image, + entry_point_info_t *bl33_ep_info) +{ + unsigned long el_status; + unsigned int mode; + + /* Figure out what mode we enter the non-secure world in */ + el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT; + el_status &= ID_AA64PFR0_ELX_MASK; + + if (el_status) + mode = MODE_EL2; + else + mode = MODE_EL1; + + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + bl33_ep_info->spsr = SPSR_64(mode, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + SET_SECURITY_STATE(bl33_ep_info->h.attr, NON_SECURE); +} + +/******************************************************************************* + * Populate the extents of memory available for loading BL3-2 + ******************************************************************************/ +void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) +{ + /* + * Populate the extents of memory available for loading BL3-2. + */ + bl32_meminfo->total_base = BL32_BASE; + bl32_meminfo->free_base = BL32_BASE; + bl32_meminfo->total_size = + (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; + bl32_meminfo->free_size = + (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; +} + + +/******************************************************************************* + * Populate the extents of memory available for loading BL3-3 + ******************************************************************************/ +void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo) +{ + bl33_meminfo->total_base = DRAM_BASE; + bl33_meminfo->total_size = DRAM_SIZE; + bl33_meminfo->free_base = DRAM_BASE; + bl33_meminfo->free_size = DRAM_SIZE; +} diff --git a/plat/juno/bl31_plat_setup.c b/plat/juno/bl31_plat_setup.c new file mode 100644 index 0000000000..131a1b1dd3 --- /dev/null +++ b/plat/juno/bl31_plat_setup.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "juno_def.h" +#include "juno_private.h" +#include "mhu.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted RAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define BL31_RO_BASE (unsigned long)(&__RO_START__) +#define BL31_RO_LIMIT (unsigned long)(&__RO_END__) + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols + * refer to page-aligned addresses. + */ +#define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +/****************************************************************************** + * Placeholder variables for copying the arguments that have been passed to + * BL3-1 from BL2. + ******************************************************************************/ +static entry_point_info_t bl32_ep_info; +static entry_point_info_t bl33_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL3-3 corresponds to the non-secure image type + * while BL3-2 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; + + next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info; + + /* None of the images on this platform can have 0x0 as the entrypoint */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} + +/******************************************************************************* + * Perform any BL3-1 specific platform actions. 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. Also, BL2 + * has flushed this information to memory, so we are guaranteed to pick up good + * data + ******************************************************************************/ +void bl31_early_platform_setup(bl31_params_t *from_bl2, + void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + console_init(PL011_UART0_BASE, PL011_UART0_CLK_IN_HZ, PL011_BAUDRATE); + + /* + * Initialise the CCI-400 driver for BL31 so that it is accessible after + * a warm boot. BL1 should have already enabled CCI coherency for this + * cluster during cold boot. + */ + cci_init(CCI400_BASE, + CCI400_SL_IFACE3_CLUSTER_IX, + CCI400_SL_IFACE4_CLUSTER_IX); + + /* + * Check params passed from BL2 should not be NULL, + */ + assert(from_bl2 != NULL); + assert(from_bl2->h.type == PARAM_BL31); + assert(from_bl2->h.version >= VERSION_1); + /* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL3-1. + * In release builds, it's not used. + */ + assert(((unsigned long long)plat_params_from_bl2) == + JUNO_BL31_PLAT_PARAM_VAL); + + /* + * Copy BL3-2 and BL3-3 entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + bl32_ep_info = *from_bl2->bl32_ep_info; + bl33_ep_info = *from_bl2->bl33_ep_info; +} + +/******************************************************************************* + * Initialize the MHU and the GIC. + ******************************************************************************/ +void bl31_platform_setup(void) +{ + unsigned int reg_val; + + mhu_secure_init(); + + /* Initialize the gic cpu and distributor interfaces */ + gic_setup(); + + /* Enable and initialize the System level generic timer */ + mmio_write_32(SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0) | CNTCR_EN); + + /* Allow access to the System counter timer module */ + reg_val = (1 << CNTACR_RPCT_SHIFT) | (1 << CNTACR_RVCT_SHIFT); + reg_val |= (1 << CNTACR_RFRQ_SHIFT) | (1 << CNTACR_RVOFF_SHIFT); + reg_val |= (1 << CNTACR_RWVT_SHIFT) | (1 << CNTACR_RWPT_SHIFT); + mmio_write_32(SYS_TIMCTL_BASE + CNTACR_BASE(1), reg_val); + + reg_val = (1 << CNTNSAR_NS_SHIFT(1)); + mmio_write_32(SYS_TIMCTL_BASE + CNTNSAR, reg_val); + + /* Topologies are best known to the platform. */ + plat_setup_topology(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + ******************************************************************************/ +void bl31_plat_arch_setup() +{ + configure_mmu_el3(BL31_RO_BASE, + BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE, + BL31_RO_BASE, + BL31_RO_LIMIT, + BL31_COHERENT_RAM_BASE, + BL31_COHERENT_RAM_LIMIT); +} diff --git a/plat/juno/include/plat_macros.S b/plat/juno/include/plat_macros.S new file mode 100644 index 0000000000..0e08834424 --- /dev/null +++ b/plat/juno/include/plat_macros.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "platform_def.h" +#include "../juno_def.h" + +.section .rodata.gic_reg_name, "aS" +gic_regs: + .asciz "gic_hppir", "gic_ahppir", "gic_ctlr", "" +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + + /* --------------------------------------------- + * The below macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x10, x16, sp + * --------------------------------------------- + */ + .macro plat_print_gic_regs + ldr x16, =GICC_BASE + /* Load the gic reg list to x6 */ + adr x6, gic_regs + /* Load the gic regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x16, #GICC_HPPIR] + ldr w9, [x16, #GICC_AHPPIR] + ldr w10, [x16, #GICC_CTLR] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +gicd_ispendr_loop: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq exit_print_gic_regs + bl asm_print_hex + + adr x4, spacer + bl asm_print_str + + ldr x4, [x7], #8 + bl asm_print_hex + + adr x4, newline + bl asm_print_str + b gicd_ispendr_loop +exit_print_gic_regs: + .endm + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below macro prints out relevant interconnect + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro plat_print_interconnect_regs + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI400_BASE + SLAVE_IFACE3_OFFSET) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI400_BASE + SLAVE_IFACE4_OFFSET) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + .endm diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h new file mode 100644 index 0000000000..2678efc2dd --- /dev/null +++ b/plat/juno/include/platform_def.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x800 + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +/* Trusted Boot Firmware BL2 */ +#define BL2_IMAGE_NAME "bl2.bin" + +/* EL3 Runtime Firmware BL3-1 */ +#define BL31_IMAGE_NAME "bl31.bin" + +/* SCP Firmware BL3-0 */ +#define BL30_IMAGE_NAME "bl30.bin" + +/* Secure Payload BL3-2 (Trusted OS) */ +#define BL32_IMAGE_NAME "bl32.bin" + +/* Non-Trusted Firmware BL3-3 */ +#define BL33_IMAGE_NAME "bl33.bin" /* e.g. UEFI */ + +/* Firmware Image Package */ +#define FIP_IMAGE_NAME "fip.bin" + +#define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_CLUSTER_COUNT 2 +#define PLATFORM_CORE_COUNT 6 +#define PLATFORM_NUM_AFFS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +#define FLASH_BASE 0x08000000 +#define FLASH_SIZE 0x04000000 + +/* Bypass offset from start of NOR flash */ +#define BL1_ROM_BYPASS_OFFSET 0x03EC0000 + +#ifndef TZROM_BASE +/* Use the bypass address */ +#define TZROM_BASE FLASH_BASE + BL1_ROM_BYPASS_OFFSET +#endif +#define TZROM_SIZE 0x00010000 + +#define TZRAM_BASE 0x04001000 +#define TZRAM_SIZE 0x0003F000 + +/******************************************************************************* + * BL1 specific defines. + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 base + * addresses. + ******************************************************************************/ +#define BL1_RO_BASE TZROM_BASE +#define BL1_RO_LIMIT (TZROM_BASE + TZROM_SIZE) +#define BL1_RW_BASE TZRAM_BASE +#define BL1_RW_LIMIT BL31_BASE + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +#define BL2_BASE (TZRAM_BASE + TZRAM_SIZE - 0xd000) +#define BL2_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Load address of BL3-0 in the Juno port + * BL3-0 is loaded to the same place as BL3-1. Once BL3-0 is transferred to the + * SCP, it is discarded and BL3-1 is loaded over the top. + ******************************************************************************/ +#define BL30_BASE BL31_BASE + +/******************************************************************************* + * BL3-1 specific defines. + ******************************************************************************/ +#define BL31_BASE (TZRAM_BASE + 0x8000) +#define BL31_LIMIT BL32_BASE + +/******************************************************************************* + * BL3-2 specific defines. + ******************************************************************************/ +#define TSP_SEC_MEM_BASE TZRAM_BASE +#define TSP_SEC_MEM_SIZE TZRAM_SIZE +#define BL32_BASE (TZRAM_BASE + TZRAM_SIZE - 0x1d000) +#define BL32_LIMIT BL2_BASE + +/******************************************************************************* + * Load address of BL3-3 in the Juno port + ******************************************************************************/ +#define NS_IMAGE_OFFSET 0xE0000000 + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define ADDR_SPACE_SIZE (1ull << 32) +#define MAX_XLAT_TABLES 2 +#define MAX_MMAP_REGIONS 16 + +/******************************************************************************* + * ID of the secure physical generic timer interrupt. + ******************************************************************************/ +#define IRQ_SEC_PHY_TIMER 29 + +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * 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. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h new file mode 100644 index 0000000000..b099e97687 --- /dev/null +++ b/plat/juno/juno_def.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __JUNO_DEF_H__ +#define __JUNO_DEF_H__ + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define JUNO_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define JUNO_PRIMARY_CPU 0x100 + +/******************************************************************************* + * Juno memory map related constants + ******************************************************************************/ +#define MHU_SECURE_BASE 0x04000000 +#define MHU_SECURE_SIZE 0x00001000 + +#define MHU_PAYLOAD_CACHED 0 + +#define TRUSTED_MAILBOXES_BASE MHU_SECURE_BASE +#define TRUSTED_MAILBOX_SHIFT 4 + +#define EMMC_BASE 0x0c000000 +#define EMMC_SIZE 0x04000000 + +#define PSRAM_BASE 0x14000000 +#define PSRAM_SIZE 0x02000000 + +#define IOFPGA_BASE 0x1c000000 +#define IOFPGA_SIZE 0x03000000 + +#define NSROM_BASE 0x1f000000 +#define NSROM_SIZE 0x00001000 + +/* Following covers Columbus Peripherals excluding NSROM and NSRAM */ +#define DEVICE0_BASE 0x20000000 +#define DEVICE0_SIZE 0x0e000000 +#define MHU_BASE 0x2b1f0000 + +#define NSRAM_BASE 0x2e000000 +#define NSRAM_SIZE 0x00008000 + +/* Following covers Juno Peripherals and PCIe expansion area */ +#define DEVICE1_BASE 0x40000000 +#define DEVICE1_SIZE 0x40000000 +#define PCIE_CONTROL_BASE 0x7ff20000 + +#define DRAM_BASE 0x80000000 +#define DRAM_SIZE 0x80000000 + +/* Memory mapped Generic timer interfaces */ +#define SYS_CNTCTL_BASE 0x2a430000 +#define SYS_CNTREAD_BASE 0x2a800000 +#define SYS_TIMCTL_BASE 0x2a810000 + +/* V2M motherboard system registers & offsets */ +#define VE_SYSREGS_BASE 0x1c010000 +#define V2M_SYS_LED 0x8 + +/* + * V2M sysled bit definitions. The values written to this + * register are defined in arch.h & runtime_svc.h. Only + * used by the primary cpu to diagnose any cold boot issues. + * + * SYS_LED[0] - Security state (S=0/NS=1) + * SYS_LED[2:1] - Exception Level (EL3-EL0) + * SYS_LED[7:3] - Exception Class (Sync/Async & origin) + * + */ +#define SYS_LED_SS_SHIFT 0x0 +#define SYS_LED_EL_SHIFT 0x1 +#define SYS_LED_EC_SHIFT 0x3 + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ +#define GICD_BASE 0x2c010000 +#define GICC_BASE 0x2c02f000 +#define GICH_BASE 0x2c04f000 +#define GICV_BASE 0x2c06f000 + +#define IRQ_MHU 69 +#define IRQ_GPU_SMMU_0 71 +#define IRQ_GPU_SMMU_1 73 +#define IRQ_ETR_SMMU 75 +#define IRQ_TZC400 80 +#define IRQ_TZ_WDOG 86 + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 +#define IRQ_SEC_SGI_8 16 + +/******************************************************************************* + * PL011 related constants + ******************************************************************************/ +/* FPGA UART0 */ +#define PL011_UART0_BASE 0x1c090000 +/* FPGA UART1 */ +#define PL011_UART1_BASE 0x1c0a0000 +/* SoC UART0 */ +#define PL011_UART2_BASE 0x7ff80000 +/* SoC UART1 */ +#define PL011_UART3_BASE 0x7ff70000 + +#define PL011_BAUDRATE 115200 + +#define PL011_UART0_CLK_IN_HZ 24000000 +#define PL011_UART1_CLK_IN_HZ 24000000 + +/******************************************************************************* + * NIC-400 related constants + ******************************************************************************/ + +/* CSS NIC-400 Global Programmers View (GPV) */ +#define CSS_NIC400_BASE 0x2a000000 + +/* The slave_bootsecure controls access to GPU, DMC and CS. */ +#define CSS_NIC400_SLAVE_BOOTSECURE 8 + +/* SoC NIC-400 Global Programmers View (GPV) */ +#define SOC_NIC400_BASE 0x7fd00000 + +#define SOC_NIC400_USB_EHCI 0 +#define SOC_NIC400_TLX_MASTER 1 +#define SOC_NIC400_USB_OHCI 2 +#define SOC_NIC400_PL354_SMC 3 +/* + * The apb4_bridge controls access to: + * - the PCIe configuration registers + * - the MMU units for USB, HDLCD and DMA + */ +#define SOC_NIC400_APB4_BRIDGE 4 +/* + * The bootsec_bridge controls access to a bunch of peripherals, e.g. the UARTs. + */ +#define SOC_NIC400_BOOTSEC_BRIDGE 5 +#define SOC_NIC400_BOOTSEC_BRIDGE_UART1 (1 << 12) + +/******************************************************************************* + * TZC-400 related constants + ******************************************************************************/ +#define TZC400_BASE 0x2a4a0000 + +#define TZC400_NSAID_CCI400 0 /* Note: Same as default NSAID!! */ +#define TZC400_NSAID_PCIE 1 +#define TZC400_NSAID_HDLCD0 2 +#define TZC400_NSAID_HDLCD1 3 +#define TZC400_NSAID_USB 4 +#define TZC400_NSAID_DMA330 5 +#define TZC400_NSAID_THINLINKS 6 +#define TZC400_NSAID_AP 9 +#define TZC400_NSAID_GPU 10 +#define TZC400_NSAID_SCP 11 +#define TZC400_NSAID_CORESIGHT 12 + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define CCI400_BASE 0x2c090000 +#define CCI400_SL_IFACE3_CLUSTER_IX 1 +#define CCI400_SL_IFACE4_CLUSTER_IX 0 + +#endif /* __JUNO_DEF_H__ */ diff --git a/plat/juno/juno_private.h b/plat/juno/juno_private.h new file mode 100644 index 0000000000..0dac03a9df --- /dev/null +++ b/plat/juno/juno_private.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __JUNO_PRIVATE_H__ +#define __JUNO_PRIVATE_H__ + +#include +#include +#include + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct plat_pm_ops; +struct meminfo; +struct bl31_params; +struct image_info; +struct entry_point_info; + +/******************************************************************************* + * This structure represents the superset of information that is passed to + * BL3-1 e.g. while passing control to it from BL2 which is bl31_params + * and other platform specific params + ******************************************************************************/ +typedef struct bl2_to_bl31_params_mem { + struct bl31_params bl31_params; + struct image_info bl31_image_info; + struct image_info bl32_image_info; + struct image_info bl33_image_info; + struct entry_point_info bl33_ep_info; + struct entry_point_info bl32_ep_info; + struct entry_point_info bl31_ep_info; +} bl2_to_bl31_params_mem_t; + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +void bl1_plat_arch_setup(void); +void bl2_plat_arch_setup(void); +void bl31_plat_arch_setup(void); +int platform_setup_pm(const struct plat_pm_ops **plat_ops); +unsigned int platform_get_core_pos(unsigned long mpidr); +void configure_mmu_el1(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void configure_mmu_el3(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit, + unsigned long coh_start, + unsigned long coh_limit); +void plat_report_exception(unsigned long type); +unsigned long plat_get_ns_image_entrypoint(void); +unsigned long platform_get_stack(unsigned long mpidr); +uint64_t plat_get_syscnt_freq(void); + +/* Declarations for plat_gic.c */ +uint32_t ic_get_pending_interrupt_id(void); +uint32_t ic_get_pending_interrupt_type(void); +uint32_t ic_acknowledge_interrupt(void); +uint32_t ic_get_interrupt_type(uint32_t id); +void ic_end_of_interrupt(uint32_t id); +void gic_cpuif_deactivate(unsigned int gicc_base); +void gic_cpuif_setup(unsigned int gicc_base); +void gic_pcpu_distif_setup(unsigned int gicd_base); +void gic_setup(void); +uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state); + +/* Declarations for plat_topology.c */ +int plat_setup_topology(void); +int plat_get_max_afflvl(void); +unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr); +unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr); + +/* Declarations for plat_io_storage.c */ +void io_setup(void); +int plat_get_image_source(const char *image_name, + uintptr_t *dev_handle, + uintptr_t *image_spec); + +/* + * Before calling this function BL2 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL2 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + */ +void bl1_plat_set_bl2_ep_info(struct image_info *image, + struct entry_point_info *ep); + +/* + * Before calling this function BL3-1 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL3-1 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + */ +void bl2_plat_set_bl31_ep_info(struct image_info *image, + struct entry_point_info *ep); + +/* + * Before calling this function BL3-2 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL3-2 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + */ +void bl2_plat_set_bl32_ep_info(struct image_info *image, + struct entry_point_info *ep); + +/* + * Before calling this function BL3-3 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL3-3 and set SPSR and security state. + * On Juno we are only setting the security state, entrypoint + */ +void bl2_plat_set_bl33_ep_info(struct image_info *image, + struct entry_point_info *ep); + +/* Gets the memory layout for BL3-2 */ +void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info); + +/* Gets the memory layout for BL3-3 */ +void bl2_plat_get_bl33_meminfo(struct meminfo *mem_info); + +#endif /* __JUNO_PRIVATE_H__ */ diff --git a/plat/juno/mhu.c b/plat/juno/mhu.c new file mode 100644 index 0000000000..b6541a8873 --- /dev/null +++ b/plat/juno/mhu.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "juno_def.h" +#include "mhu.h" + +/* SCP MHU secure channel registers */ +#define SCP_INTR_S_STAT 0x200 +#define SCP_INTR_S_SET 0x208 +#define SCP_INTR_S_CLEAR 0x210 + +/* CPU MHU secure channel registers */ +#define CPU_INTR_S_STAT 0x300 +#define CPU_INTR_S_SET 0x308 +#define CPU_INTR_S_CLEAR 0x310 + + +static bakery_lock_t mhu_secure_lock __attribute__ ((section("tzfw_coherent_mem"))); + + +void mhu_secure_message_start(void) +{ + bakery_lock_get(&mhu_secure_lock); + + /* Make sure any previous command has finished */ + while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0) + ; +} + +void mhu_secure_message_send(uint32_t command) +{ + /* Send command to SCP and wait for it to pick it up */ + mmio_write_32(MHU_BASE + CPU_INTR_S_SET, command); + while (mmio_read_32(MHU_BASE + CPU_INTR_S_STAT) != 0) + ; +} + +uint32_t mhu_secure_message_wait(void) +{ + /* Wait for response from SCP */ + uint32_t response; + while (!(response = mmio_read_32(MHU_BASE + SCP_INTR_S_STAT))) + ; + + return response; +} + +void mhu_secure_message_end(void) +{ + /* Clear any response we got by writing all ones to the CLEAR register */ + mmio_write_32(MHU_BASE + SCP_INTR_S_CLEAR, 0xffffffffu); + + bakery_lock_release(&mhu_secure_lock); +} + +void mhu_secure_init(void) +{ + bakery_lock_init(&mhu_secure_lock); + + /* + * Clear the CPU's INTR register to make sure we don't see a stale + * or garbage value and think it's a message we've already sent. + */ + mmio_write_32(MHU_BASE + CPU_INTR_S_CLEAR, 0xffffffffu); +} diff --git a/plat/juno/mhu.h b/plat/juno/mhu.h new file mode 100644 index 0000000000..5149c82db8 --- /dev/null +++ b/plat/juno/mhu.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MHU_H__ +#define __MHU_H__ + +#include + +extern void mhu_secure_message_start(void); +extern void mhu_secure_message_send(uint32_t command); +extern uint32_t mhu_secure_message_wait(void); +extern void mhu_secure_message_end(void); + +extern void mhu_secure_init(void); + +#endif /* __MHU_H__ */ diff --git a/plat/juno/plat_gic.c b/plat/juno/plat_gic.c new file mode 100644 index 0000000000..9001519be1 --- /dev/null +++ b/plat/juno/plat_gic.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include "juno_def.h" +#include "juno_private.h" + + +/* Value used to initialise Non-Secure irq priorities four at a time */ +#define DEFAULT_NS_PRIORITY_X4 \ + (GIC_HIGHEST_NS_PRIORITY | \ + (GIC_HIGHEST_NS_PRIORITY << 8) | \ + (GIC_HIGHEST_NS_PRIORITY << 16) | \ + (GIC_HIGHEST_NS_PRIORITY << 24)) + + +/******************************************************************************* + * Enable secure interrupts and use FIQs to route them. Disable legacy bypass + * and set the priority mask register to allow all interrupts to trickle in. + ******************************************************************************/ +void gic_cpuif_setup(unsigned int gicc_base) +{ + unsigned int val; + + gicc_write_pmr(gicc_base, GIC_PRI_MASK); + + val = ENABLE_GRP0 | FIQ_EN; + val |= FIQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP0; + val |= FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1; + gicc_write_ctlr(gicc_base, val); +} + +/******************************************************************************* + * Place the cpu interface in a state where it can never make a cpu exit wfi as + * as result of an asserted interrupt. This is critical for powering down a cpu + ******************************************************************************/ +void gic_cpuif_deactivate(unsigned int gicc_base) +{ + unsigned int val; + + /* Disable secure, non-secure interrupts and disable their bypass */ + val = gicc_read_ctlr(gicc_base); + val &= ~(ENABLE_GRP0 | ENABLE_GRP1); + val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0; + val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1; + gicc_write_ctlr(gicc_base, val); +} + +static void gic_set_secure(unsigned int gicd_base, unsigned id) +{ + /* Set interrupt as Group 0 */ + gicd_clr_igroupr(gicd_base, id); + + /* Set priority to max */ + gicd_set_ipriorityr(gicd_base, id, GIC_HIGHEST_SEC_PRIORITY); +} + +/******************************************************************************* + * Per cpu gic distributor setup which will be done by all cpus after a cold + * boot/hotplug. This marks out the secure interrupts & enables them. + ******************************************************************************/ +void gic_pcpu_distif_setup(unsigned int gicd_base) +{ + unsigned i; + + /* Mark all 32 PPI interrupts as Group 1 (non-secure) */ + mmio_write_32(gicd_base + GICD_IGROUPR, 0xffffffffu); + + /* Setup PPI priorities doing four at a time */ + for (i = 0; i < 32; i += 4) + mmio_write_32(gicd_base + GICD_IPRIORITYR + i, DEFAULT_NS_PRIORITY_X4); + + /* Configure those PPIs we want as secure, and enable them. */ + static const char sec_irq[] = { + IRQ_SEC_PHY_TIMER, + IRQ_SEC_SGI_0, + IRQ_SEC_SGI_1, + IRQ_SEC_SGI_2, + IRQ_SEC_SGI_3, + IRQ_SEC_SGI_4, + IRQ_SEC_SGI_5, + IRQ_SEC_SGI_6, + IRQ_SEC_SGI_7 + }; + for (i = 0; i < sizeof(sec_irq) / sizeof(sec_irq[0]); i++) { + gic_set_secure(gicd_base, sec_irq[i]); + gicd_set_isenabler(gicd_base, sec_irq[i]); + } +} + +/******************************************************************************* + * Global gic distributor setup which will be done by the primary cpu after a + * cold boot. It marks out the secure SPIs, PPIs & SGIs and enables them. It + * then enables the secure GIC distributor interface. + ******************************************************************************/ +static void gic_distif_setup(unsigned int gicd_base) +{ + unsigned int i, ctlr; + const unsigned int ITLinesNumber = + gicd_read_typer(gicd_base) & IT_LINES_NO_MASK; + + /* Disable the distributor before going further */ + ctlr = gicd_read_ctlr(gicd_base); + ctlr &= ~(ENABLE_GRP0 | ENABLE_GRP1); + gicd_write_ctlr(gicd_base, ctlr); + + /* Mark all lines of SPIs as Group 1 (non-secure) */ + for (i = 0; i < ITLinesNumber; i++) + mmio_write_32(gicd_base + GICD_IGROUPR + 4 + i * 4, 0xffffffffu); + + /* Setup SPI priorities doing four at a time */ + for (i = 0; i < ITLinesNumber * 32; i += 4) + mmio_write_32(gicd_base + GICD_IPRIORITYR + 32 + i, DEFAULT_NS_PRIORITY_X4); + + /* Configure the SPIs we want as secure */ + static const char sec_irq[] = { + IRQ_MHU, + IRQ_GPU_SMMU_0, + IRQ_GPU_SMMU_1, + IRQ_ETR_SMMU, + IRQ_TZC400, + IRQ_TZ_WDOG + }; + for (i = 0; i < sizeof(sec_irq) / sizeof(sec_irq[0]); i++) + gic_set_secure(gicd_base, sec_irq[i]); + + /* Route watchdog interrupt to this CPU and enable it. */ + gicd_set_itargetsr(gicd_base, IRQ_TZ_WDOG, + platform_get_core_pos(read_mpidr())); + gicd_set_isenabler(gicd_base, IRQ_TZ_WDOG); + + /* Now setup the PPIs */ + gic_pcpu_distif_setup(gicd_base); + + /* Enable Group 0 (secure) interrupts */ + gicd_write_ctlr(gicd_base, ctlr | ENABLE_GRP0); +} + +void gic_setup(void) +{ + gic_cpuif_setup(GICC_BASE); + gic_distif_setup(GICD_BASE); +} + +/******************************************************************************* + * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. + * The interrupt controller knows which pin/line it uses to signal a type of + * interrupt. The platform knows which interrupt controller type is being used + * in a particular security state e.g. with an ARM GIC, normal world could use + * the GICv2 features while the secure world could use GICv3 features and vice + * versa. + * This function is exported by the platform to let the interrupt management + * framework determine for a type of interrupt and security state, which line + * should be used in the SCR_EL3 to control its routing to EL3. The interrupt + * line is represented as the bit position of the IRQ or FIQ bit in the SCR_EL3. + ******************************************************************************/ +uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state) +{ + assert(type == INTR_TYPE_S_EL1 || + type == INTR_TYPE_EL3 || + type == INTR_TYPE_NS); + + assert(sec_state_is_valid(security_state)); + + /* + * We ignore the security state parameter because Juno is GICv2 only + * so both normal and secure worlds are using ARM GICv2. + */ + return gicv2_interrupt_type_to_line(GICC_BASE, type); +} + +/******************************************************************************* + * This function returns the type of the highest priority pending interrupt at + * the GIC cpu interface. INTR_TYPE_INVAL is returned when there is no + * interrupt pending. + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + uint32_t id; + + id = gicc_read_hppir(GICC_BASE); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (id < 1022) + return INTR_TYPE_S_EL1; + + if (id == GIC_SPURIOUS_INTERRUPT) + return INTR_TYPE_INVAL; + + return INTR_TYPE_NS; +} + +/******************************************************************************* + * This function returns the id of the highest priority pending interrupt at + * the GIC cpu interface. INTR_ID_UNAVAILABLE is returned when there is no + * interrupt pending. + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_id(void) +{ + uint32_t id; + + id = gicc_read_hppir(GICC_BASE); + + if (id < 1022) + return id; + + if (id == 1023) + return INTR_ID_UNAVAILABLE; + + /* + * Find out which non-secure interrupt it is under the assumption that + * the GICC_CTLR.AckCtl bit is 0. + */ + return gicc_read_ahppir(GICC_BASE); +} + +/******************************************************************************* + * This functions reads the GIC cpu interface Interrupt Acknowledge register + * to start handling the pending interrupt. It returns the contents of the IAR. + ******************************************************************************/ +uint32_t plat_ic_acknowledge_interrupt(void) +{ + return gicc_read_IAR(GICC_BASE); +} + +/******************************************************************************* + * This functions writes the GIC cpu interface End Of Interrupt register with + * the passed value to finish handling the active interrupt + ******************************************************************************/ +void plat_ic_end_of_interrupt(uint32_t id) +{ + gicc_write_EOIR(GICC_BASE, id); +} + +/******************************************************************************* + * This function returns the type of the interrupt id depending upon the group + * this interrupt has been configured under by the interrupt controller i.e. + * group0 or group1. + ******************************************************************************/ +uint32_t plat_ic_get_interrupt_type(uint32_t id) +{ + uint32_t group; + + group = gicd_get_igroupr(GICD_BASE, id); + + /* Assume that all secure interrupts are S-EL1 interrupts */ + if (group == GRP0) + return INTR_TYPE_S_EL1; + else + return INTR_TYPE_NS; +} diff --git a/plat/juno/plat_io_storage.c b/plat/juno/plat_io_storage.c new file mode 100644 index 0000000000..b2974007c1 --- /dev/null +++ b/plat/juno/plat_io_storage.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* For FOPEN_MODE_... */ +#include + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_spec; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_spec; +static uintptr_t memmap_init_params; +static uintptr_t memmap_dev_handle; + +static const io_block_spec_t fip_block_spec = { + .offset = FLASH_BASE, + .length = FLASH_SIZE +}; + +static const io_file_spec_t bl2_file_spec = { + .path = BL2_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static const io_file_spec_t bl30_file_spec = { + .path = BL30_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static const io_file_spec_t bl31_file_spec = { + .path = BL31_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static const io_file_spec_t bl33_file_spec = { + .path = BL33_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); + +struct plat_io_policy { + const char *image_name; + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy policies[] = { + { + FIP_IMAGE_NAME, + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, { + BL2_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl2_file_spec, + open_fip + }, { + BL30_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl30_file_spec, + open_fip + }, { + BL31_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl31_file_spec, + open_fip + }, { + BL33_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl33_file_spec, + open_fip + }, { + 0, 0, 0 + } +}; + + +static int open_fip(const uintptr_t spec) +{ + int result = IO_FAIL; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_NAME); + if (result == IO_SUCCESS) { + INFO("Using FIP\n"); + /*TODO: Check image defined in spec is present in FIP. */ + } + return result; +} + + +static int open_memmap(const uintptr_t spec) +{ + int result = IO_FAIL; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, memmap_init_params); + if (result == IO_SUCCESS) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == IO_SUCCESS) { + /* INFO("Using Memmap IO\n"); */ + io_close(local_image_handle); + } + } + return result; +} + +void io_setup(void) +{ + int io_result = IO_FAIL; + + /* Register the IO devices on this platform */ + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == IO_SUCCESS); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == IO_SUCCESS); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle); + assert(io_result == IO_SUCCESS); + + io_result = io_dev_open(memmap_dev_con, memmap_dev_spec, + &memmap_dev_handle); + assert(io_result == IO_SUCCESS); + + /* 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(const char *image_name, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result = IO_FAIL; + const struct plat_io_policy *policy; + + if ((image_name != NULL) && (dev_handle != NULL) && + (image_spec != NULL)) { + policy = policies; + while (policy->image_name != NULL) { + if (strcmp(policy->image_name, image_name) == 0) { + result = policy->check(policy->image_spec); + if (result == IO_SUCCESS) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + break; + } + } + policy++; + } + } else { + result = IO_FAIL; + } + return result; +} diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c new file mode 100644 index 0000000000..61dc13e8bd --- /dev/null +++ b/plat/juno/plat_pm.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "juno_def.h" +#include "juno_private.h" +#include "scpi.h" + +/******************************************************************************* + * Private Juno function to program the mailbox for a cpu before it is released + * from reset. + ******************************************************************************/ +static void juno_program_mailbox(uint64_t mpidr, uint64_t address) +{ + uint64_t linear_id; + uint64_t mbox; + + linear_id = platform_get_core_pos(mpidr); + mbox = TRUSTED_MAILBOXES_BASE + (linear_id << TRUSTED_MAILBOX_SHIFT); + *((uint64_t *) mbox) = address; + flush_dcache_range(mbox, sizeof(mbox)); +} + +/******************************************************************************* + * Private Juno function which is used to determine if any platform actions + * should be performed for the specified affinity instance given its + * state. Nothing needs to be done if the 'state' is not off or if this is not + * the highest affinity level which will enter the 'state'. + ******************************************************************************/ +static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state) +{ + uint32_t max_phys_off_afflvl; + + assert(afflvl <= MPIDR_AFFLVL1); + + if (state != PSCI_STATE_OFF) + return -EAGAIN; + + /* + * Find the highest affinity level which will be suspended and postpone + * all the platform specific actions until that level is hit. + */ + max_phys_off_afflvl = psci_get_max_phys_off_afflvl(); + assert(max_phys_off_afflvl != PSCI_INVALID_DATA); + assert(psci_get_suspend_afflvl() >= max_phys_off_afflvl); + if (afflvl != max_phys_off_afflvl) + return -EAGAIN; + + return 0; +} + +/******************************************************************************* + * Juno handler called when an affinity instance is about to be turned on. The + * level and mpidr determine the affinity instance. + ******************************************************************************/ +int32_t juno_on(uint64_t mpidr, + uint64_t sec_entrypoint, + uint64_t ns_entrypoint, + uint32_t afflvl, + uint32_t state) +{ + /* + * SCP takes care of powering up higher affinity levels so we + * only need to care about level 0 + */ + if (afflvl != MPIDR_AFFLVL0) + return PSCI_E_SUCCESS; + + /* + * Setup mailbox with address for CPU entrypoint when it next powers up + */ + juno_program_mailbox(mpidr, sec_entrypoint); + + scpi_set_css_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Juno handler called when an affinity instance has just been powered on after + * being turned off earlier. The level and mpidr determine the affinity + * instance. The 'state' arg. allows the platform to decide whether the cluster + * was turned off prior to wakeup and do what's necessary to setup it up + * correctly. + ******************************************************************************/ +int32_t juno_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state) +{ + /* Determine if any platform actions need to be executed. */ + if (juno_do_plat_actions(afflvl, state) == -EAGAIN) + return PSCI_E_SUCCESS; + + /* + * Perform the common cluster specific operations i.e enable coherency + * if this cluster was off. + */ + if (afflvl != MPIDR_AFFLVL0) + cci_enable_cluster_coherency(mpidr); + + + /* Enable the gic cpu interface */ + gic_cpuif_setup(GICC_BASE); + + /* Juno todo: Is this setup only needed after a cold boot? */ + gic_pcpu_distif_setup(GICD_BASE); + + /* Clear the mailbox for this cpu. */ + juno_program_mailbox(mpidr, 0); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static const plat_pm_ops_t juno_ops = { + .affinst_on = juno_on, + .affinst_on_finish = juno_on_finish, +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int32_t platform_setup_pm(const plat_pm_ops_t **plat_ops) +{ + *plat_ops = &juno_ops; + return 0; +} diff --git a/plat/juno/plat_topology.c b/plat/juno/plat_topology.c new file mode 100644 index 0000000000..39d4dabc65 --- /dev/null +++ b/plat/juno/plat_topology.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr) +{ + /* Report 1 (absent) instance at levels higher that the cluster level */ + if (aff_lvl > MPIDR_AFFLVL1) + return 1; + + if (aff_lvl == MPIDR_AFFLVL1) + return 2; /* We have two clusters */ + + return mpidr & 0x100 ? 4 : 2; /* 4 cpus in cluster 1, 2 in cluster 0 */ +} + +unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr) +{ + return aff_lvl <= MPIDR_AFFLVL1 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT; +} + +int plat_get_max_afflvl() +{ + return MPIDR_AFFLVL1; +} + +int plat_setup_topology() +{ + /* Juno todo: Make topology configurable via SCC */ + return 0; +} diff --git a/plat/juno/platform.mk b/plat/juno/platform.mk new file mode 100644 index 0000000000..47465360db --- /dev/null +++ b/plat/juno/platform.mk @@ -0,0 +1,82 @@ +# +# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +PLAT_INCLUDES := -Iplat/juno/include/ + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/pl011_console.S \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + lib/aarch64/xlat_tables.c \ + plat/common/aarch64/plat_common.c \ + plat/juno/plat_io_storage.c + +BL1_SOURCES += drivers/arm/cci400/cci400.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + plat/common/aarch64/platform_up_stack.S \ + plat/juno/bl1_plat_setup.c \ + plat/juno/aarch64/bl1_plat_helpers.S \ + plat/juno/aarch64/plat_helpers.S \ + plat/juno/aarch64/juno_common.c + +BL2_SOURCES += lib/locks/bakery/bakery_lock.c \ + plat/common/aarch64/platform_up_stack.S \ + plat/juno/bl2_plat_setup.c \ + plat/juno/mhu.c \ + plat/juno/aarch64/plat_helpers.S \ + plat/juno/aarch64/juno_common.c \ + plat/juno/scp_bootloader.c \ + plat/juno/scpi.c + +BL31_SOURCES += drivers/arm/cci400/cci400.c \ + drivers/arm/gic/gic_v2.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + plat/common/aarch64/platform_mp_stack.S \ + plat/juno/bl31_plat_setup.c \ + plat/juno/mhu.c \ + plat/juno/aarch64/plat_helpers.S \ + plat/juno/aarch64/juno_common.c \ + plat/juno/plat_pm.c \ + plat/juno/plat_topology.c \ + plat/juno/plat_gic.c \ + plat/juno/scpi.c + +ifneq (${RESET_TO_BL31},0) + $(error "Using BL3-1 as the reset vector is not supported on Juno. \ + Please set RESET_TO_BL31 to 0.") +endif + +NEED_BL30 := yes + +# Enable workarounds for selected Cortex-A57 erratas. +ERRATA_A57_806969 := 1 +ERRATA_A57_813420 := 1 diff --git a/plat/juno/scp_bootloader.c b/plat/juno/scp_bootloader.c new file mode 100644 index 0000000000..a6d25d49bf --- /dev/null +++ b/plat/juno/scp_bootloader.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "juno_def.h" +#include "mhu.h" +#include "scp_bootloader.h" +#include "scpi.h" + +/* Boot commands sent from AP -> SCP */ +#define BOOT_CMD_START 0x01 +#define BOOT_CMD_DATA 0x02 + +typedef struct { + uint32_t image_size; +} cmd_start_payload; + +typedef struct { + uint32_t sequence_num; + uint32_t offset; + uint32_t size; +} cmd_data_payload; + +#define BOOT_DATA_MAX_SIZE 0x1000 + +/* Boot commands sent from SCP -> AP */ +#define BOOT_CMD_ACK 0x03 +#define BOOT_CMD_NACK 0x04 + +typedef struct { + uint32_t sequence_num; +} cmd_ack_payload; + +/* + * Unlike the runtime protocol, the boot protocol uses the same memory region + * for both AP -> SCP and SCP -> AP transfers; define the address of this... + */ +static void * const cmd_payload = (void *)(MHU_SECURE_BASE + 0x0080); + +static void *scp_boot_message_start(void) +{ + mhu_secure_message_start(); + + return cmd_payload; +} + +static void scp_boot_message_send(unsigned command, size_t size) +{ + /* Make sure payload can be seen by SCP */ + if (MHU_PAYLOAD_CACHED) + flush_dcache_range((unsigned long)cmd_payload, size); + + /* Send command to SCP */ + mhu_secure_message_send(command | (size << 8)); +} + +static uint32_t scp_boot_message_wait(size_t size) +{ + uint32_t response = mhu_secure_message_wait(); + + /* Make sure we see the reply from the SCP and not any stale data */ + if (MHU_PAYLOAD_CACHED) + inv_dcache_range((unsigned long)cmd_payload, size); + + return response & 0xff; +} + +static void scp_boot_message_end(void) +{ + mhu_secure_message_end(); +} + +static int transfer_block(uint32_t sequence_num, uint32_t offset, uint32_t size) +{ + cmd_data_payload *cmd_data = scp_boot_message_start(); + cmd_data->sequence_num = sequence_num; + cmd_data->offset = offset; + cmd_data->size = size; + + scp_boot_message_send(BOOT_CMD_DATA, sizeof(*cmd_data)); + + cmd_ack_payload *cmd_ack = cmd_payload; + int ok = scp_boot_message_wait(sizeof(*cmd_ack)) == BOOT_CMD_ACK + && cmd_ack->sequence_num == sequence_num; + + scp_boot_message_end(); + + return ok; +} + +int scp_bootloader_transfer(void *image, unsigned int image_size) +{ + uintptr_t offset = (uintptr_t)image - MHU_SECURE_BASE; + uintptr_t end = offset + image_size; + uint32_t response; + + mhu_secure_init(); + + /* Initiate communications with SCP */ + do { + cmd_start_payload *cmd_start = scp_boot_message_start(); + cmd_start->image_size = image_size; + + scp_boot_message_send(BOOT_CMD_START, sizeof(*cmd_start)); + + response = scp_boot_message_wait(0); + + scp_boot_message_end(); + } while (response != BOOT_CMD_ACK); + + /* Transfer image to SCP a block at a time */ + uint32_t sequence_num = 1; + size_t size; + while ((size = end - offset) != 0) { + if (size > BOOT_DATA_MAX_SIZE) + size = BOOT_DATA_MAX_SIZE; + while (!transfer_block(sequence_num, offset, size)) + ; /* Retry forever */ + offset += size; + sequence_num++; + } + + /* Wait for SCP to signal it's ready */ + return scpi_wait_ready(); +} diff --git a/plat/juno/scp_bootloader.h b/plat/juno/scp_bootloader.h new file mode 100644 index 0000000000..e872513da1 --- /dev/null +++ b/plat/juno/scp_bootloader.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCP_BOOTLOADER_H__ +#define __SCP_BOOTLOADER_H__ + +int scp_bootloader_transfer(void *image, unsigned int image_size); + +#endif diff --git a/plat/juno/scpi.c b/plat/juno/scpi.c new file mode 100644 index 0000000000..c1677aae31 --- /dev/null +++ b/plat/juno/scpi.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "juno_def.h" +#include "mhu.h" +#include "scpi.h" + +#define MHU_SECURE_SCP_TO_AP_PAYLOAD (MHU_SECURE_BASE+0x0080) +#define MHU_SECURE_AP_TO_SCP_PAYLOAD (MHU_SECURE_BASE+0x0280) + +#define SIZE_SHIFT 20 /* Bit position for size value in MHU header */ +#define SIZE_MASK 0x1ff /* Mask to extract size value in MHU header*/ + + +void *scpi_secure_message_start(void) +{ + mhu_secure_message_start(); + + /* Return address of payload area. */ + return (void *)MHU_SECURE_AP_TO_SCP_PAYLOAD; +} + +void scpi_secure_message_send(unsigned command, size_t size) +{ + /* Make sure payload can be seen by SCP */ + if (MHU_PAYLOAD_CACHED) + flush_dcache_range(MHU_SECURE_AP_TO_SCP_PAYLOAD, size); + + mhu_secure_message_send(command | (size << SIZE_SHIFT)); +} + +unsigned scpi_secure_message_receive(void **message_out, size_t *size_out) +{ + uint32_t response = mhu_secure_message_wait(); + + /* Get size of payload */ + size_t size = (response >> SIZE_SHIFT) & SIZE_MASK; + + /* Clear size from response */ + response &= ~(SIZE_MASK << SIZE_SHIFT); + + /* Make sure we don't read stale data */ + if (MHU_PAYLOAD_CACHED) + inv_dcache_range(MHU_SECURE_SCP_TO_AP_PAYLOAD, size); + + if (size_out) + *size_out = size; + + if (message_out) + *message_out = (void *)MHU_SECURE_SCP_TO_AP_PAYLOAD; + + return response; +} + +void scpi_secure_message_end(void) +{ + mhu_secure_message_end(); +} + +static void scpi_secure_send32(unsigned command, uint32_t message) +{ + *(__typeof__(message) *)scpi_secure_message_start() = message; + scpi_secure_message_send(command, sizeof(message)); + scpi_secure_message_end(); +} + +int scpi_wait_ready(void) +{ + /* Get a message from the SCP */ + scpi_secure_message_start(); + size_t size; + unsigned command = scpi_secure_message_receive(NULL, &size); + scpi_secure_message_end(); + + /* We are expecting 'SCP Ready', produce correct error if it's not */ + scpi_status_t response = SCP_OK; + if (command != SCPI_CMD_SCP_READY) + response = SCP_E_SUPPORT; + else if (size != 0) + response = SCP_E_SIZE; + + /* Send our response back to SCP */ + scpi_secure_send32(command, response); + + return response == SCP_OK ? 0 : -1; +} + +void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, scpi_power_state_t css_state) +{ + uint32_t state = mpidr & 0x0f; /* CPU ID */ + state |= (mpidr & 0xf00) >> 4; /* Cluster ID */ + state |= cpu_state << 8; + state |= cluster_state << 12; + state |= css_state << 16; + scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state); +} diff --git a/plat/juno/scpi.h b/plat/juno/scpi.h new file mode 100644 index 0000000000..11129805bd --- /dev/null +++ b/plat/juno/scpi.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SCPI_H__ +#define __SCPI_H__ + +#include +#include + +extern void *scpi_secure_message_start(void); +extern void scpi_secure_message_send(unsigned command, size_t size); +extern unsigned scpi_secure_message_receive(void **message_out, size_t *size_out); +extern void scpi_secure_message_end(void); + + +enum { + SCP_OK = 0, /* Success */ + SCP_E_PARAM, /* Invalid parameter(s) */ + SCP_E_ALIGN, /* Invalid alignment */ + SCP_E_SIZE, /* Invalid size */ + SCP_E_HANDLER, /* Invalid handler or callback */ + SCP_E_ACCESS, /* Invalid access or permission denied */ + SCP_E_RANGE, /* Value out of range */ + SCP_E_TIMEOUT, /* Time out has ocurred */ + SCP_E_NOMEM, /* Invalid memory area or pointer */ + SCP_E_PWRSTATE, /* Invalid power state */ + SCP_E_SUPPORT, /* Feature not supported or disabled */ +}; + +typedef uint32_t scpi_status_t; + +typedef enum { + SCPI_CMD_SCP_READY = 0x01, + SCPI_CMD_SET_CSS_POWER_STATE = 0x04, +} scpi_command_t; + +typedef enum { + scpi_power_on = 0, + scpi_power_retention = 1, + scpi_power_off = 3, +} scpi_power_state_t; + +extern int scpi_wait_ready(void); +extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state, + scpi_power_state_t cluster_state, scpi_power_state_t css_state); + +#endif /* __SCPI_H__ */ From fef4fdb9cc0f2e4ca9d2864e1e92624da1e96ff5 Mon Sep 17 00:00:00 2001 From: Achin Gupta Date: Mon, 18 Aug 2014 14:40:27 +0100 Subject: [PATCH 2/5] Juno: Implement PSCI CPU_OFF and CPU_SUSPEND APIs This patch adds support for PSCI CPU_OFF and CPU_SUSPEND APIs to the Juno port of the ARM Trusted Firmware. The maximum affinity level that can be suspended is the cluster level (affinity level 1). Support for suspending the system level is not present. Change-Id: Ie2c9da0acd7d1b0d5ac64940cdf40347153e52c8 --- plat/juno/plat_pm.c | 114 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c index 61dc13e8bd..27a12278d3 100644 --- a/plat/juno/plat_pm.c +++ b/plat/juno/plat_pm.c @@ -86,11 +86,11 @@ static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state) * Juno handler called when an affinity instance is about to be turned on. The * level and mpidr determine the affinity instance. ******************************************************************************/ -int32_t juno_on(uint64_t mpidr, - uint64_t sec_entrypoint, - uint64_t ns_entrypoint, - uint32_t afflvl, - uint32_t state) +int32_t juno_affinst_on(uint64_t mpidr, + uint64_t sec_entrypoint, + uint64_t ns_entrypoint, + uint32_t afflvl, + uint32_t state) { /* * SCP takes care of powering up higher affinity levels so we @@ -117,7 +117,7 @@ int32_t juno_on(uint64_t mpidr, * was turned off prior to wakeup and do what's necessary to setup it up * correctly. ******************************************************************************/ -int32_t juno_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state) +int32_t juno_affinst_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state) { /* Determine if any platform actions need to be executed. */ if (juno_do_plat_actions(afflvl, state) == -EAGAIN) @@ -143,12 +143,110 @@ int32_t juno_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state) return PSCI_E_SUCCESS; } +/******************************************************************************* + * Common function called while turning a cpu off or suspending it. It is called + * from juno_off() or juno_suspend() when these functions in turn are called for + * the highest affinity level which will be powered down. It performs the + * actions common to the OFF and SUSPEND calls. + ******************************************************************************/ +static int32_t juno_power_down_common(uint32_t afflvl) +{ + uint32_t cluster_state = scpi_power_on; + + /* Prevent interrupts from spuriously waking up this cpu */ + gic_cpuif_deactivate(GICC_BASE); + + /* Cluster is to be turned off, so disable coherency */ + if (afflvl > MPIDR_AFFLVL0) { + cci_disable_cluster_coherency(read_mpidr_el1()); + cluster_state = scpi_power_off; + } + + /* + * Ask the SCP to power down the appropriate components depending upon + * their state. + */ + scpi_set_css_power_state(read_mpidr_el1(), + scpi_power_off, + cluster_state, + scpi_power_on); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Handler called when an affinity instance is about to be turned off. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take + * appropriate actions. + * + * CAUTION: There is no guarantee that caches will remain turned on across calls + * to this function as each affinity level is dealt with. So do not write & read + * global variables across calls. It will be wise to do flush a write to the + * global to prevent unpredictable results. + ******************************************************************************/ +static int32_t juno_affinst_off(uint64_t mpidr, uint32_t afflvl, uint32_t state) +{ + /* Determine if any platform actions need to be executed */ + if (juno_do_plat_actions(afflvl, state) == -EAGAIN) + return PSCI_E_SUCCESS; + + return juno_power_down_common(afflvl); +} + +/******************************************************************************* + * Handler called when an affinity instance is about to be suspended. The + * level and mpidr determine the affinity instance. The 'state' arg. allows the + * platform to decide whether the cluster is being turned off and take apt + * actions. The 'sec_entrypoint' determines the address in BL3-1 from where + * execution should resume. + * + * CAUTION: There is no guarantee that caches will remain turned on across calls + * to this function as each affinity level is dealt with. So do not write & read + * global variables across calls. It will be wise to do flush a write to the + * global to prevent unpredictable results. + ******************************************************************************/ +static int32_t juno_affinst_suspend(uint64_t mpidr, + uint64_t sec_entrypoint, + uint64_t ns_entrypoint, + uint32_t afflvl, + uint32_t state) +{ + /* Determine if any platform actions need to be executed */ + if (juno_do_plat_actions(afflvl, state) == -EAGAIN) + return PSCI_E_SUCCESS; + + /* + * Setup mailbox with address for CPU entrypoint when it next powers up. + */ + juno_program_mailbox(mpidr, sec_entrypoint); + + return juno_power_down_common(afflvl); +} + +/******************************************************************************* + * Juno handler called when an affinity instance has just been powered on after + * having been suspended earlier. The level and mpidr determine the affinity + * instance. + * TODO: At the moment we reuse the on finisher and reinitialize the secure + * context. Need to implement a separate suspend finisher. + ******************************************************************************/ +static int32_t juno_affinst_suspend_finish(uint64_t mpidr, + uint32_t afflvl, + uint32_t state) +{ + return juno_affinst_on_finish(mpidr, afflvl, state); +} + /******************************************************************************* * Export the platform handlers to enable psci to invoke them ******************************************************************************/ static const plat_pm_ops_t juno_ops = { - .affinst_on = juno_on, - .affinst_on_finish = juno_on_finish, + .affinst_on = juno_affinst_on, + .affinst_on_finish = juno_affinst_on_finish, + .affinst_off = juno_affinst_off, + .affinst_suspend = juno_affinst_suspend, + .affinst_suspend_finish = juno_affinst_suspend_finish }; /******************************************************************************* From edfda10a6b4ac7691746f1cd23e74a8dc3b70f0a Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Thu, 17 Jul 2014 09:56:29 +0100 Subject: [PATCH 3/5] Juno: Add support for Test Secure-EL1 Payload This patch implements the TSP on Juno. It executes from on-chip Trusted SRAM. Also, the other bootloader images (i.e. BL1 R/W, BL2 and BL3-1) have been moved around. The reason is, although there was enough space overall to store the TSP in SRAM, there was no contiguous free chunk of SRAM big enough to hold it. This patch keeps the overall memory layout (i.e. keeping BL1 R/W at the bottom, BL2 at the top and BL3-1 in between) but moves the base addresses of all the bootloader images in such a way that: - memory fragmentation is reduced enough to fit BL3-2 in; - new base addresses are suitable for release builds as well as debug ones; - each image has a few extra kilobytes for future growth. BL3-1 and BL3-2 are the images which received the biggest allocations since they will most probably grow the most. This patch also adds instruction synchronization barriers around the code which handles the timer interrupt in the TSP. This ensures that the interrupt is not acknowledged after or EOIed before it is deactivated at the peripheral. Change-Id: I1c5b51858700027ee283ac85d18e06863a27c72e --- bl32/tsp/tsp_timer.c | 7 ++- plat/juno/include/platform_def.h | 5 +- plat/juno/juno_def.h | 1 + plat/juno/plat-tsp.ld.S | 31 ++++++++++ plat/juno/plat_io_storage.c | 10 ++++ plat/juno/tsp/tsp-juno.mk | 37 ++++++++++++ plat/juno/tsp/tsp_plat_setup.c | 97 ++++++++++++++++++++++++++++++++ 7 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 plat/juno/plat-tsp.ld.S create mode 100644 plat/juno/tsp/tsp-juno.mk create mode 100644 plat/juno/tsp/tsp_plat_setup.c diff --git a/bl32/tsp/tsp_timer.c b/bl32/tsp/tsp_timer.c index d9460b69da..f196021d07 100644 --- a/bl32/tsp/tsp_timer.c +++ b/bl32/tsp/tsp_timer.c @@ -68,9 +68,14 @@ void tsp_generic_timer_handler(void) /* Ensure that the timer did assert the interrupt */ assert(get_cntp_ctl_istatus(read_cntps_ctl_el1())); - /* Disable the timer and reprogram it */ + /* + * Disable the timer and reprogram it. The barriers ensure that there is + * no reordering of instructions around the reprogramming code. + */ + isb(); write_cntps_ctl_el1(0); tsp_generic_timer_start(); + isb(); } /******************************************************************************* diff --git a/plat/juno/include/platform_def.h b/plat/juno/include/platform_def.h index 2678efc2dd..6d9d0fb002 100644 --- a/plat/juno/include/platform_def.h +++ b/plat/juno/include/platform_def.h @@ -32,6 +32,7 @@ #define __PLATFORM_DEF_H__ #include +#include "../juno_def.h" /******************************************************************************* * Platform binary types for linking @@ -142,9 +143,9 @@ #define MAX_MMAP_REGIONS 16 /******************************************************************************* - * ID of the secure physical generic timer interrupt. + * ID of the secure physical generic timer interrupt used by the TSP ******************************************************************************/ -#define IRQ_SEC_PHY_TIMER 29 +#define TSP_IRQ_SEC_PHY_TIMER IRQ_SEC_PHY_TIMER /******************************************************************************* * Declarations and constants to access the mailboxes safely. Each mailbox is diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h index b099e97687..b3099b715e 100644 --- a/plat/juno/juno_def.h +++ b/plat/juno/juno_def.h @@ -113,6 +113,7 @@ #define IRQ_TZC400 80 #define IRQ_TZ_WDOG 86 +#define IRQ_SEC_PHY_TIMER 29 #define IRQ_SEC_SGI_0 8 #define IRQ_SEC_SGI_1 9 #define IRQ_SEC_SGI_2 10 diff --git a/plat/juno/plat-tsp.ld.S b/plat/juno/plat-tsp.ld.S new file mode 100644 index 0000000000..16d6c17190 --- /dev/null +++ b/plat/juno/plat-tsp.ld.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + ASSERT(__BL32_END__ <= BL2_BASE, "BL3-2 image overlaps BL2 image.") diff --git a/plat/juno/plat_io_storage.c b/plat/juno/plat_io_storage.c index b2974007c1..83d7e43bab 100644 --- a/plat/juno/plat_io_storage.c +++ b/plat/juno/plat_io_storage.c @@ -67,6 +67,11 @@ static const io_file_spec_t bl31_file_spec = { .mode = FOPEN_MODE_RB }; +static const io_file_spec_t bl32_file_spec = { + .path = BL32_IMAGE_NAME, + .mode = FOPEN_MODE_RB +}; + static const io_file_spec_t bl33_file_spec = { .path = BL33_IMAGE_NAME, .mode = FOPEN_MODE_RB @@ -103,6 +108,11 @@ static const struct plat_io_policy policies[] = { &fip_dev_handle, (uintptr_t)&bl31_file_spec, open_fip + }, { + BL32_IMAGE_NAME, + &fip_dev_handle, + (uintptr_t)&bl32_file_spec, + open_fip }, { BL33_IMAGE_NAME, &fip_dev_handle, diff --git a/plat/juno/tsp/tsp-juno.mk b/plat/juno/tsp/tsp-juno.mk new file mode 100644 index 0000000000..d0d29d7737 --- /dev/null +++ b/plat/juno/tsp/tsp-juno.mk @@ -0,0 +1,37 @@ +# +# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# TSP source files specific to Juno platform +BL32_SOURCES += drivers/arm/gic/gic_v2.c \ + plat/common/aarch64/platform_mp_stack.S \ + plat/juno/aarch64/juno_common.c \ + plat/juno/aarch64/plat_helpers.S \ + plat/juno/tsp/tsp_plat_setup.c \ + plat/juno/plat_gic.c diff --git a/plat/juno/tsp/tsp_plat_setup.c b/plat/juno/tsp/tsp_plat_setup.c new file mode 100644 index 0000000000..b999df1f87 --- /dev/null +++ b/plat/juno/tsp/tsp_plat_setup.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "../juno_def.h" +#include "../juno_private.h" + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +extern unsigned long __RO_START__; +extern unsigned long __RO_END__; + +extern unsigned long __COHERENT_RAM_START__; +extern unsigned long __COHERENT_RAM_END__; + +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +#define BL32_RO_BASE (unsigned long)(&__RO_START__) +#define BL32_RO_LIMIT (unsigned long)(&__RO_END__) + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) + +/******************************************************************************* + * Initialize the UART + ******************************************************************************/ +void tsp_early_platform_setup(void) +{ + /* + * Initialize a different console than already in use to display + * messages from TSP + */ + console_init(PL011_UART1_BASE, PL011_UART1_CLK_IN_HZ, PL011_BAUDRATE); +} + +/******************************************************************************* + * Perform platform specific setup placeholder + ******************************************************************************/ +void tsp_platform_setup(void) +{ +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this only intializes the MMU + ******************************************************************************/ +void tsp_plat_arch_setup(void) +{ + configure_mmu_el1(BL32_RO_BASE, + BL32_COHERENT_RAM_LIMIT - BL32_RO_BASE, + BL32_RO_BASE, + BL32_RO_LIMIT, + BL32_COHERENT_RAM_BASE, + BL32_COHERENT_RAM_LIMIT); +} From efafbc898e101a48bb3cb635514d7ee30b4c7f41 Mon Sep 17 00:00:00 2001 From: Juan Castillo Date: Tue, 12 Aug 2014 08:42:28 +0100 Subject: [PATCH 4/5] Juno: Implement PSCI SYSTEM_OFF and SYSTEM_RESET APIs This patch adds the Juno platform specific handlers for PSCI SYSTEM_OFF and SYSTEM_RESET operations. Change-Id: Ie389adead533ec2314af44d721b4d0f306147c7d --- plat/juno/plat_pm.c | 40 +++++++++++++++++++++++++++++++++++++++- plat/juno/scpi.c | 14 ++++++++++++++ plat/juno/scpi.h | 8 ++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c index 27a12278d3..74ce89fdfe 100644 --- a/plat/juno/plat_pm.c +++ b/plat/juno/plat_pm.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -238,6 +239,41 @@ static int32_t juno_affinst_suspend_finish(uint64_t mpidr, return juno_affinst_on_finish(mpidr, afflvl, state); } +/******************************************************************************* + * Juno handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 juno_system_off(void) +{ + uint32_t response; + + /* Send the power down request to the SCP */ + response = scpi_sys_power_state(scpi_system_shutdown); + + if (response != SCP_OK) { + ERROR("Juno System Off: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("Juno System Off: operation not handled.\n"); + panic(); +} + +static void __dead2 juno_system_reset(void) +{ + uint32_t response; + + /* Send the system reset request to the SCP */ + response = scpi_sys_power_state(scpi_system_reboot); + + if (response != SCP_OK) { + ERROR("Juno System Reset: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("Juno System Reset: operation not handled.\n"); + panic(); +} + /******************************************************************************* * Export the platform handlers to enable psci to invoke them ******************************************************************************/ @@ -246,7 +282,9 @@ static const plat_pm_ops_t juno_ops = { .affinst_on_finish = juno_affinst_on_finish, .affinst_off = juno_affinst_off, .affinst_suspend = juno_affinst_suspend, - .affinst_suspend_finish = juno_affinst_suspend_finish + .affinst_suspend_finish = juno_affinst_suspend_finish, + .system_off = juno_system_off, + .system_reset = juno_system_reset }; /******************************************************************************* diff --git a/plat/juno/scpi.c b/plat/juno/scpi.c index c1677aae31..950c00bb7c 100644 --- a/plat/juno/scpi.c +++ b/plat/juno/scpi.c @@ -124,3 +124,17 @@ void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state, state |= css_state << 16; scpi_secure_send32(SCPI_CMD_SET_CSS_POWER_STATE, state); } + +uint32_t scpi_sys_power_state(scpi_system_state_t system_state) +{ + uint32_t *response; + size_t size; + uint8_t state = system_state & 0xff; + + /* Send the command */ + *(__typeof__(state) *)scpi_secure_message_start() = state; + scpi_secure_message_send(SCPI_CMD_SYS_POWER_STATE, sizeof(state)); + scpi_secure_message_receive((void *)&response, &size); + scpi_secure_message_end(); + return *response; +} diff --git a/plat/juno/scpi.h b/plat/juno/scpi.h index 11129805bd..8a5ef65496 100644 --- a/plat/juno/scpi.h +++ b/plat/juno/scpi.h @@ -59,6 +59,7 @@ typedef uint32_t scpi_status_t; typedef enum { SCPI_CMD_SCP_READY = 0x01, SCPI_CMD_SET_CSS_POWER_STATE = 0x04, + SCPI_CMD_SYS_POWER_STATE = 0x08 } scpi_command_t; typedef enum { @@ -67,8 +68,15 @@ typedef enum { scpi_power_off = 3, } scpi_power_state_t; +typedef enum { + scpi_system_shutdown = 0, + scpi_system_reboot = 1, + scpi_system_reset = 2 +} scpi_system_state_t; + extern int scpi_wait_ready(void); extern void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state, scpi_power_state_t cluster_state, scpi_power_state_t css_state); +uint32_t scpi_sys_power_state(scpi_system_state_t system_state); #endif /* __SCPI_H__ */ From 38af430af68002887129aaff990069cf3e2daf6a Mon Sep 17 00:00:00 2001 From: Juan Castillo Date: Tue, 12 Aug 2014 17:24:30 +0100 Subject: [PATCH 5/5] Juno: Read primary CPU MPID from SCC GPR_1 This patch removes the PRIMARY_CPU definition hardcoded in the Juno port. Instead, the primary CPU is obtained at runtime by reading the SCC General Purpose Register 1 (GPR_1), whose value is copied by the SCP into shared memory during the boot process. Change-Id: I3981daa92eb7142250712274cf7f655b219837f5 --- plat/juno/aarch64/bl1_plat_helpers.S | 17 +++++++++++++++++ plat/juno/aarch64/plat_helpers.S | 16 ---------------- plat/juno/bl2_plat_setup.c | 2 +- plat/juno/juno_def.h | 9 +++++++-- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/plat/juno/aarch64/bl1_plat_helpers.S b/plat/juno/aarch64/bl1_plat_helpers.S index 785aa15adb..3054eabf23 100644 --- a/plat/juno/aarch64/bl1_plat_helpers.S +++ b/plat/juno/aarch64/bl1_plat_helpers.S @@ -32,10 +32,27 @@ #include #include "../juno_def.h" + .globl platform_is_primary_cpu .globl platform_get_entrypoint .globl platform_cold_boot_init .globl plat_secondary_cold_boot_setup + /* ----------------------------------------------------- + * unsigned int platform_is_primary_cpu (unsigned int mpid); + * + * Given the mpidr say whether this cpu is the primary + * cpu (applicable ony after a cold boot) + * ----------------------------------------------------- + */ +func platform_is_primary_cpu + mov x9, x30 + bl platform_get_core_pos + ldr x1, =SCP_BOOT_CFG_ADDR + ldr x1, [x1] + ubfx x1, x1, #PRIMARY_CPU_SHIFT, #PRIMARY_CPU_MASK + cmp x0, x1 + cset x0, eq + ret x9 /* ----------------------------------------------------- * void plat_secondary_cold_boot_setup (void); diff --git a/plat/juno/aarch64/plat_helpers.S b/plat/juno/aarch64/plat_helpers.S index 03541620c3..1721a0ae95 100644 --- a/plat/juno/aarch64/plat_helpers.S +++ b/plat/juno/aarch64/plat_helpers.S @@ -41,7 +41,6 @@ .globl plat_report_exception .globl plat_reset_handler .globl platform_get_core_pos - .globl platform_is_primary_cpu .globl platform_mem_init /* Define a crash console for the plaform */ @@ -103,21 +102,6 @@ func platform_get_core_pos ret - /* ----------------------------------------------------- - * unsigned int platform_is_primary_cpu(unsigned long mpid); - * - * Given the mpidr say whether this cpu is the primary - * cpu (applicable only after a cold boot) - * ----------------------------------------------------- - */ -func platform_is_primary_cpu - /* Juno todo: allow configuration of primary CPU using SCC */ - and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) - cmp x0, #JUNO_PRIMARY_CPU - cset x0, eq - ret - - /* ----------------------------------------------------- * void platform_mem_init(void); * diff --git a/plat/juno/bl2_plat_setup.c b/plat/juno/bl2_plat_setup.c index 0441cf6c7b..5dec2d7a1e 100644 --- a/plat/juno/bl2_plat_setup.c +++ b/plat/juno/bl2_plat_setup.c @@ -128,7 +128,7 @@ bl31_params_t *bl2_plat_get_bl31_params(void) PARAM_EP, VERSION_1, 0); /* BL3-3 expects to receive the primary CPU MPID (through x0) */ - bl2_to_bl31_params->bl33_ep_info->args.arg0 = JUNO_PRIMARY_CPU; + bl2_to_bl31_params->bl33_ep_info->args.arg0 = 0xffff & read_mpidr(); bl2_to_bl31_params->bl33_image_info = &bl31_params_mem.bl33_image_info; SET_PARAM_HEAD(bl2_to_bl31_params->bl33_image_info, PARAM_IMAGE_BINARY, diff --git a/plat/juno/juno_def.h b/plat/juno/juno_def.h index b3099b715e..1eae65d6c6 100644 --- a/plat/juno/juno_def.h +++ b/plat/juno/juno_def.h @@ -34,8 +34,6 @@ /* Special value used to verify platform parameters from BL2 to BL3-1 */ #define JUNO_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL -#define JUNO_PRIMARY_CPU 0x100 - /******************************************************************************* * Juno memory map related constants ******************************************************************************/ @@ -194,4 +192,11 @@ #define CCI400_SL_IFACE3_CLUSTER_IX 1 #define CCI400_SL_IFACE4_CLUSTER_IX 0 +/******************************************************************************* + * SCP <=> AP boot configuration + ******************************************************************************/ +#define SCP_BOOT_CFG_ADDR 0x04000080 +#define PRIMARY_CPU_SHIFT 8 +#define PRIMARY_CPU_MASK 0xf + #endif /* __JUNO_DEF_H__ */