Commit 01b916bf authored by Sandrine Bailleux's avatar Sandrine Bailleux Committed by Soby Mathew
Browse files

Juno: Implement initial platform port

This patch adds the initial port of the ARM Trusted Firmware on the Juno
development platform. This port does not support a BL3-2 image or any PSCI APIs
apart from PSCI_VERSION and PSCI_CPU_ON. It enables workarounds for selected
Cortex-A57 (#806969 & #813420) errata and implements the workaround for a Juno
platform errata (Defect id 831273).

Change-Id: Ib3d92df3af53820cfbb2977582ed0d7abf6ef893
parent e822d7c1
...@@ -166,6 +166,10 @@ ...@@ -166,6 +166,10 @@
#define EL0VTEN_BIT (1 << 8) #define EL0VTEN_BIT (1 << 8)
#define EL0PCTEN_BIT (1 << 0) #define EL0PCTEN_BIT (1 << 0)
#define EL0VCTEN_BIT (1 << 1) #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 */ /* CPTR_EL3 definitions */
#define TCPAC_BIT (1 << 31) #define TCPAC_BIT (1 << 31)
......
...@@ -52,4 +52,15 @@ ...@@ -52,4 +52,15 @@
#define CPUACTLR_NO_ALLOC_WBWA (1 << 49) #define CPUACTLR_NO_ALLOC_WBWA (1 << 49)
#define CPUACTLR_DCC_AS_DCCI (1 << 44) #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__ */ #endif /* __CORTEX_A57_H__ */
/*
* 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 <arch.h>
#include <asm_macros.S>
#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
/*
* 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 <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <debug.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <xlat_tables.h>
#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;
}
/*
* 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 <arch.h>
#include <asm_macros.S>
#include <bl_common.h>
#include <cortex_a57.h>
#include <cpu_macros.S>
#include <platform_def.h>
#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
/*
* 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 <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <cci400.h>
#include <console.h>
#include <debug.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <tzc400.h>
#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);
}
/*
* 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 <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
#include <platform.h>
#include <platform_def.h>
#include <string.h>
#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;
}
/*
* 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 <arch.h>
#include <assert.h>
#include <bl31.h>
#include <bl_common.h>
#include <cci400.h>
#include <console.h>
#include <mmio.h>
#include <platform.h>
#include <stddef.h>
#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);
}
/*
* 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 <cci400.h>
#include <gic_v2.h>
#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
/*
* 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 <arch.h>
/*******************************************************************************
* 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__ */
/*
* 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__ */
/*
* 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 <bl_common.h>
#include <platform_def.h>
#include <stdint.h>
/*******************************************************************************
* 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__ */
/*
* 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 <arch_helpers.h>
#include <bakery_lock.h>
#include <mmio.h>
#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);
}
/*
* 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 <stdint.h>
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__ */
/*
* 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 <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <gic_v2.h>
#include <interrupt_mgmt.h>
#include <platform.h>
#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;
}
/*
* 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 <assert.h>
#include <debug.h>
#include <io_driver.h>
#include <io_fip.h>
#include <io_memmap.h>
#include <io_storage.h>
#include <platform_def.h>
#include <semihosting.h> /* For FOPEN_MODE_... */
#include <string.h>
/* 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;
}
/*
* 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 <assert.h>
#include <arch_helpers.h>
#include <cci400.h>
#include <errno.h>
#include <platform.h>
#include <platform_def.h>
#include <psci.h>
#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;
}
/*
* 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 <platform_def.h>
#include <psci.h>
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;
}
#
# 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
/*
* 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 <arch_helpers.h>
#include <platform.h>
#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();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment