diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index b2aac2f..4056260 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 9cf8780..6128b16 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 0000000..785aa15 --- /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 0000000..5ba38c1 --- /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 0000000..0354162 --- /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 0000000..d2f2ab4 --- /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 0000000..0441cf6 --- /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 0000000..131a1b1 --- /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 0000000..0e08834 --- /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 0000000..2678efc --- /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 0000000..b099e97 --- /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 0000000..0dac03a --- /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 0000000..b6541a8 --- /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 0000000..5149c82 --- /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 0000000..9001519 --- /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 0000000..b297400 --- /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 0000000..61dc13e --- /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 0000000..39d4dab --- /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 0000000..4746536 --- /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 0000000..a6d25d4 --- /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 0000000..e872513 --- /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 0000000..c1677aa --- /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 0000000..1112980 --- /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__ */