juno: Create as a trimmed copy of plat/fvp
Signed-off-by: Jon Medhurst <tixy@linaro.org>
This commit is contained in:
parent
977fbcd4e0
commit
068d9170a3
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* 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 <platform.h>
|
||||||
|
|
||||||
|
.globl platform_get_entrypoint
|
||||||
|
.globl platform_cold_boot_init
|
||||||
|
.globl plat_secondary_cold_boot_setup
|
||||||
|
|
||||||
|
|
||||||
|
.section .text, "ax"; .align 3
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------
|
||||||
|
* 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.
|
||||||
|
* -----------------------------------------------------
|
||||||
|
*/
|
||||||
|
plat_secondary_cold_boot_setup: ; .type plat_secondary_cold_boot_setup, %function
|
||||||
|
/* 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
|
||||||
|
* TODO: PSYSR is a common register and should be
|
||||||
|
* accessed using locks. Since its not possible
|
||||||
|
* to use locks immediately after a cold reset
|
||||||
|
* we are relying on the fact that after a cold
|
||||||
|
* reset all cpus will read the same WK field
|
||||||
|
* -----------------------------------------------------
|
||||||
|
*/
|
||||||
|
platform_get_entrypoint: ; .type platform_get_entrypoint, %function
|
||||||
|
mov x9, x30 // lr
|
||||||
|
mov x2, x0
|
||||||
|
ldr x1, =PWRC_BASE
|
||||||
|
str w2, [x1, #PSYSR_OFF]
|
||||||
|
ldr w2, [x1, #PSYSR_OFF]
|
||||||
|
ubfx w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_MASK
|
||||||
|
cbnz w2, warm_reset
|
||||||
|
mov x0, x2
|
||||||
|
b exit
|
||||||
|
warm_reset:
|
||||||
|
/* ---------------------------------------------
|
||||||
|
* A per-cpu mailbox is maintained in the tru-
|
||||||
|
* sted DRAM. Its flushed out of the caches
|
||||||
|
* after every update using normal memory so
|
||||||
|
* its safe to read it here with SO attributes
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
ldr x10, =TZDRAM_BASE + MBOX_OFF
|
||||||
|
bl platform_get_core_pos
|
||||||
|
lsl x0, x0, #CACHE_WRITEBACK_SHIFT
|
||||||
|
ldr x0, [x10, x0]
|
||||||
|
cbz x0, _panic
|
||||||
|
exit:
|
||||||
|
ret x9
|
||||||
|
_panic: b _panic
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------
|
||||||
|
* void platform_mem_init (void);
|
||||||
|
*
|
||||||
|
* Zero out the mailbox registers in the TZDRAM. The
|
||||||
|
* mmu is turned off right now and only the primary can
|
||||||
|
* ever execute this code. Secondaries will read the
|
||||||
|
* mailboxes using SO accesses. In short, BL31 will
|
||||||
|
* update the mailboxes after mapping the tzdram as
|
||||||
|
* normal memory. It will flush its copy after update.
|
||||||
|
* BL1 will always read the mailboxes with the MMU off
|
||||||
|
* -----------------------------------------------------
|
||||||
|
*/
|
||||||
|
platform_mem_init: ; .type platform_mem_init, %function
|
||||||
|
ldr x0, =TZDRAM_BASE + MBOX_OFF
|
||||||
|
stp xzr, xzr, [x0, #0]
|
||||||
|
stp xzr, xzr, [x0, #0x10]
|
||||||
|
stp xzr, xzr, [x0, #0x20]
|
||||||
|
stp xzr, xzr, [x0, #0x30]
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------
|
||||||
|
* void platform_cold_boot_init (bl1_main function);
|
||||||
|
*
|
||||||
|
* Routine called only by the primary cpu after a cold
|
||||||
|
* boot to perform early platform initialization
|
||||||
|
* -----------------------------------------------------
|
||||||
|
*/
|
||||||
|
platform_cold_boot_init: ; .type platform_cold_boot_init, %function
|
||||||
|
mov x20, x0
|
||||||
|
bl platform_mem_init
|
||||||
|
bl read_mpidr
|
||||||
|
mov x19, x0
|
||||||
|
|
||||||
|
/* ---------------------------------------------
|
||||||
|
* Give ourselves a small coherent stack to
|
||||||
|
* ease the pain of initializing the MMU and
|
||||||
|
* CCI in assembler
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
mov x0, x19
|
||||||
|
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
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <arch_helpers.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
/* Included only for error codes */
|
||||||
|
#include <psci.h>
|
||||||
|
|
||||||
|
unsigned char platform_normal_stacks[PLATFORM_STACK_SIZE][PLATFORM_CORE_COUNT]
|
||||||
|
__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE),
|
||||||
|
section("tzfw_normal_stacks")));
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This array holds the characteristics of the differences between the three
|
||||||
|
* FVP platforms (Base, A53_A57 & Foundation). It will be populated during cold
|
||||||
|
* boot at each boot stage by the primary before enabling the MMU (to allow cci
|
||||||
|
* configuration) & used thereafter. Each BL will have its own copy to allow
|
||||||
|
* independent operation.
|
||||||
|
******************************************************************************/
|
||||||
|
static unsigned long platform_config[CONFIG_LIMIT];
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* An internal global pointer of the level 1 translation tables which should not
|
||||||
|
* change once setup by the primary cpu during a cold boot.
|
||||||
|
*******************************************************************************/
|
||||||
|
unsigned long l1_xlation_table __aligned(PLATFORM_CACHE_LINE_SIZE)
|
||||||
|
__attribute__ ((section("tzfw_coherent_mem")));
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Enable the MMU assuming that the pagetables have already been created
|
||||||
|
*******************************************************************************/
|
||||||
|
void enable_mmu()
|
||||||
|
{
|
||||||
|
unsigned long mair, tcr, ttbr, sctlr;
|
||||||
|
unsigned long current_el = read_current_el();
|
||||||
|
|
||||||
|
/* Set the attributes in the right indices of the MAIR */
|
||||||
|
mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
|
||||||
|
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
|
||||||
|
ATTR_IWBWA_OWBWA_NTR_INDEX);
|
||||||
|
write_mair(mair);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set TCR bits as well. Inner & outer WBWA & shareable + T0SZ = 32
|
||||||
|
*/
|
||||||
|
tcr = TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA |
|
||||||
|
TCR_RGN_INNER_WBA | TCR_T0SZ_4GB;
|
||||||
|
if (GET_EL(current_el) == MODE_EL3) {
|
||||||
|
tcr |= TCR_EL3_RES1;
|
||||||
|
/* Invalidate EL3 TLBs */
|
||||||
|
tlbialle3();
|
||||||
|
} else {
|
||||||
|
/* Invalidate EL1 TLBs */
|
||||||
|
tlbivmalle1();
|
||||||
|
}
|
||||||
|
|
||||||
|
write_tcr(tcr);
|
||||||
|
|
||||||
|
/* Set TTBR bits as well */
|
||||||
|
ttbr = (unsigned long) l1_xlation_table;
|
||||||
|
write_ttbr0(ttbr);
|
||||||
|
|
||||||
|
sctlr = read_sctlr();
|
||||||
|
sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT | SCTLR_I_BIT;
|
||||||
|
sctlr |= SCTLR_A_BIT | SCTLR_C_BIT;
|
||||||
|
write_sctlr(sctlr);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable_mmu(void)
|
||||||
|
{
|
||||||
|
/* Zero out the MMU related registers */
|
||||||
|
write_mair(0);
|
||||||
|
write_tcr(0);
|
||||||
|
write_ttbr0(0);
|
||||||
|
write_sctlr(0);
|
||||||
|
|
||||||
|
/* Flush the caches */
|
||||||
|
dcsw_op_all(DCCISW);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Setup the pagetables as per the platform memory map & initialize the mmu
|
||||||
|
*******************************************************************************/
|
||||||
|
void configure_mmu(meminfo *mem_layout,
|
||||||
|
unsigned long ro_start,
|
||||||
|
unsigned long ro_limit,
|
||||||
|
unsigned long coh_start,
|
||||||
|
unsigned long coh_limit)
|
||||||
|
{
|
||||||
|
assert(IS_PAGE_ALIGNED(ro_start));
|
||||||
|
assert(IS_PAGE_ALIGNED(ro_limit));
|
||||||
|
assert(IS_PAGE_ALIGNED(coh_start));
|
||||||
|
assert(IS_PAGE_ALIGNED(coh_limit));
|
||||||
|
|
||||||
|
l1_xlation_table = fill_xlation_tables(mem_layout,
|
||||||
|
ro_start,
|
||||||
|
ro_limit,
|
||||||
|
coh_start,
|
||||||
|
coh_limit);
|
||||||
|
enable_mmu();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simple routine which returns a configuration variable value */
|
||||||
|
unsigned long platform_get_cfgvar(unsigned int var_id)
|
||||||
|
{
|
||||||
|
assert(var_id < CONFIG_LIMIT);
|
||||||
|
return platform_config[var_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long plat_get_ns_image_entrypoint(void) {
|
||||||
|
return NS_IMAGE_OFFSET;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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 <platform.h>
|
||||||
|
|
||||||
|
.globl plat_report_exception
|
||||||
|
|
||||||
|
.section .text, "ax"
|
||||||
|
|
||||||
|
/* ---------------------------------------------
|
||||||
|
* void plat_report_exception(unsigned int type)
|
||||||
|
* Function to report an unhandled exception
|
||||||
|
* with platform-specific means.
|
||||||
|
* On FVP platform, it updates the LEDs
|
||||||
|
* to indicate where we are
|
||||||
|
* ---------------------------------------------
|
||||||
|
*/
|
||||||
|
plat_report_exception:
|
||||||
|
/* Juno todo: Come up with a way of reporting errors */
|
||||||
|
ret
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* 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 <assert.h>
|
||||||
|
#include <arch_helpers.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <bl1.h>
|
||||||
|
#include <console.h>
|
||||||
|
#include <cci400.h>
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Declarations of linker defined symbols which will help us find the layout
|
||||||
|
* of trusted SRAM
|
||||||
|
******************************************************************************/
|
||||||
|
extern unsigned long __COHERENT_RAM_START__;
|
||||||
|
extern unsigned long __COHERENT_RAM_END__;
|
||||||
|
|
||||||
|
extern unsigned long __BL1_RAM_START__;
|
||||||
|
extern unsigned long __BL1_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__)
|
||||||
|
|
||||||
|
#define BL1_RAM_BASE (unsigned long)(&__BL1_RAM_START__)
|
||||||
|
#define BL1_RAM_LIMIT (unsigned long)(&__BL1_RAM_END__)
|
||||||
|
|
||||||
|
|
||||||
|
/* Data structure which holds the extents of the trusted SRAM for BL1*/
|
||||||
|
static meminfo bl1_tzram_layout;
|
||||||
|
|
||||||
|
meminfo *bl1_plat_sec_mem_layout(void)
|
||||||
|
{
|
||||||
|
return &bl1_tzram_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Perform any BL1 specific platform actions.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl1_early_platform_setup(void)
|
||||||
|
{
|
||||||
|
const unsigned long bl1_ram_base = BL1_RAM_BASE;
|
||||||
|
const unsigned long bl1_ram_limit = BL1_RAM_LIMIT;
|
||||||
|
const unsigned long tzram_limit = TZRAM_BASE + TZRAM_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate how much ram is BL1 using & how much remains free.
|
||||||
|
* This also includes a rudimentary mechanism to detect whether
|
||||||
|
* the BL1 data is loaded at the top or bottom of memory.
|
||||||
|
* TODO: add support for discontigous chunks of free ram if
|
||||||
|
* needed. Might need dynamic memory allocation support
|
||||||
|
* et al.
|
||||||
|
*/
|
||||||
|
bl1_tzram_layout.total_base = TZRAM_BASE;
|
||||||
|
bl1_tzram_layout.total_size = TZRAM_SIZE;
|
||||||
|
|
||||||
|
if (bl1_ram_limit == tzram_limit) {
|
||||||
|
/* BL1 has been loaded at the top of memory. */
|
||||||
|
bl1_tzram_layout.free_base = TZRAM_BASE;
|
||||||
|
bl1_tzram_layout.free_size = bl1_ram_base - TZRAM_BASE;
|
||||||
|
} else {
|
||||||
|
/* BL1 has been loaded at the bottom of memory. */
|
||||||
|
bl1_tzram_layout.free_base = bl1_ram_limit;
|
||||||
|
bl1_tzram_layout.free_size =
|
||||||
|
tzram_limit - bl1_ram_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the console */
|
||||||
|
console_init(PL011_UART0_BASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Function which will evaluate how much of the trusted ram has been gobbled
|
||||||
|
* up by BL1 and return the base and size of whats available for loading BL2.
|
||||||
|
* Its called after coherency and the MMU have been turned on.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl1_platform_setup(void)
|
||||||
|
{
|
||||||
|
/* 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_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)
|
||||||
|
{
|
||||||
|
unsigned long cci_setup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable CCI-400 for this cluster. No need
|
||||||
|
* for locks as no other cpu is active at the
|
||||||
|
* moment
|
||||||
|
*/
|
||||||
|
cci_setup = platform_get_cfgvar(CONFIG_HAS_CCI);
|
||||||
|
if (cci_setup) {
|
||||||
|
cci_enable_coherency(read_mpidr());
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_mmu(&bl1_tzram_layout,
|
||||||
|
TZROM_BASE,
|
||||||
|
TZROM_BASE + TZROM_SIZE,
|
||||||
|
BL1_COHERENT_RAM_BASE,
|
||||||
|
BL1_COHERENT_RAM_LIMIT);
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* 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 <assert.h>
|
||||||
|
#include <arch_helpers.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <bl2.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Declarations of linker defined symbols which will help us find the layout
|
||||||
|
* of trusted SRAM
|
||||||
|
******************************************************************************/
|
||||||
|
extern unsigned long __RO_START__;
|
||||||
|
extern unsigned long __RO_END__;
|
||||||
|
|
||||||
|
extern unsigned long __COHERENT_RAM_START__;
|
||||||
|
extern unsigned long __COHERENT_RAM_END__;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next 2 constants identify the extents of the code & RO data region.
|
||||||
|
* These addresses are used by the MMU setup code and therefore they must be
|
||||||
|
* page-aligned. It is the responsibility of the linker script to ensure that
|
||||||
|
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
|
||||||
|
*/
|
||||||
|
#define 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__)
|
||||||
|
|
||||||
|
/* Pointer to memory visible to both BL2 and BL31 for passing data */
|
||||||
|
extern unsigned char **bl2_el_change_mem_ptr;
|
||||||
|
|
||||||
|
/* Data structure which holds the extents of the trusted SRAM for BL2 */
|
||||||
|
static meminfo bl2_tzram_layout
|
||||||
|
__attribute__ ((aligned(PLATFORM_CACHE_LINE_SIZE),
|
||||||
|
section("tzfw_coherent_mem")));
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Reference to structure which holds the arguments which need to be passed
|
||||||
|
* to BL31
|
||||||
|
******************************************************************************/
|
||||||
|
static bl31_args *bl2_to_bl31_args;
|
||||||
|
|
||||||
|
meminfo *bl2_plat_sec_mem_layout(void)
|
||||||
|
{
|
||||||
|
return &bl2_tzram_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function returns a pointer to the memory that the platform has kept
|
||||||
|
* aside to pass all the information that BL31 could need.
|
||||||
|
******************************************************************************/
|
||||||
|
bl31_args *bl2_get_bl31_args_ptr(void)
|
||||||
|
{
|
||||||
|
return bl2_to_bl31_args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* BL1 has passed the extents of the trusted SRAM that should be visible to BL2
|
||||||
|
* in x0. This memory layout is sitting at the base of the free trusted SRAM.
|
||||||
|
* Copy it to a safe loaction before its reclaimed by later BL2 functionality.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl2_early_platform_setup(meminfo *mem_layout,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
/* Setup the BL2 memory layout */
|
||||||
|
bl2_tzram_layout.total_base = mem_layout->total_base;
|
||||||
|
bl2_tzram_layout.total_size = mem_layout->total_size;
|
||||||
|
bl2_tzram_layout.free_base = mem_layout->free_base;
|
||||||
|
bl2_tzram_layout.free_size = mem_layout->free_size;
|
||||||
|
bl2_tzram_layout.attr = mem_layout->attr;
|
||||||
|
bl2_tzram_layout.next = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Perform platform specific setup. For now just initialize the memory location
|
||||||
|
* to use for passing arguments to BL31.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl2_platform_setup()
|
||||||
|
{
|
||||||
|
/* Initialise the IO layer and register platform IO devices */
|
||||||
|
io_setup();
|
||||||
|
/* Use the Trusted DRAM for passing args to BL31 */
|
||||||
|
bl2_to_bl31_args = (bl31_args *) TZDRAM_BASE;
|
||||||
|
|
||||||
|
/* Populate the extents of memory available for loading BL33 */
|
||||||
|
bl2_to_bl31_args->bl33_meminfo.total_base = DRAM_BASE;
|
||||||
|
bl2_to_bl31_args->bl33_meminfo.total_size = DRAM_SIZE;
|
||||||
|
bl2_to_bl31_args->bl33_meminfo.free_base = DRAM_BASE;
|
||||||
|
bl2_to_bl31_args->bl33_meminfo.free_size = DRAM_SIZE;
|
||||||
|
bl2_to_bl31_args->bl33_meminfo.attr = 0;
|
||||||
|
bl2_to_bl31_args->bl33_meminfo.next = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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()
|
||||||
|
{
|
||||||
|
configure_mmu(&bl2_tzram_layout,
|
||||||
|
BL2_RO_BASE,
|
||||||
|
BL2_RO_LIMIT,
|
||||||
|
BL2_COHERENT_RAM_BASE,
|
||||||
|
BL2_COHERENT_RAM_LIMIT);
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* 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 <platform.h>
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Declarations of linker defined symbols which will help us find the layout
|
||||||
|
* of trusted SRAM
|
||||||
|
******************************************************************************/
|
||||||
|
extern unsigned long __RO_START__;
|
||||||
|
extern unsigned long __RO_END__;
|
||||||
|
|
||||||
|
extern unsigned long __COHERENT_RAM_START__;
|
||||||
|
extern unsigned long __COHERENT_RAM_END__;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The next 2 constants identify the extents of the code & RO data region.
|
||||||
|
* These addresses are used by the MMU setup code and therefore they must be
|
||||||
|
* page-aligned. It is the responsibility of the linker script to ensure that
|
||||||
|
* __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses.
|
||||||
|
*/
|
||||||
|
#define 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__)
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Reference to structure which holds the arguments that have been passed to
|
||||||
|
* BL31 from BL2.
|
||||||
|
******************************************************************************/
|
||||||
|
static bl31_args *bl2_to_bl31_args;
|
||||||
|
|
||||||
|
meminfo *bl31_plat_sec_mem_layout(void)
|
||||||
|
{
|
||||||
|
return &bl2_to_bl31_args->bl31_meminfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
meminfo *bl31_plat_get_bl32_mem_layout(void)
|
||||||
|
{
|
||||||
|
return &bl2_to_bl31_args->bl32_meminfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Return a pointer to the 'el_change_info' structure of the next image for the
|
||||||
|
* security state specified. BL33 corresponds to the non-secure image type
|
||||||
|
* while BL32 corresponds to the secure image type. A NULL pointer is returned
|
||||||
|
* if the image does not exist.
|
||||||
|
******************************************************************************/
|
||||||
|
el_change_info *bl31_get_next_image_info(uint32_t type)
|
||||||
|
{
|
||||||
|
el_change_info *next_image_info;
|
||||||
|
|
||||||
|
next_image_info = (type == NON_SECURE) ?
|
||||||
|
&bl2_to_bl31_args->bl33_image_info :
|
||||||
|
&bl2_to_bl31_args->bl32_image_info;
|
||||||
|
|
||||||
|
/* None of the images on this platform can have 0x0 as the entrypoint */
|
||||||
|
if (next_image_info->entrypoint)
|
||||||
|
return next_image_info;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Perform any BL31 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. On the FVP
|
||||||
|
* we know that BL2 has populated the parameters in secure DRAM. So we just use
|
||||||
|
* the reference passed in 'from_bl2' instead of copying. The 'data' parameter
|
||||||
|
* is not used since all the information is contained in 'from_bl2'. Also, BL2
|
||||||
|
* has flushed this information to memory, so we are guaranteed to pick up good
|
||||||
|
* data
|
||||||
|
******************************************************************************/
|
||||||
|
void bl31_early_platform_setup(bl31_args *from_bl2,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
bl2_to_bl31_args = from_bl2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Initialize the gic, configure the CLCD and zero out variables needed by the
|
||||||
|
* secondaries to boot up correctly.
|
||||||
|
******************************************************************************/
|
||||||
|
void bl31_platform_setup()
|
||||||
|
{
|
||||||
|
/* Initialize the gic cpu and distributor interfaces */
|
||||||
|
gic_setup();
|
||||||
|
|
||||||
|
/* 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(&bl2_to_bl31_args->bl31_meminfo,
|
||||||
|
BL31_RO_BASE,
|
||||||
|
BL31_RO_LIMIT,
|
||||||
|
BL31_COHERENT_RAM_BASE,
|
||||||
|
BL31_COHERENT_RAM_LIMIT);
|
||||||
|
}
|
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdint.h>
|
||||||
|
#include <arch_helpers.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <gic.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* TODO: Revisit if priorities are being set such that no non-secure interrupt
|
||||||
|
* can have a higher priority than a secure one as recommended in the GICv2 spec
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function does some minimal GICv3 configuration. The Firmware itself does
|
||||||
|
* not fully support GICv3 at this time and relies on GICv2 emulation as
|
||||||
|
* provided by GICv3. This function allows software (like Linux) in later stages
|
||||||
|
* to use full GICv3 features.
|
||||||
|
******************************************************************************/
|
||||||
|
void gicv3_cpuif_setup(void)
|
||||||
|
{
|
||||||
|
unsigned int scr_val, val;
|
||||||
|
uintptr_t base;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When CPUs come out of reset they have their GICR_WAKER.ProcessorSleep
|
||||||
|
* bit set. In order to allow interrupts to get routed to the CPU we
|
||||||
|
* need to clear this bit if set and wait for GICR_WAKER.ChildrenAsleep
|
||||||
|
* to clear (GICv3 Architecture specification 5.4.23).
|
||||||
|
* GICR_WAKER is NOT banked per CPU, compute the correct base address
|
||||||
|
* per CPU.
|
||||||
|
*/
|
||||||
|
base = gicv3_get_rdist(BASE_GICR_BASE, read_mpidr());
|
||||||
|
if (base == (uintptr_t)NULL) {
|
||||||
|
/* No re-distributor base address. This interface cannot be
|
||||||
|
* configured.
|
||||||
|
*/
|
||||||
|
panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
val = gicr_read_waker(base);
|
||||||
|
|
||||||
|
val &= ~WAKER_PS;
|
||||||
|
gicr_write_waker(base, val);
|
||||||
|
dsb();
|
||||||
|
|
||||||
|
/* We need to wait for ChildrenAsleep to clear. */
|
||||||
|
val = gicr_read_waker(base);
|
||||||
|
while (val & WAKER_CA) {
|
||||||
|
val = gicr_read_waker(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to set SCR_EL3.NS in order to see GICv3 non-secure state.
|
||||||
|
* Restore SCR_EL3.NS again before exit.
|
||||||
|
*/
|
||||||
|
scr_val = read_scr();
|
||||||
|
write_scr(scr_val | SCR_NS_BIT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default EL2 and NS-EL1 software should be able to enable GICv3
|
||||||
|
* System register access without any configuration at EL3. But it turns
|
||||||
|
* out that GICC PMR as set in GICv2 mode does not affect GICv3 mode. So
|
||||||
|
* we need to set it here again. In order to do that we need to enable
|
||||||
|
* register access. We leave it enabled as it should be fine and might
|
||||||
|
* prevent problems with later software trying to access GIC System
|
||||||
|
* Registers.
|
||||||
|
*/
|
||||||
|
val = read_icc_sre_el3();
|
||||||
|
write_icc_sre_el3(val | ICC_SRE_EN | ICC_SRE_SRE);
|
||||||
|
|
||||||
|
val = read_icc_sre_el2();
|
||||||
|
write_icc_sre_el2(val | ICC_SRE_EN | ICC_SRE_SRE);
|
||||||
|
|
||||||
|
write_icc_pmr_el1(GIC_PRI_MASK);
|
||||||
|
|
||||||
|
/* Restore SCR_EL3 */
|
||||||
|
write_scr(scr_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function does some minimal GICv3 configuration when cores go
|
||||||
|
* down.
|
||||||
|
******************************************************************************/
|
||||||
|
void gicv3_cpuif_deactivate(void)
|
||||||
|
{
|
||||||
|
unsigned int val;
|
||||||
|
uintptr_t base;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When taking CPUs down we need to set GICR_WAKER.ProcessorSleep and
|
||||||
|
* wait for GICR_WAKER.ChildrenAsleep to get set.
|
||||||
|
* (GICv3 Architecture specification 5.4.23).
|
||||||
|
* GICR_WAKER is NOT banked per CPU, compute the correct base address
|
||||||
|
* per CPU.
|
||||||
|
*/
|
||||||
|
base = gicv3_get_rdist(BASE_GICR_BASE, read_mpidr());
|
||||||
|
if (base == (uintptr_t)NULL) {
|
||||||
|
/* No re-distributor base address. This interface cannot be
|
||||||
|
* configured.
|
||||||
|
*/
|
||||||
|
panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
val = gicr_read_waker(base);
|
||||||
|
val |= WAKER_PS;
|
||||||
|
gicr_write_waker(base, val);
|
||||||
|
dsb();
|
||||||
|
|
||||||
|
/* We need to wait for ChildrenAsleep to set. */
|
||||||
|
val = gicr_read_waker(base);
|
||||||
|
while ((val & WAKER_CA) == 0) {
|
||||||
|
val = gicr_read_waker(base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
val = gicc_read_iidr(gicc_base);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If GICv3 we need to do a bit of additional setup. We want to
|
||||||
|
* allow default GICv2 behaviour but allow the next stage to
|
||||||
|
* enable full gicv3 features.
|
||||||
|
*/
|
||||||
|
if (((val >> GICC_IIDR_ARCH_SHIFT) & GICC_IIDR_ARCH_MASK) >= 3) {
|
||||||
|
gicv3_cpuif_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
val = ENABLE_GRP0 | FIQ_EN | FIQ_BYP_DIS_GRP0;
|
||||||
|
val |= IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1;
|
||||||
|
|
||||||
|
gicc_write_pmr(gicc_base, GIC_PRI_MASK);
|
||||||
|
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);
|
||||||
|
|
||||||
|
val = gicc_read_iidr(gicc_base);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If GICv3 we need to do a bit of additional setup. Make sure the
|
||||||
|
* RDIST is put to sleep.
|
||||||
|
*/
|
||||||
|
if (((val >> GICC_IIDR_ARCH_SHIFT) & GICC_IIDR_ARCH_MASK) >= 3) {
|
||||||
|
gicv3_cpuif_deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
gicd_write_igroupr(gicd_base, 0, ~0);
|
||||||
|
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_PHY_TIMER);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_0);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_1);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_2);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_3);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_4);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_5);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_6);
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_SEC_SGI_7);
|
||||||
|
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_PHY_TIMER);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_0);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_1);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_2);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_3);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_4);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_5);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_6);
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_SEC_SGI_7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.
|
||||||
|
******************************************************************************/
|
||||||
|
void gic_distif_setup(unsigned int gicd_base)
|
||||||
|
{
|
||||||
|
unsigned int ctr, num_ints, ctlr;
|
||||||
|
|
||||||
|
/* Disable the distributor before going further */
|
||||||
|
ctlr = gicd_read_ctlr(gicd_base);
|
||||||
|
ctlr &= ~(ENABLE_GRP0 | ENABLE_GRP1);
|
||||||
|
gicd_write_ctlr(gicd_base, ctlr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark out non-secure interrupts. Calculate number of
|
||||||
|
* IGROUPR registers to consider. Will be equal to the
|
||||||
|
* number of IT_LINES
|
||||||
|
*/
|
||||||
|
num_ints = gicd_read_typer(gicd_base) & IT_LINES_NO_MASK;
|
||||||
|
num_ints++;
|
||||||
|
for (ctr = 0; ctr < num_ints; ctr++)
|
||||||
|
gicd_write_igroupr(gicd_base, ctr << IGROUPR_SHIFT, ~0);
|
||||||
|
|
||||||
|
/* Configure secure interrupts now */
|
||||||
|
gicd_clr_igroupr(gicd_base, IRQ_TZ_WDOG);
|
||||||
|
gicd_set_ipriorityr(gicd_base, IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY);
|
||||||
|
gicd_set_itargetsr(gicd_base, IRQ_TZ_WDOG,
|
||||||
|
platform_get_core_pos(read_mpidr()));
|
||||||
|
gicd_set_isenabler(gicd_base, IRQ_TZ_WDOG);
|
||||||
|
gic_pcpu_distif_setup(gicd_base);
|
||||||
|
|
||||||
|
gicd_write_ctlr(gicd_base, ctlr | ENABLE_GRP0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gic_setup(void)
|
||||||
|
{
|
||||||
|
unsigned int gicd_base, gicc_base;
|
||||||
|
|
||||||
|
gicd_base = platform_get_cfgvar(CONFIG_GICD_ADDR);
|
||||||
|
gicc_base = platform_get_cfgvar(CONFIG_GICC_ADDR);
|
||||||
|
|
||||||
|
gic_cpuif_setup(gicc_base);
|
||||||
|
gic_distif_setup(gicd_base);
|
||||||
|
}
|
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
||||||
|
#include "platform.h"
|
||||||
|
#include "io_storage.h"
|
||||||
|
#include "io_driver.h"
|
||||||
|
#include "io_semihosting.h"
|
||||||
|
#include "semihosting.h" /* For FOPEN_MODE_... */
|
||||||
|
#include "io_fip.h"
|
||||||
|
#include "io_memmap.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
/* IO devices */
|
||||||
|
static struct io_plat_data io_data;
|
||||||
|
static struct io_dev_connector *sh_dev_con;
|
||||||
|
static void *const sh_dev_spec;
|
||||||
|
static void *const sh_init_params;
|
||||||
|
static io_dev_handle sh_dev_handle;
|
||||||
|
static struct io_dev_connector *fip_dev_con;
|
||||||
|
static void *const fip_dev_spec;
|
||||||
|
static io_dev_handle fip_dev_handle;
|
||||||
|
static struct io_dev_connector *memmap_dev_con;
|
||||||
|
static void *const memmap_dev_spec;
|
||||||
|
static void *const memmap_init_params;
|
||||||
|
static io_dev_handle memmap_dev_handle;
|
||||||
|
|
||||||
|
static io_block_spec fip_block_spec = {
|
||||||
|
.offset = FLASH0_BASE,
|
||||||
|
.length = FLASH0_SIZE
|
||||||
|
};
|
||||||
|
|
||||||
|
static io_file_spec bl2_file_spec = {
|
||||||
|
.path = BL2_IMAGE_NAME,
|
||||||
|
.mode = FOPEN_MODE_R
|
||||||
|
};
|
||||||
|
|
||||||
|
static io_file_spec bl31_file_spec = {
|
||||||
|
.path = BL31_IMAGE_NAME,
|
||||||
|
.mode = FOPEN_MODE_R
|
||||||
|
};
|
||||||
|
|
||||||
|
static io_file_spec bl33_file_spec = {
|
||||||
|
.path = BL33_IMAGE_NAME,
|
||||||
|
.mode = FOPEN_MODE_R
|
||||||
|
};
|
||||||
|
|
||||||
|
static int open_fip(void* spec);
|
||||||
|
static int open_memmap(void* spec);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char * image_name;
|
||||||
|
io_dev_handle* dev_handle;
|
||||||
|
void* image_spec;
|
||||||
|
int (*check)(void* spec);
|
||||||
|
} plat_io_policy;
|
||||||
|
|
||||||
|
static plat_io_policy policies[] = {
|
||||||
|
{ FIP_IMAGE_NAME, &memmap_dev_handle, &fip_block_spec, open_memmap },
|
||||||
|
{ BL2_IMAGE_NAME, &fip_dev_handle, &bl2_file_spec, open_fip },
|
||||||
|
{ BL31_IMAGE_NAME, &fip_dev_handle, &bl31_file_spec, open_fip },
|
||||||
|
{ BL33_IMAGE_NAME, &fip_dev_handle, &bl33_file_spec, open_fip },
|
||||||
|
{0,0,0}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int open_fip(void *spec)
|
||||||
|
{
|
||||||
|
int result = IO_FAIL;
|
||||||
|
|
||||||
|
/* See if a Firmware Image Package is available */
|
||||||
|
result = io_dev_init(fip_dev_handle, (void *)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(void *spec)
|
||||||
|
{
|
||||||
|
int result = IO_FAIL;
|
||||||
|
io_handle 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_semihosting(void *spec)
|
||||||
|
{
|
||||||
|
int result = IO_FAIL;
|
||||||
|
io_handle local_image_handle;
|
||||||
|
|
||||||
|
/* See if the file exists on semi-hosting.*/
|
||||||
|
result = io_dev_init(sh_dev_handle, sh_init_params);
|
||||||
|
if (result == IO_SUCCESS) {
|
||||||
|
result = io_open(sh_dev_handle, spec, &local_image_handle);
|
||||||
|
if (result == IO_SUCCESS) {
|
||||||
|
INFO("Using Semi-hosting IO\n");
|
||||||
|
io_close(local_image_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void io_setup (void)
|
||||||
|
{
|
||||||
|
int io_result = IO_FAIL;
|
||||||
|
|
||||||
|
/* Initialise the IO layer */
|
||||||
|
io_init(&io_data);
|
||||||
|
|
||||||
|
/* Register the IO devices on this platform */
|
||||||
|
io_result = register_io_dev_sh(&sh_dev_con);
|
||||||
|
assert(io_result == IO_SUCCESS);
|
||||||
|
|
||||||
|
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(sh_dev_con, sh_dev_spec, &sh_dev_handle);
|
||||||
|
assert(io_result == IO_SUCCESS);
|
||||||
|
|
||||||
|
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, io_dev_handle *dev_handle,
|
||||||
|
void **image_spec)
|
||||||
|
{
|
||||||
|
int result = IO_FAIL;
|
||||||
|
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) {
|
||||||
|
*(io_file_spec**)image_spec = policy->image_spec;
|
||||||
|
*dev_handle=*(policy->dev_handle);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
result = open_semihosting(policy->image_spec);
|
||||||
|
if (result == IO_SUCCESS) {
|
||||||
|
*dev_handle = sh_dev_handle;
|
||||||
|
*(io_file_spec **)image_spec = policy->image_spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
policy++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = IO_FAIL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdint.h>
|
||||||
|
#include <psci.h>
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Export the platform handlers to enable psci to invoke them
|
||||||
|
******************************************************************************/
|
||||||
|
static plat_pm_ops pm_ops = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Export the platform specific power ops & initialize the fvp power controller
|
||||||
|
******************************************************************************/
|
||||||
|
int platform_setup_pm(plat_pm_ops **plat_ops)
|
||||||
|
{
|
||||||
|
*plat_ops = &pm_ops;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
* 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 <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <fvp_pwrc.h>
|
||||||
|
/* TODO: Reusing psci error codes & state information. Get our own! */
|
||||||
|
#include <psci.h>
|
||||||
|
|
||||||
|
/* We treat '255' as an invalid affinity instance */
|
||||||
|
#define AFFINST_INVAL 0xff
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* We support 3 flavours of the FVP: Foundation, Base AEM & Base Cortex. Each
|
||||||
|
* flavour has a different topology. The common bit is that there can be a max.
|
||||||
|
* of 2 clusters (affinity 1) and 4 cpus (affinity 0) per cluster. So we define
|
||||||
|
* a tree like data structure which caters to these maximum bounds. It simply
|
||||||
|
* marks the absent affinity level instances as PSCI_AFF_ABSENT e.g. there is no
|
||||||
|
* cluster 1 on the Foundation FVP. The 'data' field is currently unused.
|
||||||
|
******************************************************************************/
|
||||||
|
typedef struct {
|
||||||
|
unsigned char sibling;
|
||||||
|
unsigned char child;
|
||||||
|
unsigned char state;
|
||||||
|
unsigned int data;
|
||||||
|
} affinity_info;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* The following two data structures store the topology tree for the fvp. There
|
||||||
|
* is a separate array for each affinity level i.e. cpus and clusters. The child
|
||||||
|
* and sibling references allow traversal inside and in between the two arrays.
|
||||||
|
******************************************************************************/
|
||||||
|
static affinity_info fvp_aff1_topology_map[PLATFORM_CLUSTER_COUNT];
|
||||||
|
static affinity_info fvp_aff0_topology_map[PLATFORM_CORE_COUNT];
|
||||||
|
|
||||||
|
/* Simple global variable to safeguard us from stupidity */
|
||||||
|
static unsigned int topology_setup_done;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function implements a part of the critical interface between the psci
|
||||||
|
* generic layer and the platform to allow the former to detect the platform
|
||||||
|
* topology. psci queries the platform to determine how many affinity instances
|
||||||
|
* are present at a particular level for a given mpidr e.g. consider a dual
|
||||||
|
* cluster platform where each cluster has 4 cpus. A call to this function with
|
||||||
|
* (0, 0x100) will return the number of cpus implemented under cluster 1 i.e. 4.
|
||||||
|
* Similarly a call with (1, 0x100) will return 2 i.e. the number of clusters.
|
||||||
|
* This is 'cause we are effectively asking how many affinity level 1 instances
|
||||||
|
* are implemented under affinity level 2 instance 0.
|
||||||
|
******************************************************************************/
|
||||||
|
unsigned int plat_get_aff_count(unsigned int aff_lvl,
|
||||||
|
unsigned long mpidr)
|
||||||
|
{
|
||||||
|
unsigned int aff_count = 1, ctr;
|
||||||
|
unsigned char parent_aff_id;
|
||||||
|
|
||||||
|
assert(topology_setup_done == 1);
|
||||||
|
|
||||||
|
switch (aff_lvl) {
|
||||||
|
case 3:
|
||||||
|
case 2:
|
||||||
|
/*
|
||||||
|
* Assert if the parent affinity instance is not 0.
|
||||||
|
* This also takes care of level 3 in an obfuscated way
|
||||||
|
*/
|
||||||
|
parent_aff_id = (mpidr >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||||
|
assert(parent_aff_id == 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Report that we implement a single instance of
|
||||||
|
* affinity levels 2 & 3 which are AFF_ABSENT
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* Assert if the parent affinity instance is not 0. */
|
||||||
|
parent_aff_id = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||||
|
assert(parent_aff_id == 0);
|
||||||
|
|
||||||
|
/* Fetch the starting index in the aff1 array */
|
||||||
|
for (ctr = 0;
|
||||||
|
fvp_aff1_topology_map[ctr].sibling != AFFINST_INVAL;
|
||||||
|
ctr = fvp_aff1_topology_map[ctr].sibling) {
|
||||||
|
aff_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/* Assert if the cluster id is anything apart from 0 or 1 */
|
||||||
|
parent_aff_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||||
|
assert(parent_aff_id < PLATFORM_CLUSTER_COUNT);
|
||||||
|
|
||||||
|
/* Fetch the starting index in the aff0 array */
|
||||||
|
for (ctr = fvp_aff1_topology_map[parent_aff_id].child;
|
||||||
|
fvp_aff0_topology_map[ctr].sibling != AFFINST_INVAL;
|
||||||
|
ctr = fvp_aff0_topology_map[ctr].sibling) {
|
||||||
|
aff_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aff_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function implements a part of the critical interface between the psci
|
||||||
|
* generic layer and the platform to allow the former to detect the state of a
|
||||||
|
* affinity instance in the platform topology. psci queries the platform to
|
||||||
|
* determine whether an affinity instance is present or absent. This caters for
|
||||||
|
* topologies where an intermediate affinity level instance is missing e.g.
|
||||||
|
* consider a platform which implements a single cluster with 4 cpus and there
|
||||||
|
* is another cpu sitting directly on the interconnect along with the cluster.
|
||||||
|
* The mpidrs of the cluster would range from 0x0-0x3. The mpidr of the single
|
||||||
|
* cpu would be 0x100 to highlight that it does not belong to cluster 0. Cluster
|
||||||
|
* 1 is however missing but needs to be accounted to reach this single cpu in
|
||||||
|
* the topology tree. Hence it will be marked as PSCI_AFF_ABSENT. This is not
|
||||||
|
* applicable to the FVP but depicted as an example.
|
||||||
|
******************************************************************************/
|
||||||
|
unsigned int plat_get_aff_state(unsigned int aff_lvl,
|
||||||
|
unsigned long mpidr)
|
||||||
|
{
|
||||||
|
unsigned int aff_state = PSCI_AFF_ABSENT, idx;
|
||||||
|
idx = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||||
|
|
||||||
|
assert(topology_setup_done == 1);
|
||||||
|
|
||||||
|
switch (aff_lvl) {
|
||||||
|
case 3:
|
||||||
|
case 2:
|
||||||
|
/* Report affinity levels 2 & 3 as absent */
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
aff_state = fvp_aff1_topology_map[idx].state;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
/*
|
||||||
|
* First get start index of the aff0 in its array & then add
|
||||||
|
* to it the affinity id that we want the state of
|
||||||
|
*/
|
||||||
|
idx = fvp_aff1_topology_map[idx].child;
|
||||||
|
idx += (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||||
|
aff_state = fvp_aff0_topology_map[idx].state;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aff_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Handy optimization to prevent the psci implementation from traversing through
|
||||||
|
* affinity levels which are not present while detecting the platform topology.
|
||||||
|
******************************************************************************/
|
||||||
|
int plat_get_max_afflvl()
|
||||||
|
{
|
||||||
|
return MPIDR_AFFLVL1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* This function populates the FVP specific topology information depending upon
|
||||||
|
* the FVP flavour its running on. We construct all the mpidrs we can handle
|
||||||
|
* and rely on the PWRC.PSYSR to flag absent cpus when their status is queried.
|
||||||
|
******************************************************************************/
|
||||||
|
int plat_setup_topology()
|
||||||
|
{
|
||||||
|
unsigned char aff0, aff1, aff_state, aff0_offset = 0;
|
||||||
|
unsigned long mpidr;
|
||||||
|
|
||||||
|
topology_setup_done = 0;
|
||||||
|
|
||||||
|
for (aff1 = 0; aff1 < PLATFORM_CLUSTER_COUNT; aff1++) {
|
||||||
|
|
||||||
|
fvp_aff1_topology_map[aff1].child = aff0_offset;
|
||||||
|
fvp_aff1_topology_map[aff1].sibling = aff1 + 1;
|
||||||
|
|
||||||
|
for (aff0 = 0; aff0 < PLATFORM_MAX_CPUS_PER_CLUSTER; aff0++) {
|
||||||
|
|
||||||
|
mpidr = aff1 << MPIDR_AFF1_SHIFT;
|
||||||
|
mpidr |= aff0 << MPIDR_AFF0_SHIFT;
|
||||||
|
|
||||||
|
if (fvp_pwrc_read_psysr(mpidr) != PSYSR_INVALID) {
|
||||||
|
/*
|
||||||
|
* Presence of even a single aff0 indicates
|
||||||
|
* presence of parent aff1 on the FVP.
|
||||||
|
*/
|
||||||
|
aff_state = PSCI_AFF_PRESENT;
|
||||||
|
fvp_aff1_topology_map[aff1].state =
|
||||||
|
PSCI_AFF_PRESENT;
|
||||||
|
} else {
|
||||||
|
aff_state = PSCI_AFF_ABSENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fvp_aff0_topology_map[aff0_offset].child = AFFINST_INVAL;
|
||||||
|
fvp_aff0_topology_map[aff0_offset].state = aff_state;
|
||||||
|
fvp_aff0_topology_map[aff0_offset].sibling =
|
||||||
|
aff0_offset + 1;
|
||||||
|
|
||||||
|
/* Increment the absolute number of aff0s traversed */
|
||||||
|
aff0_offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tie-off the last aff0 sibling to -1 to avoid overflow */
|
||||||
|
fvp_aff0_topology_map[aff0_offset - 1].sibling = AFFINST_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tie-off the last aff1 sibling to AFFINST_INVAL to avoid overflow */
|
||||||
|
fvp_aff1_topology_map[aff1 - 1].sibling = AFFINST_INVAL;
|
||||||
|
|
||||||
|
topology_setup_done = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,287 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PLATFORM_H__
|
||||||
|
#define __PLATFORM_H__
|
||||||
|
|
||||||
|
#include <arch.h>
|
||||||
|
#include <mmio.h>
|
||||||
|
#include <psci.h>
|
||||||
|
#include <bl_common.h>
|
||||||
|
#include "io_storage.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform binary types for linking
|
||||||
|
******************************************************************************/
|
||||||
|
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
|
||||||
|
#define PLATFORM_LINKER_ARCH aarch64
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Generic platform constants
|
||||||
|
******************************************************************************/
|
||||||
|
#define PLATFORM_STACK_SIZE 0x800
|
||||||
|
|
||||||
|
#define FIRMWARE_WELCOME_STR "Booting trusted firmware boot loader stage 1\n\r"
|
||||||
|
|
||||||
|
/* Trusted Boot Firmware BL2 */
|
||||||
|
#define BL2_IMAGE_NAME "bl2.bin"
|
||||||
|
|
||||||
|
/* EL3 Runtime Firmware BL31 */
|
||||||
|
#define BL31_IMAGE_NAME "bl31.bin"
|
||||||
|
|
||||||
|
/* Secure Payload BL32 (Trusted OS) */
|
||||||
|
#define BL32_IMAGE_NAME "bl32.bin"
|
||||||
|
|
||||||
|
/* Non-Trusted Firmware BL33 and its load address */
|
||||||
|
#define BL33_IMAGE_NAME "bl33.bin" /* e.g. UEFI */
|
||||||
|
#define NS_IMAGE_OFFSET (DRAM_BASE + 0x8000000) /* DRAM + 128MB */
|
||||||
|
|
||||||
|
/* Firmware Image Package */
|
||||||
|
#define FIP_IMAGE_NAME "fip.bin"
|
||||||
|
|
||||||
|
#define PLATFORM_CACHE_LINE_SIZE 64
|
||||||
|
#define PLATFORM_CLUSTER_COUNT 2ull
|
||||||
|
#define PLATFORM_CLUSTER0_CORE_COUNT 4
|
||||||
|
#define PLATFORM_CLUSTER1_CORE_COUNT 4
|
||||||
|
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
|
||||||
|
PLATFORM_CLUSTER0_CORE_COUNT)
|
||||||
|
#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
|
||||||
|
#define PRIMARY_CPU 0x0
|
||||||
|
#define MAX_IO_DEVICES 3
|
||||||
|
#define MAX_IO_HANDLES 4
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform memory map related constants
|
||||||
|
******************************************************************************/
|
||||||
|
#define TZROM_BASE 0x00000000
|
||||||
|
#define TZROM_SIZE 0x04000000
|
||||||
|
|
||||||
|
#define TZRAM_BASE 0x04000000
|
||||||
|
#define TZRAM_SIZE 0x40000
|
||||||
|
|
||||||
|
#define FLASH0_BASE 0x08000000
|
||||||
|
#define FLASH0_SIZE TZROM_SIZE
|
||||||
|
|
||||||
|
#define FLASH1_BASE 0x0c000000
|
||||||
|
#define FLASH1_SIZE 0x04000000
|
||||||
|
|
||||||
|
#define PSRAM_BASE 0x14000000
|
||||||
|
#define PSRAM_SIZE 0x04000000
|
||||||
|
|
||||||
|
#define VRAM_BASE 0x18000000
|
||||||
|
#define VRAM_SIZE 0x02000000
|
||||||
|
|
||||||
|
/* Aggregate of all devices in the first GB */
|
||||||
|
#define DEVICE0_BASE 0x1a000000
|
||||||
|
#define DEVICE0_SIZE 0x12200000
|
||||||
|
|
||||||
|
#define DEVICE1_BASE 0x2f000000
|
||||||
|
#define DEVICE1_SIZE 0x200000
|
||||||
|
|
||||||
|
#define NSRAM_BASE 0x2e000000
|
||||||
|
#define NSRAM_SIZE 0x10000
|
||||||
|
|
||||||
|
/* Location of trusted dram on the base fvp */
|
||||||
|
#define TZDRAM_BASE 0x06000000
|
||||||
|
#define TZDRAM_SIZE 0x02000000
|
||||||
|
#define MBOX_OFF 0x1000
|
||||||
|
#define AFFMAP_OFF 0x1200
|
||||||
|
|
||||||
|
#define DRAM_BASE 0x80000000ull
|
||||||
|
#define DRAM_SIZE 0x80000000ull
|
||||||
|
|
||||||
|
#define PCIE_EXP_BASE 0x40000000
|
||||||
|
#define TZRNG_BASE 0x7fe60000
|
||||||
|
#define TZNVCTR_BASE 0x7fe70000
|
||||||
|
#define TZROOTKEY_BASE 0x7fe80000
|
||||||
|
|
||||||
|
/* Memory mapped Generic timer interfaces */
|
||||||
|
#define SYS_CNTCTL_BASE 0x2a430000
|
||||||
|
|
||||||
|
/* Counter timer module offsets */
|
||||||
|
#define CNTNSAR 0x4
|
||||||
|
#define CNTNSAR_NS_SHIFT(x) x
|
||||||
|
|
||||||
|
#define CNTACR_BASE(x) (0x40 + (x << 2))
|
||||||
|
#define CNTACR_RPCT_SHIFT 0x0
|
||||||
|
#define CNTACR_RVCT_SHIFT 0x1
|
||||||
|
#define CNTACR_RFRQ_SHIFT 0x2
|
||||||
|
#define CNTACR_RVOFF_SHIFT 0x3
|
||||||
|
#define CNTACR_RWVT_SHIFT 0x4
|
||||||
|
#define CNTACR_RWPT_SHIFT 0x5
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* BL2 specific defines.
|
||||||
|
******************************************************************************/
|
||||||
|
#define BL2_BASE 0x0402D000
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* BL31 specific defines.
|
||||||
|
******************************************************************************/
|
||||||
|
#define BL31_BASE 0x0400C000
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Platform specific page table and MMU setup constants
|
||||||
|
******************************************************************************/
|
||||||
|
#define EL3_ADDR_SPACE_SIZE (1ull << 32)
|
||||||
|
#define EL3_NUM_PAGETABLES 2
|
||||||
|
#define EL3_TROM_PAGETABLE 0
|
||||||
|
#define EL3_TRAM_PAGETABLE 1
|
||||||
|
|
||||||
|
#define ADDR_SPACE_SIZE (1ull << 32)
|
||||||
|
|
||||||
|
#define NUM_L2_PAGETABLES 2
|
||||||
|
#define GB1_L2_PAGETABLE 0
|
||||||
|
#define GB2_L2_PAGETABLE 1
|
||||||
|
|
||||||
|
#define NUM_L3_PAGETABLES 2
|
||||||
|
#define TZRAM_PAGETABLE 0
|
||||||
|
#define NSRAM_PAGETABLE 1
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* CCI-400 related constants
|
||||||
|
******************************************************************************/
|
||||||
|
#define CCI400_BASE 0x2c090000
|
||||||
|
#define CCI400_SL_IFACE_CLUSTER0 3
|
||||||
|
#define CCI400_SL_IFACE_CLUSTER1 4
|
||||||
|
#define CCI400_SL_IFACE_INDEX(mpidr) (mpidr & MPIDR_CLUSTER_MASK ? \
|
||||||
|
CCI400_SL_IFACE_CLUSTER1 : \
|
||||||
|
CCI400_SL_IFACE_CLUSTER0)
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* GIC-400 & interrupt handling related constants
|
||||||
|
******************************************************************************/
|
||||||
|
/* VE compatible GIC memory map */
|
||||||
|
#define VE_GICD_BASE 0x2c001000
|
||||||
|
#define VE_GICC_BASE 0x2c002000
|
||||||
|
#define VE_GICH_BASE 0x2c004000
|
||||||
|
#define VE_GICV_BASE 0x2c006000
|
||||||
|
|
||||||
|
/* Base FVP compatible GIC memory map */
|
||||||
|
#define BASE_GICD_BASE 0x2f000000
|
||||||
|
#define BASE_GICR_BASE 0x2f100000
|
||||||
|
#define BASE_GICC_BASE 0x2c000000
|
||||||
|
#define BASE_GICH_BASE 0x2c010000
|
||||||
|
#define BASE_GICV_BASE 0x2c02f000
|
||||||
|
|
||||||
|
#define IRQ_TZ_WDOG 56
|
||||||
|
#define IRQ_SEC_PHY_TIMER 29
|
||||||
|
#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
|
||||||
|
******************************************************************************/
|
||||||
|
#define PL011_UART0_BASE 0x1c090000
|
||||||
|
#define PL011_UART1_BASE 0x1c0a0000
|
||||||
|
#define PL011_UART2_BASE 0x1c0b0000
|
||||||
|
#define PL011_UART3_BASE 0x1c0c0000
|
||||||
|
#define PL011_BASE PL011_UART0_BASE
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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)
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
typedef volatile struct {
|
||||||
|
unsigned long value
|
||||||
|
__attribute__((__aligned__(CACHE_WRITEBACK_GRANULE)));
|
||||||
|
} mailbox;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Function and variable prototypes
|
||||||
|
******************************************************************************/
|
||||||
|
extern unsigned long *bl1_normal_ram_base;
|
||||||
|
extern unsigned long *bl1_normal_ram_len;
|
||||||
|
extern unsigned long *bl1_normal_ram_limit;
|
||||||
|
extern unsigned long *bl1_normal_ram_zi_base;
|
||||||
|
extern unsigned long *bl1_normal_ram_zi_len;
|
||||||
|
|
||||||
|
extern unsigned long *bl1_coherent_ram_base;
|
||||||
|
extern unsigned long *bl1_coherent_ram_len;
|
||||||
|
extern unsigned long *bl1_coherent_ram_limit;
|
||||||
|
extern unsigned long *bl1_coherent_ram_zi_base;
|
||||||
|
extern unsigned long *bl1_coherent_ram_zi_len;
|
||||||
|
extern unsigned long warm_boot_entrypoint;
|
||||||
|
|
||||||
|
extern void bl1_plat_arch_setup(void);
|
||||||
|
extern void bl2_plat_arch_setup(void);
|
||||||
|
extern void bl31_plat_arch_setup(void);
|
||||||
|
extern int platform_setup_pm(plat_pm_ops **);
|
||||||
|
extern unsigned int platform_get_core_pos(unsigned long mpidr);
|
||||||
|
extern void disable_mmu(void);
|
||||||
|
extern void enable_mmu(void);
|
||||||
|
extern void configure_mmu(meminfo *,
|
||||||
|
unsigned long,
|
||||||
|
unsigned long,
|
||||||
|
unsigned long,
|
||||||
|
unsigned long);
|
||||||
|
extern void plat_report_exception(unsigned long);
|
||||||
|
extern unsigned long plat_get_ns_image_entrypoint(void);
|
||||||
|
extern unsigned long platform_get_stack(unsigned long mpidr);
|
||||||
|
|
||||||
|
/* Declarations for fvp_gic.c */
|
||||||
|
extern void gic_cpuif_deactivate(unsigned int);
|
||||||
|
extern void gic_cpuif_setup(unsigned int);
|
||||||
|
extern void gic_pcpu_distif_setup(unsigned int);
|
||||||
|
extern void gic_setup(void);
|
||||||
|
|
||||||
|
/* Declarations for fvp_topology.c */
|
||||||
|
extern int plat_setup_topology(void);
|
||||||
|
extern int plat_get_max_afflvl(void);
|
||||||
|
extern unsigned int plat_get_aff_count(unsigned int, unsigned long);
|
||||||
|
extern unsigned int plat_get_aff_state(unsigned int, unsigned long);
|
||||||
|
|
||||||
|
/* Declarations for plat_io_storage.c */
|
||||||
|
extern void io_setup(void);
|
||||||
|
extern int plat_get_image_source(const char *image_name,
|
||||||
|
io_dev_handle *dev_handle, void **image_spec);
|
||||||
|
|
||||||
|
#endif /*__ASSEMBLY__*/
|
||||||
|
|
||||||
|
#endif /* __PLATFORM_H__ */
|
|
@ -0,0 +1,87 @@
|
||||||
|
#
|
||||||
|
# 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 := -Idrivers/arm/interconnect/cci-400 \
|
||||||
|
-Idrivers/arm/peripherals/pl011 \
|
||||||
|
-Idrivers/power
|
||||||
|
|
||||||
|
PLAT_BL1_C_VPATH := drivers/arm/interconnect/cci-400 \
|
||||||
|
drivers/arm/peripherals/pl011 \
|
||||||
|
lib/semihosting \
|
||||||
|
lib/stdlib \
|
||||||
|
drivers/io
|
||||||
|
|
||||||
|
PLAT_BL1_S_VPATH := lib/semihosting/${ARCH}
|
||||||
|
|
||||||
|
PLAT_BL2_C_VPATH := drivers/arm/interconnect/cci-400 \
|
||||||
|
drivers/arm/peripherals/pl011 \
|
||||||
|
lib/stdlib \
|
||||||
|
lib/semihosting \
|
||||||
|
drivers/io
|
||||||
|
|
||||||
|
PLAT_BL2_S_VPATH := lib/semihosting/${ARCH}
|
||||||
|
|
||||||
|
PLAT_BL31_C_VPATH := drivers/arm/interconnect/cci-400 \
|
||||||
|
drivers/arm/peripherals/pl011 \
|
||||||
|
lib/semihosting \
|
||||||
|
lib/stdlib \
|
||||||
|
drivers/power \
|
||||||
|
drivers/io
|
||||||
|
|
||||||
|
PLAT_BL31_S_VPATH := lib/semihosting/${ARCH}
|
||||||
|
|
||||||
|
PLAT_BL_COMMON_SOURCES := semihosting_call.S \
|
||||||
|
mmio.c \
|
||||||
|
pl011.c \
|
||||||
|
semihosting.c \
|
||||||
|
sysreg_helpers.S \
|
||||||
|
plat_io_storage.c \
|
||||||
|
io_semihosting.c \
|
||||||
|
io_fip.c \
|
||||||
|
io_memmap.c
|
||||||
|
|
||||||
|
BL1_SOURCES += bl1_plat_setup.c \
|
||||||
|
bl1_plat_helpers.S \
|
||||||
|
plat_helpers.S \
|
||||||
|
plat_common.c \
|
||||||
|
cci400.c
|
||||||
|
|
||||||
|
BL2_SOURCES += bl2_plat_setup.c \
|
||||||
|
plat_common.c
|
||||||
|
|
||||||
|
BL31_SOURCES += bl31_plat_setup.c \
|
||||||
|
plat_helpers.S \
|
||||||
|
plat_common.c \
|
||||||
|
plat_pm.c \
|
||||||
|
plat_topology.c \
|
||||||
|
plat_gic.c \
|
||||||
|
cci400.c \
|
||||||
|
gic_v2.c \
|
||||||
|
gic_v3.c
|
Loading…
Reference in New Issue